From 1fadaf164cd1d27f1e4374f89ea2131642548b19 Mon Sep 17 00:00:00 2001 From: Stanislav Perekrestov Date: Mon, 3 Jun 2024 11:45:48 +0200 Subject: [PATCH 1/3] fixes incorrect variable reference --- src/Serilog.Sinks.GoogleCloudLogging/LogFormatter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Serilog.Sinks.GoogleCloudLogging/LogFormatter.cs b/src/Serilog.Sinks.GoogleCloudLogging/LogFormatter.cs index 191f09c..c903f73 100644 --- a/src/Serilog.Sinks.GoogleCloudLogging/LogFormatter.cs +++ b/src/Serilog.Sinks.GoogleCloudLogging/LogFormatter.cs @@ -116,7 +116,7 @@ public static string CreateLogName(string projectId, string name) // limited to 512 characters and must be url-encoded (using 500 char limit here to be safe) var safeChars = LogNameUnsafeChars.Replace(name, ""); var truncated = safeChars.Length > 500 ? safeChars.Substring(0, 500) : safeChars; - var encoded = UrlEncoder.Default.Encode(safeChars); + var encoded = UrlEncoder.Default.Encode(truncated); // LogName class creates templated string matching GCP requirements logName = new LogName(projectId, encoded).ToString(); From b5735b803a7310134b28adbd43acd3061e29a15b Mon Sep 17 00:00:00 2001 From: Stanislav Perekrestov Date: Mon, 3 Jun 2024 11:47:34 +0200 Subject: [PATCH 2/3] Adds .NET 8.0 support and upgrades to Serilog 4.0 (#71) --- .../GoogleCloudLoggingSink.cs | 4 ++-- .../GoogleCloudLoggingSinkExtensions.cs | 8 +++----- .../LogFormatter.cs | 13 ++++++++++--- .../Serilog.Sinks.GoogleCloudLogging.csproj | 12 ++++++------ src/TestWeb/TestWeb.csproj | 8 ++++---- 5 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSink.cs b/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSink.cs index e7ab9ef..47166b0 100644 --- a/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSink.cs +++ b/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSink.cs @@ -8,9 +8,9 @@ using Google.Cloud.Logging.Type; using Google.Cloud.Logging.V2; using Google.Protobuf.WellKnownTypes; +using Serilog.Core; using Serilog.Events; using Serilog.Formatting; -using Serilog.Sinks.PeriodicBatching; namespace Serilog.Sinks.GoogleCloudLogging; @@ -62,7 +62,7 @@ public GoogleCloudLoggingSink(GoogleCloudLoggingSinkOptions sinkOptions, ITextFo : new LoggingServiceV2ClientBuilder { JsonCredentials = _sinkOptions.GoogleCredentialJson }.Build(); } - public Task EmitBatchAsync(IEnumerable events) + public Task EmitBatchAsync(IReadOnlyCollection events) { using var writer = new StringWriter(); var entries = new List(); diff --git a/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSinkExtensions.cs b/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSinkExtensions.cs index bc3c06d..943f768 100644 --- a/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSinkExtensions.cs +++ b/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSinkExtensions.cs @@ -5,7 +5,6 @@ using Serilog.Events; using Serilog.Formatting; using Serilog.Formatting.Display; -using Serilog.Sinks.PeriodicBatching; namespace Serilog.Sinks.GoogleCloudLogging; @@ -39,17 +38,16 @@ public static LoggerConfiguration GoogleCloudLogging( // formatter can be null if neither parameters are provided textFormatter ??= !String.IsNullOrWhiteSpace(outputTemplate) ? new MessageTemplateTextFormatter(outputTemplate) : null; - var batchingOptions = new PeriodicBatchingSinkOptions + var batchingOptions = new BatchingOptions { BatchSizeLimit = batchSizeLimit ?? 100, - Period = period ?? TimeSpan.FromSeconds(5), + BufferingTimeLimit = period ?? TimeSpan.FromSeconds(5), QueueLimit = queueLimit }; var sink = new GoogleCloudLoggingSink(sinkOptions, textFormatter); - var batchingSink = new PeriodicBatchingSink(sink, batchingOptions); - return loggerConfiguration.Sink(batchingSink, restrictedToMinimumLevel, levelSwitch); + return loggerConfiguration.Sink(sink, batchingOptions, restrictedToMinimumLevel, levelSwitch); } /// diff --git a/src/Serilog.Sinks.GoogleCloudLogging/LogFormatter.cs b/src/Serilog.Sinks.GoogleCloudLogging/LogFormatter.cs index c903f73..099020a 100644 --- a/src/Serilog.Sinks.GoogleCloudLogging/LogFormatter.cs +++ b/src/Serilog.Sinks.GoogleCloudLogging/LogFormatter.cs @@ -11,12 +11,19 @@ namespace Serilog.Sinks.GoogleCloudLogging; -internal class LogFormatter +internal partial class LogFormatter { private readonly ITextFormatter? _textFormatter; private static readonly Dictionary LogNameCache = new(StringComparer.Ordinal); - private static readonly Regex LogNameUnsafeChars = new("[^0-9A-Z._/-]+", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant); + + #if NET8_0_OR_GREATER + [GeneratedRegex("[^0-9A-Z._/-]+", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant)] + private static partial Regex LogNameUnsafeChars(); + #else + private static readonly Regex LogNameUnsafeCharsRegex = new("[^0-9A-Z._/-]+", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant); + private static Regex LogNameUnsafeChars() => LogNameUnsafeCharsRegex; + #endif public LogFormatter(ITextFormatter? textFormatter) { @@ -114,7 +121,7 @@ public static string CreateLogName(string projectId, string name) { // name must only contain: letters, numbers, underscore, hyphen, forward slash, period // limited to 512 characters and must be url-encoded (using 500 char limit here to be safe) - var safeChars = LogNameUnsafeChars.Replace(name, ""); + var safeChars = LogNameUnsafeChars().Replace(name, ""); var truncated = safeChars.Length > 500 ? safeChars.Substring(0, 500) : safeChars; var encoded = UrlEncoder.Default.Encode(truncated); diff --git a/src/Serilog.Sinks.GoogleCloudLogging/Serilog.Sinks.GoogleCloudLogging.csproj b/src/Serilog.Sinks.GoogleCloudLogging/Serilog.Sinks.GoogleCloudLogging.csproj index c2e8fcc..e952403 100644 --- a/src/Serilog.Sinks.GoogleCloudLogging/Serilog.Sinks.GoogleCloudLogging.csproj +++ b/src/Serilog.Sinks.GoogleCloudLogging/Serilog.Sinks.GoogleCloudLogging.csproj @@ -18,7 +18,7 @@ true snupkg true - net6.0;net5.0;netstandard2.1 + net8.0;net6.0;netstandard2.1 latest enable @@ -29,14 +29,14 @@ - - + + all runtime; build; native; contentfiles; analyzers - - - + + + diff --git a/src/TestWeb/TestWeb.csproj b/src/TestWeb/TestWeb.csproj index f6bee1d..c178191 100644 --- a/src/TestWeb/TestWeb.csproj +++ b/src/TestWeb/TestWeb.csproj @@ -1,15 +1,15 @@  - net6.0 + net8.0 default false - - - + + + From a6608ab18814e225cc2b6e268cdf274b9a656e58 Mon Sep 17 00:00:00 2001 From: Stanislav Perekrestov Date: Thu, 14 Mar 2024 17:11:20 +0100 Subject: [PATCH 3/3] propagates current trace and span ids (#67) Serilog starting from v3.1.0 adds two new first-class properties to LogEvent: TraceId and SpanId. These are set automatically in Logger.Write() to the corresponding property values from System.Diagnostics.Activity.Current. --- .../GoogleCloudLoggingSink.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSink.cs b/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSink.cs index 47166b0..90039cd 100644 --- a/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSink.cs +++ b/src/Serilog.Sinks.GoogleCloudLogging/GoogleCloudLoggingSink.cs @@ -104,6 +104,18 @@ private LogEntry CreateLogEntry(LogEvent evnt, StringWriter writer) HandleSpecialProperty(log, property.Key, property.Value); } + if (_sinkOptions.UseLogCorrelation) + { + if (evnt.TraceId.ToString() is { Length: > 0 } traceId) + { + log.Trace = $"projects/{_projectId}/traces/{traceId}"; + } + if (evnt.SpanId?.ToString() is { Length: > 0 } spanId) + { + log.SpanId = spanId; + } + } + if (_serviceContext != null) jsonPayload.Fields.Add("serviceContext", Value.ForStruct(_serviceContext)); @@ -119,12 +131,6 @@ private void HandleSpecialProperty(LogEntry log, string key, LogEventPropertyVal if (_sinkOptions.UseLogCorrelation) { - if (key.Equals("TraceId", StringComparison.OrdinalIgnoreCase)) - log.Trace = $"projects/{_projectId}/traces/{GetString(value)}"; - - if (key.Equals("SpanId", StringComparison.OrdinalIgnoreCase)) - log.SpanId = GetString(value); - if (key.Equals("TraceSampled", StringComparison.OrdinalIgnoreCase)) log.TraceSampled = GetBoolean(value); }