Skip to content

Commit

Permalink
Merge branch 'main' into instrumentationServiceFabricRemoting
Browse files Browse the repository at this point in the history
  • Loading branch information
Kielek authored Dec 17, 2024
2 parents 1235ed5 + aca23a2 commit 1462719
Show file tree
Hide file tree
Showing 12 changed files with 476 additions and 3 deletions.
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,15 @@ updates:
interval: "daily"
labels:
- "infra"
- package-ecosystem: "dotnet-sdk"
directory: "/"
schedule:
interval: "weekly"
day: "wednesday"
labels:
- "infra"
ignore:
- dependency-name: "*"
update-types:
- "version-update:semver-major"
- "version-update:semver-minor"
2 changes: 1 addition & 1 deletion opentelemetry-dotnet-contrib.sln
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{1FCC8E
src\Shared\ServerCertificateValidationProvider.cs = src\Shared\ServerCertificateValidationProvider.cs
src\Shared\SpanAttributeConstants.cs = src\Shared\SpanAttributeConstants.cs
src\Shared\SpanHelper.cs = src\Shared\SpanHelper.cs
src\Shared\SqlProcessor.cs = src\Shared\SqlProcessor.cs
src\Shared\SqlProcessor.cs = src\Shared\SqlProcessor.cs
src\Shared\UriHelper.cs = src\Shared\UriHelper.cs
EndProjectSection
EndProject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ OpenTelemetry.Trace.BaggageActivityProcessor
OpenTelemetry.Trace.TracerProviderBuilderExtensions
override OpenTelemetry.RateLimitingSampler.ShouldSample(in OpenTelemetry.Trace.SamplingParameters samplingParameters) -> OpenTelemetry.Trace.SamplingResult
override OpenTelemetry.Trace.BaggageActivityProcessor.OnStart(System.Diagnostics.Activity! data) -> void
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddBaggageProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! builder) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddBaggageProcessor(this OpenTelemetry.Logs.LoggerProviderBuilder! builder, System.Predicate<string!>! baggageKeyPredicate) -> OpenTelemetry.Logs.LoggerProviderBuilder!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddBaggageProcessor(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions! loggerOptions) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AddBaggageProcessor(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions! loggerOptions, System.Predicate<string!>! baggageKeyPredicate) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
static Microsoft.Extensions.Logging.OpenTelemetryLoggingExtensions.AttachLogsToActivityEvent(this OpenTelemetry.Logs.OpenTelemetryLoggerOptions! loggerOptions, System.Action<OpenTelemetry.Logs.LogToActivityEventConversionOptions!>? configure = null) -> OpenTelemetry.Logs.OpenTelemetryLoggerOptions!
static OpenTelemetry.Trace.BaggageActivityProcessor.AllowAllBaggageKeys.get -> System.Predicate<string!>!
static OpenTelemetry.Trace.TracerProviderBuilderExtensions.AddAutoFlushActivityProcessor(this OpenTelemetry.Trace.TracerProviderBuilder! builder, System.Func<System.Diagnostics.Activity!, bool>! predicate, int timeoutMilliseconds = 10000) -> OpenTelemetry.Trace.TracerProviderBuilder!
Expand Down
3 changes: 3 additions & 0 deletions src/OpenTelemetry.Extensions/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ rate per second. For details see
* Updated OpenTelemetry core component version(s) to `1.10.0`.
([#2317](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2317))

* Adds Baggage LogRecord Processor.
([#2354](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2354))

## 1.0.0-beta.5

Released 2024-May-08
Expand Down
46 changes: 46 additions & 0 deletions src/OpenTelemetry.Extensions/Internal/BaggageLogRecordProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

using OpenTelemetry.Logs;

namespace OpenTelemetry.Extensions.Internal;

internal sealed class BaggageLogRecordProcessor : BaseProcessor<LogRecord>
{
private readonly Predicate<string> baggageKeyPredicate;

public BaggageLogRecordProcessor(Predicate<string> baggageKeyPredicate)
{
this.baggageKeyPredicate = baggageKeyPredicate ?? throw new ArgumentNullException(nameof(baggageKeyPredicate));
}

public static Predicate<string> AllowAllBaggageKeys => (_) => true;

public override void OnEnd(LogRecord data)
{
var baggage = Baggage.Current;

if (data != null && baggage.Count > 0)
{
var capacity = (data.Attributes?.Count ?? 0) + baggage.Count;
var attributes = new List<KeyValuePair<string, object?>>(capacity);

foreach (var entry in baggage)
{
if (this.baggageKeyPredicate(entry.Key))
{
attributes.Add(new(entry.Key, entry.Value));
}
}

if (data.Attributes != null)
{
attributes.AddRange(data.Attributes);
}

data.Attributes = attributes;
}

base.OnEnd(data!);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,14 @@ public void LogRecordFilterException(string? categoryName, string exception)
}

[Event(3, Message = "Baggage key predicate threw exeption when trying to add baggage entry with key '{0}'. Baggage entry will not be added to the activity. Exception: '{1}'", Level = EventLevel.Warning)]
public void BaggageKeyPredicateException(string baggageKey, string exception)
public void BaggageKeyActivityPredicateException(string baggageKey, string exception)
{
this.WriteEvent(3, baggageKey, exception);
}

[Event(4, Message = "Baggage key predicate threw exeption when trying to add baggage entry with key '{0}'. Baggage entry will not be added to the log record. Exception: '{1}'", Level = EventLevel.Warning)]
public void BaggageKeyLogRecordPredicateException(string baggageKey, string exception)
{
this.WriteEvent(4, baggageKey, exception);
}
}
100 changes: 100 additions & 0 deletions src/OpenTelemetry.Extensions/Logs/OpenTelemetryLoggingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// SPDX-License-Identifier: Apache-2.0

using System.Diagnostics;
using OpenTelemetry;
using OpenTelemetry.Extensions.Internal;
using OpenTelemetry.Internal;
using OpenTelemetry.Logs;

Expand Down Expand Up @@ -34,4 +36,102 @@ public static OpenTelemetryLoggerOptions AttachLogsToActivityEvent(
return loggerOptions.AddProcessor(new ActivityEventAttachingLogProcessor(options));
#pragma warning restore CA2000 // Dispose objects before losing scope
}

/// <summary>
/// Adds a <see cref="LogRecord"/> processor to the OpenTelemetry <see
/// cref="OpenTelemetryLoggerOptions"/> which will copy all
/// baggage entries as log record attributes.
/// </summary>
/// <param name="loggerOptions"><see cref="OpenTelemetryLoggerOptions"/> to add the <see cref="LogRecord"/> processor to.</param>
/// <returns>The instance of <see cref="OpenTelemetryLoggerOptions"/> to chain the calls.</returns>
/// <exception cref="ArgumentNullException"><paramref name="loggerOptions"/> is <c>null</c>.</exception>
/// <remarks>
/// Copies all current baggage entries to log record attributes.
/// </remarks>
public static OpenTelemetryLoggerOptions AddBaggageProcessor(
this OpenTelemetryLoggerOptions loggerOptions)
{
return loggerOptions.AddBaggageProcessor(BaggageLogRecordProcessor.AllowAllBaggageKeys);
}

/// <summary>
/// Adds a <see cref="LogRecord"/> processor to the OpenTelemetry <see
/// cref="OpenTelemetryLoggerOptions"/> which will conditionally copy
/// baggage entries as log record attributes.
/// </summary>
/// <param name="loggerOptions"><see cref="OpenTelemetryLoggerOptions"/> to add the <see cref="LogRecord"/> processor to.</param>
/// <param name="baggageKeyPredicate">Predicate to determine which baggage keys should be added to the log record.</param>
/// <returns>The instance of <see cref="OpenTelemetryLoggerOptions"/> to chain the calls.</returns>
/// <exception cref="ArgumentNullException"><paramref name="loggerOptions"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="baggageKeyPredicate"/> is <c>null</c>.</exception>
/// <remarks>
/// Conditionally copies current baggage entries to log record attributes.
/// In case of an exception the predicate is treated as false, and the baggage entry will not be copied.
/// </remarks>
public static OpenTelemetryLoggerOptions AddBaggageProcessor(
this OpenTelemetryLoggerOptions loggerOptions,
Predicate<string> baggageKeyPredicate)
{
Guard.ThrowIfNull(loggerOptions);
Guard.ThrowIfNull(baggageKeyPredicate);

return loggerOptions.AddProcessor(_ => SetupBaggageLogRecordProcessor(baggageKeyPredicate));
}

/// <summary>
/// Adds a <see cref="LogRecord"/> processor to the OpenTelemetry <see
/// cref="LoggerProviderBuilder"/> which will copy all
/// baggage entries as log record attributes.
/// </summary>
/// <param name="builder"><see cref="LoggerProviderBuilder"/> to add the <see cref="LogRecord"/> processor to.</param>
/// <returns>The instance of <see cref="LoggerProviderBuilder"/> to chain the calls.</returns>
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <c>null</c>.</exception>
/// <remarks>
/// Copies all current baggage entries to log record attributes.
/// </remarks>
public static LoggerProviderBuilder AddBaggageProcessor(
this LoggerProviderBuilder builder)
{
return builder.AddBaggageProcessor(BaggageLogRecordProcessor.AllowAllBaggageKeys);
}

/// <summary>
/// Adds a <see cref="LogRecord"/> processor to the OpenTelemetry <see
/// cref="LoggerProviderBuilder"/> which will copy all
/// baggage entries as log record attributes.
/// </summary>
/// <param name="builder"><see cref="LoggerProviderBuilder"/> to add the <see cref="LogRecord"/> processor to.</param>
/// <param name="baggageKeyPredicate">Predicate to determine which baggage keys should be added to the log record.</param>
/// <returns>The instance of <see cref="LoggerProviderBuilder"/> to chain the calls.</returns>
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="baggageKeyPredicate"/> is <c>null</c>.</exception>
/// <remarks>
/// Conditionally copies current baggage entries to log record attributes.
/// In case of an exception the predicate is treated as false, and the baggage entry will not be copied.
/// </remarks>
public static LoggerProviderBuilder AddBaggageProcessor(
this LoggerProviderBuilder builder,
Predicate<string> baggageKeyPredicate)
{
Guard.ThrowIfNull(builder);
Guard.ThrowIfNull(baggageKeyPredicate);

return builder.AddProcessor(_ => SetupBaggageLogRecordProcessor(baggageKeyPredicate));
}

private static BaggageLogRecordProcessor SetupBaggageLogRecordProcessor(Predicate<string> baggageKeyPredicate)
{
return new BaggageLogRecordProcessor(baggageKey =>
{
try
{
return baggageKeyPredicate(baggageKey);
}
catch (Exception exception)
{
OpenTelemetryExtensionsEventSource.Log.BaggageKeyLogRecordPredicateException(baggageKey, exception.Message);
return false;
}
});
}
}
22 changes: 22 additions & 0 deletions src/OpenTelemetry.Extensions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,28 @@ future.
Adds a log processor which will convert log messages into events and attach them
to the currently running `Activity`.

### AddBaggageProcessor

Adds a log processor which will copy baggage entries to log records.
The method takes an optional predicate to filter the copied baggage entries
based on the entry key. If no predicate is provided, all entries are copied.

Example of AddBaggageProcessor usage with a predicate:

```csharp
var regex = new Regex("^allow", RegexOptions.Compiled);
using var loggerFactory = LoggerFactory.Create(builder => builder
.AddOpenTelemetry(options =>
{
options.AddBaggageProcessor(regex.IsMatch);
// other set up (exporters, processors)
})
```

Warning: The baggage key predicate is executed for every baggage entry for each
log record.
Do not use slow or intensive operations.

## Traces

### AutoFlushActivityProcessor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static TracerProviderBuilder AddBaggageActivityProcessor(
}
catch (Exception exception)
{
OpenTelemetryExtensionsEventSource.Log.BaggageKeyPredicateException(baggageKey, exception.Message);
OpenTelemetryExtensionsEventSource.Log.BaggageKeyActivityPredicateException(baggageKey, exception.Message);
return false;
}
}));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using OpenTelemetry.Trace;
using Xunit;

namespace OpenTelemetry.Extensions.Tests.Logs;

public class LoggerFactoryBaggageLogRecordProcessorTests
{
[Fact]
public void BaggageLogRecordProcessor_CanAddAllowAllBaggageKeysPredicate()
{
var logRecordList = new List<LogRecord>();
using var loggerFactory = LoggerFactory.Create(builder => builder
.AddOpenTelemetry(options =>
{
options.AddBaggageProcessor();
options.AddInMemoryExporter(logRecordList);
})
.AddFilter("*", LogLevel.Trace)); // Enable all LogLevels
Baggage.SetBaggage("allow", "value");

var logger = loggerFactory.CreateLogger(GetTestMethodName());
logger.LogError("this does not matter");
var logRecord = Assert.Single(logRecordList);
Assert.NotNull(logRecord);
Assert.NotNull(logRecord.Attributes);
Assert.Contains(logRecord.Attributes, kv => kv.Key == "allow");
}

[Fact]
public void BaggageLogRecordProcessor_CanUseCustomPredicate()
{
var logRecordList = new List<LogRecord>();
using var loggerFactory = LoggerFactory.Create(builder => builder
.AddOpenTelemetry(options =>
{
options.AddBaggageProcessor((baggageKey) => baggageKey.StartsWith("allow", StringComparison.Ordinal));
options.AddInMemoryExporter(logRecordList);
})
.AddFilter("*", LogLevel.Trace)); // Enable all LogLevels
Baggage.SetBaggage("allow", "value");
Baggage.SetBaggage("deny", "other_value");

var logger = loggerFactory.CreateLogger(GetTestMethodName());
logger.LogError("this does not matter");
var logRecord = Assert.Single(logRecordList);
Assert.NotNull(logRecord);
Assert.NotNull(logRecord.Attributes);
Assert.Contains(logRecord.Attributes, kv => kv.Key == "allow");
Assert.DoesNotContain(logRecord.Attributes, kv => kv.Key == "deny");
}

[Fact]
public void BaggageLogRecordProcessor_CanUseRegex()
{
var regex = new Regex("^allow", RegexOptions.Compiled);
var logRecordList = new List<LogRecord>();
using var loggerFactory = LoggerFactory.Create(builder => builder
.AddOpenTelemetry(options =>
{
options.AddBaggageProcessor(regex.IsMatch);
options.AddInMemoryExporter(logRecordList);
})
.AddFilter("*", LogLevel.Trace)); // Enable all LogLevels
Baggage.SetBaggage("allow", "value");
Baggage.SetBaggage("deny", "other_value");

var logger = loggerFactory.CreateLogger(GetTestMethodName());
logger.LogError("this does not matter");
var logRecord = Assert.Single(logRecordList);
Assert.NotNull(logRecord);
Assert.NotNull(logRecord.Attributes);
Assert.Contains(logRecord.Attributes, kv => kv.Key == "allow");
Assert.DoesNotContain(logRecord.Attributes, kv => kv.Key == "deny");
}

[Fact]
public void BaggageLogRecordProcessor_PredicateThrows_DoesNothing()
{
var logRecordList = new List<LogRecord>();
using var loggerFactory = LoggerFactory.Create(builder => builder
.AddOpenTelemetry(options =>
{
options.AddBaggageProcessor(_ => throw new Exception("Predicate throws an exception."));
options.AddInMemoryExporter(logRecordList);
})
.AddFilter("*", LogLevel.Trace)); // Enable all LogLevels
Baggage.SetBaggage("deny", "value");

var logger = loggerFactory.CreateLogger(GetTestMethodName());
logger.LogError("this does not matter");
var logRecord = Assert.Single(logRecordList);
Assert.NotNull(logRecord);
Assert.DoesNotContain(logRecord?.Attributes ?? [], kv => kv.Key == "deny");
}

[Fact]
public void BaggageLogRecordProcessor_PredicateThrows_OnlyDropsEntriesThatThrow()
{
var logRecordList = new List<LogRecord>();
using var loggerFactory = LoggerFactory.Create(builder => builder
.AddOpenTelemetry(options =>
{
options.AddBaggageProcessor(key =>
{
return key != "allow" ? throw new Exception("Predicate throws an exception.") : true;
});
options.AddInMemoryExporter(logRecordList);
})
.AddFilter("*", LogLevel.Trace)); // Enable all LogLevels
Baggage.SetBaggage("allow", "value");
Baggage.SetBaggage("deny", "value");
Baggage.SetBaggage("deny_2", "value");

var logger = loggerFactory.CreateLogger(GetTestMethodName());
logger.LogError("this does not matter");
var logRecord = Assert.Single(logRecordList);
Assert.NotNull(logRecord);
Assert.NotNull(logRecord.Attributes);
Assert.Contains(logRecord.Attributes, kv => kv.Key == "allow");
Assert.DoesNotContain(logRecord?.Attributes ?? [], kv => kv.Key == "deny");
}

private static string GetTestMethodName([CallerMemberName] string callingMethodName = "")
{
return callingMethodName;
}
}
Loading

0 comments on commit 1462719

Please sign in to comment.