Skip to content

Merge structured logging into dev in preparation for release #1803

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

Merged
merged 12 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Libraries/src/Amazon.Lambda.Core/Amazon.Lambda.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<TargetFrameworks>netstandard2.0;net6.0;net8.0</TargetFrameworks>
<Description>Amazon Lambda .NET Core support - Core package.</Description>
<AssemblyTitle>Amazon.Lambda.Core</AssemblyTitle>
<VersionPrefix>2.2.0</VersionPrefix>
<VersionPrefix>2.3.0</VersionPrefix>
<AssemblyName>Amazon.Lambda.Core</AssemblyName>
<PackageId>Amazon.Lambda.Core</PackageId>
<PackageTags>AWS;Amazon;Lambda</PackageTags>
Expand Down
223 changes: 221 additions & 2 deletions Libraries/src/Amazon.Lambda.Core/ILambdaLogger.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
using System;
using System.Runtime.Versioning;

namespace Amazon.Lambda.Core
{
#if NET6_0_OR_GREATER
Expand Down Expand Up @@ -62,7 +65,7 @@ public interface ILambdaLogger
#if NET6_0_OR_GREATER

/// <summary>
/// Log message catagorized by the given log level
/// Log message categorized by the given log level
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
Expand All @@ -73,7 +76,7 @@ public interface ILambdaLogger
void Log(string level, string message) => LogLine(message);

/// <summary>
/// Log message catagorized by the given log level
/// Log message categorized by the given log level
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
Expand Down Expand Up @@ -142,6 +145,222 @@ public interface ILambdaLogger
/// </summary>
/// <param name="message"></param>
void LogCritical(string message) => Log(LogLevel.Critical.ToString(), message);


private const string ParameterizedPreviewMessage =
"Parameterized logging is in preview till a new version of .NET Lambda runtime client that supports parameterized logging " +
"has been deployed to the .NET Lambda managed runtime. Till deployment has been made the feature can be used by deploying as an " +
"executable including the latest version of Amazon.Lambda.RuntimeSupport and setting the \"EnablePreviewFeatures\" in the Lambda " +
"project file to \"true\"";

/// <summary>
/// Log message categorized by the given log level
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="level">Log level of the message.</param>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void Log(string level, string message, params object[] args) => Log(level, message, args);

/// <summary>
/// Log message categorized by the given log level
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="level">Log level of the message.</param>
/// <param name="exception">Exception to include with the logging.</param>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void Log(string level, Exception exception, string message, params object[] args)
{
Log(level, message, args);
Log(level, exception.ToString(), args);
}

/// <summary>
/// Log message categorized by the given log level
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="level">Log level of the message.</param>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void Log(LogLevel level, string message, params object[] args) => Log(level.ToString(), message, args);

/// <summary>
/// Log message categorized by the given log level
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="level">Log level of the message.</param>
/// <param name="exception">Exception to include with the logging.</param>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void Log(LogLevel level, Exception exception, string message, params object[] args) => Log(level.ToString(), exception, message, args);

/// <summary>
/// Log trace message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogTrace(string message, params object[] args) => Log(LogLevel.Trace.ToString(), message, args);

/// <summary>
/// Log trace message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="exception">Exception to include with the logging.</param>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogTrace(Exception exception, string message, params object[] args) => Log(LogLevel.Trace.ToString(), exception, message, args);

/// <summary>
/// Log debug message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogDebug(string message, params object[] args) => Log(LogLevel.Debug.ToString(), message, args);

/// <summary>
/// Log debug message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="exception">Exception to include with the logging.</param>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogDebug(Exception exception, string message, params object[] args) => Log(LogLevel.Debug.ToString(), exception, message, args);

/// <summary>
/// Log information message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogInformation(string message, params object[] args) => Log(LogLevel.Information.ToString(), message, args);

/// <summary>
/// Log information message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="exception">Exception to include with the logging.</param>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogInformation(Exception exception, string message, params object[] args) => Log(LogLevel.Information.ToString(), exception, message, args);

/// <summary>
/// Log warning message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogWarning(string message, params object[] args) => Log(LogLevel.Warning.ToString(), message, args);

/// <summary>
/// Log warning message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="exception">Exception to include with the logging.</param>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogWarning(Exception exception, string message, params object[] args) => Log(LogLevel.Warning.ToString(), exception, message, args);

/// <summary>
/// Log error message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogError(string message, params object[] args) => Log(LogLevel.Error.ToString(), message, args);

/// <summary>
/// Log error message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="exception">Exception to include with the logging.</param>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogError(Exception exception, string message, params object[] args) => Log(LogLevel.Error.ToString(), exception, message, args);

/// <summary>
/// Log critical message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogCritical(string message, params object[] args) => Log(LogLevel.Critical.ToString(), message, args);

/// <summary>
/// Log critical message.
/// <para>
/// To configure the minimum log level set the AWS_LAMBDA_HANDLER_LOG_LEVEL environment variable. The value should be set
/// to one of the values in the LogLevel enumeration. The default minimum log level is "Information".
/// </para>
/// </summary>
/// <param name="exception">Exception to include with the logging.</param>
/// <param name="message">Message to log.</param>
/// <param name="args">Values to be replaced in log messages that are parameterized.</param>
[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
void LogCritical(Exception exception, string message, params object[] args) => Log(LogLevel.Critical.ToString(), exception, message, args);

#endif

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<PropertyGroup>
<TargetFrameworks>netstandard2.0;net5.0;net6.0;net8.0</TargetFrameworks>
<VersionPrefix>1.10.0</VersionPrefix>
<VersionPrefix>1.11.0</VersionPrefix>
<Description>Provides a bootstrap and Lambda Runtime API Client to help you to develop custom .NET Core Lambda Runtimes.</Description>
<AssemblyTitle>Amazon.Lambda.RuntimeSupport</AssemblyTitle>
<AssemblyName>Amazon.Lambda.RuntimeSupport</AssemblyName>
Expand All @@ -13,6 +13,7 @@
<PackageReadmeFile>README.md</PackageReadmeFile>
<GenerateAssemblyVersionAttribute>true</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>true</GenerateAssemblyFileVersionAttribute>
<LangVersion>9.0</LangVersion>
</PropertyGroup>

<PropertyGroup Condition=" '$(ExecutableOutputType)'=='true' ">
Expand All @@ -23,7 +24,6 @@
<WarningsAsErrors>IL2026,IL2067,IL2075</WarningsAsErrors>
<IsTrimmable>true</IsTrimmable>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ internal class Constants
internal const string AWS_LAMBDA_INITIALIZATION_TYPE_PC = "provisioned-concurrency";
internal const string AWS_LAMBDA_INITIALIZATION_TYPE_ON_DEMAND = "on-demand";

internal const string NET_RIC_LOG_LEVEL_ENVIRONMENT_VARIABLE = "AWS_LAMBDA_HANDLER_LOG_LEVEL";
internal const string NET_RIC_LOG_FORMAT_ENVIRONMENT_VARIABLE = "AWS_LAMBDA_HANDLER_LOG_FORMAT";

internal const string LAMBDA_LOG_LEVEL_ENVIRONMENT_VARIABLE = "AWS_LAMBDA_LOG_LEVEL";
internal const string LAMBDA_LOG_FORMAT_ENVIRONMENT_VARIABLE = "AWS_LAMBDA_LOG_FORMAT";

internal const string LAMBDA_LOG_FORMAT_JSON = "Json";

internal enum AwsLambdaDotNetPreJit
{
Never,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.Lambda.RuntimeSupport.Bootstrap;
using Amazon.Lambda.RuntimeSupport.Helpers;

Expand Down Expand Up @@ -252,9 +253,11 @@ public static HttpClient ConstructHttpClient()

private void WriteUnhandledExceptionToLog(Exception exception)
{
// Console.Error.WriteLine are redirected to the IConsoleLoggerWriter which
// will take care of writing to the function's log stream.
#if NET6_0_OR_GREATER
Client.ConsoleLogger.FormattedWriteLine(LogLevel.Error.ToString(), exception, null);
#else
Console.Error.WriteLine(exception);
#endif
}

#if NET8_0_OR_GREATER
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* permissions and limitations under the License.
*/

using Amazon.Lambda.RuntimeSupport.Helpers;
using System;
using System.IO;
using System.Threading;
Expand All @@ -25,6 +26,11 @@ namespace Amazon.Lambda.RuntimeSupport
/// </summary>
public interface IRuntimeApiClient
{
/// <summary>
/// Logger used for formatting log messages into the user's CloudWatch Log stream.
/// </summary>
IConsoleLoggerWriter ConsoleLogger { get; }

/// <summary>
/// Report an initialization error as an asynchronous operation.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public class RuntimeApiClient : IRuntimeApiClient
internal Func<Exception, ExceptionInfo> ExceptionConverter { get; set; }
internal LambdaEnvironment LambdaEnvironment { get; set; }

/// <inheritdoc/>
public IConsoleLoggerWriter ConsoleLogger => _consoleLoggerRedirector;

/// <summary>
/// Create a new RuntimeApiClient
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Amazon.Lambda.Core;
using Amazon.Lambda.RuntimeSupport.Helpers;
using System;
using System.Runtime.Versioning;

namespace Amazon.Lambda.RuntimeSupport
{
Expand Down Expand Up @@ -44,6 +45,24 @@ public void Log(string level, string message)
{
_consoleLoggerRedirector.FormattedWriteLine(level, message);
}

private const string ParameterizedPreviewMessage =
"Parameterized logging is in preview till a new version of .NET Lambda runtime client that supports parameterized logging " +
"has been deployed to the .NET Lambda managed runtime. Till deployment has been made the feature can be used by deploying as an " +
"executable including the latest version of Amazon.Lambda.RuntimeSupport and setting the \"LangVersion\" in the Lambda " +
"project file to \"preview\"";

[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
public void Log(string level, string message, params object[] args)
{
_consoleLoggerRedirector.FormattedWriteLine(level, message, args);
}

[RequiresPreviewFeatures(ParameterizedPreviewMessage)]
public void Log(string level, Exception exception, string message, params object[] args)
{
_consoleLoggerRedirector.FormattedWriteLine(level, exception, message, args);
}
#endif
}
}
Loading
Loading