Skip to content

Commit

Permalink
v0.9.0 (#38)
Browse files Browse the repository at this point in the history
  • Loading branch information
romandres authored Apr 18, 2023
1 parent d76e1df commit ac79002
Show file tree
Hide file tree
Showing 15 changed files with 321 additions and 200 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/reusable_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ jobs:
shell: pwsh

- name: Copy files to artifact directory
run: Copy-Item -Path "publish/*" -Destination "../artifact/psstreamlogger" -Include @("*.dll", "*.psd1", "*.psm1")
run: |
Copy-Item -Path "publish/*" -Destination "../artifact/psstreamlogger" -Include @("*.dll", "*.dll-Help.xml", "*.psd1", "*.psm1")
Copy-Item -Path "src/PSStreamLogger/bin/Release/${{ inputs.targetFramework }}/*" -Destination "../artifact/psstreamlogger" -Include @("*.dll-Help.xml")
shell: pwsh

- name: Set module version in manifest
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/reusable_publish_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ jobs:

- name: Arrange manifest files
run: |
Move-Item -Path "./module/coreclr/*" -Destination "./module" -Include @("*.psm1", "*.psd1")
Remove-Item -Path "./module/fullclr/*" -Include @("*.psm1", "*.psd1")
Move-Item -Path "./module/fullclr/*" -Destination "./module" -Include @("*.psm1", "*.psd1", "*.dll-Help.xml")
Remove-Item -Path "./module/coreclr/*" -Include @("*.psm1", "*.psd1", "*.dll-Help.xml")
shell: pwsh

- name: Create archive
Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<!--Version-->
<VersionPrefix>0.8.0</VersionPrefix>
<VersionPrefix>0.9.0</VersionPrefix>

<!--Metadata-->
<Authors>romandres</Authors>
Expand Down
40 changes: 34 additions & 6 deletions src/PSStreamLogger/Cmdlets/InvokeCommandWithLoggingCmdlet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,37 @@

namespace PSStreamLoggerModule
{

/// <summary>
/// <para type="synopsis">Executes a command and logs PowerShell stream output.</para>
/// <para type="description">Executes a command and sends data written into PowerShell streams (Verbose, Debug, Information, Warning, Error) as log events to the configured loggers.</para>
/// <para type="description">Output is passed through.</para>
/// <para type="type">Cmdlet</para>
/// </summary>
[Cmdlet(VerbsLifecycle.Invoke, "CommandWithLogging")]
public class InvokeCommandWithLoggingCmdlet : PSCmdlet, IDisposable
{
/// <summary>
/// <para type="description">The script block to execute.</para>
/// </summary>
[Parameter(Mandatory = true)]
public ScriptBlock? ScriptBlock { get; set; }

/// <summary>
/// <para type="description">The loggers to send log events to. If no loggers are configured, a console logger with minimum log level information will be used.</para>
/// </summary>
[Parameter()]
public Logger[]? Loggers { get; set; }

/// <summary>
/// <para type="description">The mode to execute the script block in. NewScope executes the script block in a new scope (default), CurrentScope executes it in the current scope (in the same scope this Cmdlet is executed from) and NewRunspace executes it in a new PowerShell runspace.</para>
/// </summary>
[Parameter]
public RunMode RunMode { get; set; } = RunMode.NewScope;
public ExecutionMode ExecutionMode { get; set; } = ExecutionMode.NewScope;

/// <summary>
/// <para type="description">Disable the automatic PowerShell stream configuration. based on the lowest log level.</para>
/// <para type="description">By default the PowerShell streams are configured based on the lowest log level across all loggers.</para>
/// </summary>
[Parameter]
public SwitchParameter DisableStreamConfiguration { get; set; }

Expand Down Expand Up @@ -56,8 +74,13 @@ protected virtual void Dispose(bool disposing)
{
foreach (var logger in Loggers)
{
logger.SerilogLogger.Dispose();
logger.SerilogLogger?.Dispose();
logger.SerilogLogger = null;
}

#if DEBUG
Console.WriteLine("DEBUG: Disposed loggers");
#endif
}

powerShellExecutor?.Dispose();
Expand All @@ -78,7 +101,7 @@ protected override void EndProcessing()

var streamConfiguration = !DisableStreamConfiguration.IsPresent ? new PSStreamConfiguration(minimumLogLevel) : null;

if (RunMode != RunMode.NewRunspace)
if (ExecutionMode != ExecutionMode.NewRunspace)
{
StringBuilder logLevelCommandBuilder = new StringBuilder();

Expand All @@ -92,7 +115,7 @@ protected override void EndProcessing()

exec = () =>
{
return InvokeCommand.InvokeScript($"{logLevelCommandBuilder}& {{ {ScriptBlock} {Environment.NewLine}}} *>&1 | PSStreamLogger\\Out-PSStreamLogger -DataRecordLogger $input[0]", RunMode == RunMode.NewScope, PipelineResultTypes.Output, new List<object>() { dataRecordLogger! });
return InvokeCommand.InvokeScript($"{logLevelCommandBuilder}& {{ {ScriptBlock} {Environment.NewLine}}} *>&1 | PSStreamLogger\\Out-PSStreamLogger -DataRecordLogger $input[0]", ExecutionMode == ExecutionMode.NewScope, PipelineResultTypes.Output, new List<object>() { dataRecordLogger! });
};
}
else
Expand Down Expand Up @@ -131,6 +154,11 @@ private void PrepareLogging()

foreach (var logger in Loggers!)
{
if (logger.SerilogLogger is null)
{
throw new InvalidOperationException($"Logger {logger.Name} was disposed and cannot be reused");
}

if (logger.MinimumLogLevel < minimumLogLevel)
{
minimumLogLevel = logger.MinimumLogLevel;
Expand All @@ -140,7 +168,7 @@ private void PrepareLogging()
}

scriptLogger = loggerFactory.CreateLogger("PSScriptBlock");
dataRecordLogger = new DataRecordLogger(scriptLogger, RunMode == RunMode.NewRunspace ? 0 : 2);
dataRecordLogger = new DataRecordLogger(scriptLogger, ExecutionMode == ExecutionMode.NewRunspace ? 0 : 2);
}
}
}
9 changes: 6 additions & 3 deletions src/PSStreamLogger/Cmdlets/Loggers/Logger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@ public class Logger

public static readonly string DefaultExpressionTemplate = $"[{{@t:yyyy-MM-dd HH:mm:ss.fffzz}} {{@l:u3}}] {{@m:lj}}{Environment.NewLine}{{{DataRecordLogger.PSErrorDetailsKey}}}";

public Logger(Serilog.Events.LogEventLevel minimumLogLevel, Serilog.Core.Logger serilogLogger)
public Logger(Serilog.Events.LogEventLevel minimumLogLevel, Serilog.Core.Logger serilogLogger, string name)
{
MinimumLogLevel = minimumLogLevel;
SerilogLogger = serilogLogger;
Name = $"{name}_{Guid.NewGuid()}";
}


public string Name { get; private set; }

internal Serilog.Events.LogEventLevel MinimumLogLevel { get; private set; }

public Serilog.Core.Logger SerilogLogger { get; private set; }
internal Serilog.Core.Logger? SerilogLogger { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,28 @@

namespace PSStreamLoggerModule
{
[Cmdlet(VerbsCommon.New, "AzureApplicationInsightsLogger")]
public class NewAzureApplicationInsightsLogger : PSCmdlet
/// <summary>
/// <para type="synopsis">Creates a new logger that writes log events to an Azure Application Insights instance.</para>
/// <para type="description">A logger based on the Serilog.Sinks.ApplicationInsights that writes log events to an Azure Application Insights instance.</para>
/// <para type="type">Cmdlet</para>
/// </summary>
[Cmdlet(VerbsCommon.New, Name)]
public class NewAzureApplicationInsightsLogger : NewLoggerCmdlet
{
private const string Name = "AzureApplicationInsightsLogger";

/// <summary>
/// <para type="description">The connection string for the target Azure Application Insights instance.</para>
/// </summary>
[Parameter(Mandatory = true)]
public string? ConnectionString { get; set; }

/// <summary>
/// <para type="description">An optional hashtable containing additional properties to add to each log event (key = log property name, value = log property value).</para>
/// </summary>
[Parameter()]
public Hashtable? Properties { get; set; }

[Parameter()]
public string? FilterIncludeOnlyExpression { get; set; }

[Parameter()]
public string? FilterExcludeExpression { get; set; }

[Parameter()]
public Serilog.Events.LogEventLevel MinimumLogLevel { get; set; } = Logger.DefaultMinimumLogLevel;

protected override void EndProcessing()
{
var loggerConfiguration = new Serilog.LoggerConfiguration()
Expand All @@ -52,7 +56,7 @@ protected override void EndProcessing()
.Filter.ByExcluding(FilterExcludeExpression);
}

WriteObject(new Logger(MinimumLogLevel, loggerConfiguration.CreateLogger()));
WriteObject(new Logger(MinimumLogLevel, loggerConfiguration.CreateLogger(), Name));
}
}
}
31 changes: 13 additions & 18 deletions src/PSStreamLogger/Cmdlets/Loggers/NewConsoleLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,16 @@

namespace PSStreamLoggerModule
{
[Cmdlet(VerbsCommon.New, "ConsoleLogger")]
public class NewConsoleLogger : PSCmdlet
/// <summary>
/// <para type="synopsis">Creates a new console logger that writes log events to the console.</para>
/// <para type="description">A logger based on the Serilog.Sinks.Console that writes log events to the console via standard output.</para>
/// <para type="type">Cmdlet</para>
/// </summary>
[Cmdlet(VerbsCommon.New, Name)]
public class NewConsoleLogger : NewTextLoggerCmldet
{
[Parameter()]
public string ExpressionTemplate { get; set; } = Logger.DefaultExpressionTemplate;

[Parameter()]
public string? FilterIncludeOnlyExpression { get; set; }

[Parameter()]
public string? FilterExcludeExpression { get; set; }

[Parameter()]
public Serilog.Events.LogEventLevel MinimumLogLevel { get; set; } = Logger.DefaultMinimumLogLevel;

private const string Name = "ConsoleLogger";

protected override void EndProcessing()
{
var loggerConfiguration = CreateLoggerConfiguration(ExpressionTemplate, MinimumLogLevel);
Expand All @@ -37,10 +32,10 @@ protected override void EndProcessing()
.Filter.ByExcluding(FilterExcludeExpression);
}

WriteObject(new Logger(MinimumLogLevel, loggerConfiguration.CreateLogger()));
WriteObject(new Logger(MinimumLogLevel, loggerConfiguration.CreateLogger(), Name));
}

public static LoggerConfiguration CreateLoggerConfiguration(string expressionTemplate, LogEventLevel minimumLogLevel)
private static LoggerConfiguration CreateLoggerConfiguration(string expressionTemplate, LogEventLevel minimumLogLevel)
{
return new Serilog.LoggerConfiguration()
.MinimumLevel.Is(minimumLogLevel)
Expand All @@ -50,12 +45,12 @@ public static LoggerConfiguration CreateLoggerConfiguration(string expressionTem
.Enrich.FromLogContext();
}

public static Logger CreateDefaultLogger()
internal static Logger CreateDefaultLogger()
{
var minimumLogLevel = Logger.DefaultMinimumLogLevel;

var loggerConfiguration = CreateLoggerConfiguration(Logger.DefaultExpressionTemplate, Logger.DefaultMinimumLogLevel);
return new Logger(minimumLogLevel, loggerConfiguration.CreateLogger());
return new Logger(minimumLogLevel, loggerConfiguration.CreateLogger(), Name);
}
}
}
49 changes: 30 additions & 19 deletions src/PSStreamLogger/Cmdlets/Loggers/NewEventLogLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,47 @@

namespace PSStreamLoggerModule
{
[Cmdlet(VerbsCommon.New, "EventLogLogger")]
public class NewEventLogLogger : PSCmdlet
/// <summary>
/// <para type="synopsis">Creates a new event log logger that writes log events to a Windows EventLog.</para>
/// <para type="description">A logger based on the Serilog.Sinks.EventLog that writes log events to a Windows EventLog.</para>
/// <para type="type">Cmdlet</para>
/// </summary>
[Cmdlet(VerbsCommon.New, Name)]
public class NewEventLogLogger : NewTextLoggerCmldet
{
private const string Name = "EventLogLogger";

public NewEventLogLogger()
{
ExpressionTemplate = $"{{@m:lj}}{Environment.NewLine}{{{DataRecordLogger.PSErrorDetailsKey}}}";
}

/// <summary>
/// <para type="description">The event source that is typically name of the application/program writing log events to the event log.</para>
/// <para type="description">The logger will not create the event source. The event source has to exist for the logger to work (can be created with elevated privileges using New-EventLog).</para>
/// </summary>
[Parameter(Mandatory = true)]
public string? LogSource { get; set; }
public string? Source { get; set; }

/// <summary>
/// <para type="description">The name of the target event log to which log events are written.</para>
/// <para type="description">The logger will not create the event log. The event log has to exist for the logger to work (can be created with elevated privileges using New-EventLog).</para>
/// </summary>
[Parameter()]
public string? LogName { get; set; }

[Parameter()]
public string ExpressionTemplate { get; set; } = $"{{@m:lj}}{Environment.NewLine}{{{DataRecordLogger.PSErrorDetailsKey}}}";

[Parameter()]
public string? FilterIncludeOnlyExpression { get; set; }

[Parameter()]
public string? FilterExcludeExpression { get; set; }


/// <summary>
/// <para type="description">A script block that provides the event ID for each log event based on the log event's properties.</para>
/// </summary>
[Parameter()]
public ScriptBlock? EventIdProvider { get; set; }

[Parameter()]
public Serilog.Events.LogEventLevel MinimumLogLevel { get; set; } = Logger.DefaultMinimumLogLevel;


protected override void EndProcessing()
{
var loggerConfiguration = new Serilog.LoggerConfiguration()
.MinimumLevel.Is(MinimumLogLevel)
.WriteTo.EventLog(
source: LogSource,
source: Source,
logName: LogName,
formatter: new ExpressionTemplate(template: ExpressionTemplate, formatProvider: CultureInfo.CurrentCulture),
restrictedToMinimumLevel: MinimumLogLevel,
Expand All @@ -56,7 +67,7 @@ protected override void EndProcessing()
.Filter.ByExcluding(FilterExcludeExpression);
}

WriteObject(new Logger(MinimumLogLevel, loggerConfiguration.CreateLogger()));
WriteObject(new Logger(MinimumLogLevel, loggerConfiguration.CreateLogger(), Name));
}
}
}
Loading

0 comments on commit ac79002

Please sign in to comment.