Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PSFLoggingProvider template produced with Invoke-PSMDTemplate is a version_1 template #485

Open
ayprof opened this issue May 3, 2021 · 5 comments

Comments

@ayprof
Copy link

ayprof commented May 3, 2021

Not sure if this is intended or not but I tried to create a custom logfile provider from the template (no problems there), but the provider produced is a version_1 provider, not version_2. I'm running into some issues converting it into a version_2 provider manually, and wondered if this isn't something that should be fixed.

To reproduce:
Invoke-PSMDTemplate PSFLoggingProvider -Name 'customProvider' -Module 'customModule'

@FriedrichWeinmann
Copy link
Member

Heya @ayprof ,

thanks for bringing that up and sorry for the inconvenience!
That definitely needs to be fixed, I've added an issue in the PSModuleDevelopment Repository because the templates belong to that one and that way I don't miss fixing that before the next release.
No solid ETA beyond soonish, still struggling to finish one feature upgrade for that (the templates getting a few new options and a fundamental improvement in how you can integrate logic during template processing). Issue is as always time and energy :(

That said, if you need help converting the logging provider and can share the code, I'll be happy to help and advise in the meantime.

@ayprof
Copy link
Author

ayprof commented May 19, 2021

No problem, thanks for the excellent work!

To start, maybe I should ask first whether my issue would be resolved by moving to a version2 provider. I have a script that is called via another script that runs it as a job. Both the script called and the script calling it log the results in separate logfiles. The first script updates a security group and then logs the changes in a logfile with the name of the security group and puts it in a folder also named after the security group. The script that creates the jobs per security group is called from a scheduled task. The configuration I'm using is below and is called at the beginning of the script:


$paramSetPSFLoggingProvider = @{
            Name          = 'LogFile'
            InstanceName  = "${groupLogName}"
            FilePath      = "C:\DynamicGroupLogging\${script:groupLogName}\${script:groupLogName}_%Date%.csv"
            Enabled       = $true
            Logname       = $groupLogName
            Headers       = 'Message','ModuleName','Tags','TargetObject','Timestamp','Type','Username','File','ComputerName','FunctionName','Level','Line','Runspace'
            LogRotatePath = "C:\DynamicGroupLogging\${script:groupLogName}\${script:groupLogName}*.csv"
        }
        Set-PSFLoggingProvider @paramSetPSFLoggingProvider

This works sometimes, but the rest of the time the groupLogName is truncated from the path, leaving logfiles that only include the date. I'm not sure why this works at first and then stops working a few days later.

I was really only shooting in the dark to see if moving to version2 would fix this issue but I really don't know. Any thoughts?

@FriedrichWeinmann
Copy link
Member

This is fundamentally independent of the provider versions.
That would only happen if the variable $groupLogName were missing somehow.
Note: Using three different notations to reference the same variable is probably not the most stable solution, I would recommend consolidating them all to $script:groupLogName

I could see this having issues when you mess around with scopes or dotsourcing, but generally those should still always behave the same, no matter how often you run them ...

Any chance you can share the full code you are using?

@ayprof
Copy link
Author

ayprof commented May 20, 2021

This is the code that gets ran as a scheduled task. It calls the Update-DynamicGroup function that contains the PSFramework configuration code that I already included in the previous post.

#Requires -Modules ActiveDirectory, PSFramework
function Start-DynamicGroupUpdate {

    <#
    .SYNOPSIS
    Creates jobs for each entry in JSON configuration file to update security groups dynamically

    .DESCRIPTION
    Uses jobs to run Update-DynamicGroup per object in JSON configuration file using the parameters therein to update a security groups dynamically

    .PARAMETER ConfigurationFile
    Loads a JSON-formatted file that contains the parameters that should be run against each security group using the Update-DynamicGroup function
    
    .EXAMPLE
    Start-DynamicGroupUpdate -ConfigurationFile .\Private\config\dynamicGroupsConfigTesting.json

    #>


    [CmdletBinding()]
    param(

        [Parameter(Mandatory=$true)]
        [String]$ConfigurationFile

    )


    $logname = 'jobLog'
    ## SET LOGGING PARAMETERS ##
    $paramSetPSFLoggingProvider = @{
        Name          = 'logfile'
        InstanceName  = "$logname"
        FilePath      = "C:\DynamicGroupLogging\${logname}\${logname}_%Date%.csv"
        FileType      = 'CSV'
        Enabled       = $true
        Logname       = $logname
        IncludeHeader = $true
        Encoding      = 'UTF8'
        Headers       = 'Message','ModuleName','Tags','TargetObject','Timestamp','Type','Username','File','ComputerName','FunctionName','Level','Line','Runspace'
        LogRotatePath = "C:\DynamicGroupLogging\${logname}\${logname}*.csv"
        CsvDelimiter  = ','
    }

    Set-PSFLoggingProvider @paramSetPSFLoggingProvider
    ## END LOGGING PARAMETERS ##

    try {
        $config = Get-Content -Path $ConfigurationFile | ConvertFrom-Json
        $jobLogs = New-Object -TypeName "System.Collections.ArrayList"
    }
    catch {
        Write-PSFMessage -Level Verbose -Message "Couldn't get configuration file.  Is the drive accessible or did the filename change?" -Tag 'Failure' -ErrorRecord $_
    }

    try {
        $config.securityGroup | ForEach-Object {
            $param = @{
                Group = $_.name
                Attribute = $_.specifiedAttribute
                OrganizationalUnit = $_.organizationalUnit
                SearchScope = $_.searchScope
                ExcludeDisabled = $_.ExcludeDisabled
                ExcludeWithoutSurname = $_.ExcludeWithoutSurname
                Confirm = $true
            }
            # Write-Output $param
            Write-PSFMessage -Message "Starting job to update the $($_.name) security group..."
            $script = [scriptBlock]::Create(
                @'
                    $param = $using:param
                    Update-DynamicGroup @param 
'@
            )
            $job = Start-Job -Name ($_.name + '-Job') -ScriptBlock $script
            Wait-Job -Name ($_.name + '-Job')
            $results = $job | Receive-Job -Keep
            Get-Job -Name ($_.name + '-Job') | Remove-Job
            [void]$jobLogs.Add($results)
            Write-PSFMessage -Message "Completed job $results"
        }
        Write-PSFMessage -Message "$jobLogs"
    }
    catch {
        Write-PSFMessage -Level Verbose -Message "Error running job: " -Tag 'Failure' -ErrorRecord $_
    }
}

@FriedrichWeinmann
Copy link
Member

Hm, is there a reason you are using jobs when you are waiting for them to complete anyway before moving on?
Runspaces might give you better performance and simplify the logging at the same time.
That said, nothing in this snippet contains anything that affects the logging in Update-DynamicGroup, which I'm assuming is part of another custom module on your machine.
The way you start the job - while creative - is unexceptional as far as scopes and execution of Update-DynamicGroup are concerned, so I don't see that being a problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants