diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md
index dbea72b5ad0..90f64dd9c0a 100644
--- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md
+++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md
@@ -12,6 +12,13 @@
and `OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT`.
([#4887](https://github.com/open-telemetry/opentelemetry-dotnet/pull/4887))
+* Added ability to export attributes corresponding to `LogRecord.Exception` i.e.
+`exception.type`, `exception.message` and `exception.stacktrace`. These
+attributes will be exported when
+`OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES` environment
+variable will be set to `true`.
+([#4892](https://github.com/open-telemetry/opentelemetry-dotnet/pull/4892))
+
## 1.6.0
Released 2023-Sep-05
diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ExperimentalOptions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ExperimentalOptions.cs
new file mode 100644
index 00000000000..2734ad8a158
--- /dev/null
+++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ExperimentalOptions.cs
@@ -0,0 +1,45 @@
+//
+// Copyright The OpenTelemetry Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#nullable enable
+
+using Microsoft.Extensions.Configuration;
+using OpenTelemetry.Internal;
+
+namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
+
+internal sealed class ExperimentalOptions
+{
+ public const string EMITLOGEXCEPTIONATTRIBUTES = "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES";
+
+ public ExperimentalOptions()
+ : this(new ConfigurationBuilder().AddEnvironmentVariables().Build())
+ {
+ }
+
+ public ExperimentalOptions(IConfiguration configuration)
+ {
+ if (configuration.TryGetBoolValue(EMITLOGEXCEPTIONATTRIBUTES, out var emitLogExceptionAttributes))
+ {
+ this.EmitLogExceptionAttributes = emitLogExceptionAttributes;
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether log exception attributes should be exported.
+ ///
+ public bool EmitLogExceptionAttributes { get; set; } = false;
+}
diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OtlpLogRecordTransformer.cs
similarity index 78%
rename from src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs
rename to src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OtlpLogRecordTransformer.cs
index 028a02b5126..3a7be7f04c8 100644
--- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/LogRecordExtensions.cs
+++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OtlpLogRecordTransformer.cs
@@ -1,4 +1,4 @@
-//
+//
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,7 +16,9 @@
using System.Runtime.CompilerServices;
using Google.Protobuf;
+using OpenTelemetry.Internal;
using OpenTelemetry.Logs;
+using OpenTelemetry.Trace;
using OtlpCollector = OpenTelemetry.Proto.Collector.Logs.V1;
using OtlpCommon = OpenTelemetry.Proto.Common.V1;
using OtlpLogs = OpenTelemetry.Proto.Logs.V1;
@@ -24,14 +26,23 @@
namespace OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
-internal static class LogRecordExtensions
+internal sealed class OtlpLogRecordTransformer
{
- internal static void AddBatch(
- this OtlpCollector.ExportLogsServiceRequest request,
- SdkLimitOptions sdkLimitOptions,
+ private readonly SdkLimitOptions sdkLimitOptions;
+ private readonly ExperimentalOptions experimentalOptions;
+
+ public OtlpLogRecordTransformer(SdkLimitOptions sdkLimitOptions, ExperimentalOptions experimentalOptions)
+ {
+ this.sdkLimitOptions = sdkLimitOptions;
+ this.experimentalOptions = experimentalOptions;
+ }
+
+ internal OtlpCollector.ExportLogsServiceRequest BuildExportRequest(
OtlpResource.Resource processResource,
in Batch logRecordBatch)
{
+ var request = new OtlpCollector.ExportLogsServiceRequest();
+
var resourceLogs = new OtlpLogs.ResourceLogs
{
Resource = processResource,
@@ -43,16 +54,18 @@ internal static void AddBatch(
foreach (var logRecord in logRecordBatch)
{
- var otlpLogRecord = logRecord.ToOtlpLog(sdkLimitOptions);
+ var otlpLogRecord = this.ToOtlpLog(logRecord);
if (otlpLogRecord != null)
{
scopeLogs.LogRecords.Add(otlpLogRecord);
}
}
+
+ return request;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord, SdkLimitOptions sdkLimitOptions)
+ internal OtlpLogs.LogRecord ToOtlpLog(LogRecord logRecord)
{
OtlpLogs.LogRecord otlpLogRecord = null;
@@ -75,8 +88,8 @@ internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord, SdkLimitO
otlpLogRecord.SeverityText = logRecord.Severity.Value.ToShortName();
}
- var attributeValueLengthLimit = sdkLimitOptions.LogRecordAttributeValueLengthLimit;
- var attributeCountLimit = sdkLimitOptions.LogRecordAttributeCountLimit ?? int.MaxValue;
+ var attributeValueLengthLimit = this.sdkLimitOptions.LogRecordAttributeValueLengthLimit;
+ var attributeCountLimit = this.sdkLimitOptions.LogRecordAttributeCountLimit ?? int.MaxValue;
/*
// Removing this temporarily for stable release
@@ -104,14 +117,14 @@ internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord, SdkLimitO
{
otlpLogRecord.AddStringAttribute(nameof(logRecord.EventId.Name), logRecord.EventId.Name, attributeValueLengthLimit, attributeCountLimit);
}
+ */
- if (logRecord.Exception != null)
+ if (this.experimentalOptions.EmitLogExceptionAttributes && logRecord.Exception != null)
{
- otlpLogRecord.AddStringAttribute(SemanticConventions.AttributeExceptionType, logRecord.Exception.GetType().Name, attributeValueLengthLimit, attributeCountLimit);
- otlpLogRecord.AddStringAttribute(SemanticConventions.AttributeExceptionMessage, logRecord.Exception.Message, attributeValueLengthLimit, attributeCountLimit);
- otlpLogRecord.AddStringAttribute(SemanticConventions.AttributeExceptionStacktrace, logRecord.Exception.ToInvariantString(), attributeValueLengthLimit, attributeCountLimit);
+ AddStringAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionType, logRecord.Exception.GetType().Name, attributeValueLengthLimit, attributeCountLimit);
+ AddStringAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionMessage, logRecord.Exception.Message, attributeValueLengthLimit, attributeCountLimit);
+ AddStringAttribute(otlpLogRecord, SemanticConventions.AttributeExceptionStacktrace, logRecord.Exception.ToInvariantString(), attributeValueLengthLimit, attributeCountLimit);
}
- */
bool bodyPopulatedFromFormattedMessage = false;
if (logRecord.FormattedMessage != null)
@@ -133,7 +146,7 @@ internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord, SdkLimitO
}
else if (OtlpKeyValueTransformer.Instance.TryTransformTag(attribute, out var result, attributeValueLengthLimit))
{
- otlpLogRecord.AddAttribute(result, attributeCountLimit);
+ AddAttribute(otlpLogRecord, result, attributeCountLimit);
}
}
}
@@ -183,7 +196,7 @@ void ProcessScope(LogRecordScope scope, OtlpLogs.LogRecord otlpLog)
{
if (OtlpKeyValueTransformer.Instance.TryTransformTag(scopeItem, out var result, attributeValueLengthLimit))
{
- otlpLog.AddAttribute(result, attributeCountLimit);
+ AddAttribute(otlpLog, result, attributeCountLimit);
}
}
}
@@ -198,7 +211,7 @@ void ProcessScope(LogRecordScope scope, OtlpLogs.LogRecord otlpLog)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void AddAttribute(this OtlpLogs.LogRecord logRecord, OtlpCommon.KeyValue attribute, int maxAttributeCount)
+ private static void AddAttribute(OtlpLogs.LogRecord logRecord, OtlpCommon.KeyValue attribute, int maxAttributeCount)
{
if (logRecord.Attributes.Count < maxAttributeCount)
{
@@ -211,22 +224,22 @@ private static void AddAttribute(this OtlpLogs.LogRecord logRecord, OtlpCommon.K
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void AddStringAttribute(this OtlpLogs.LogRecord logRecord, string key, string value, int? maxValueLength, int maxAttributeCount)
+ private static void AddStringAttribute(OtlpLogs.LogRecord logRecord, string key, string value, int? maxValueLength, int maxAttributeCount)
{
var attributeItem = new KeyValuePair(key, value);
if (OtlpKeyValueTransformer.Instance.TryTransformTag(attributeItem, out var result, maxValueLength))
{
- logRecord.AddAttribute(result, maxAttributeCount);
+ AddAttribute(logRecord, result, maxAttributeCount);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void AddIntAttribute(this OtlpLogs.LogRecord logRecord, string key, int value, int maxAttributeCount)
+ private static void AddIntAttribute(OtlpLogs.LogRecord logRecord, string key, int value, int maxAttributeCount)
{
var attributeItem = new KeyValuePair(key, value);
if (OtlpKeyValueTransformer.Instance.TryTransformTag(attributeItem, out var result))
{
- logRecord.AddAttribute(result, maxAttributeCount);
+ AddAttribute(logRecord, result, maxAttributeCount);
}
}
diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporter.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporter.cs
index 3a1b4551f98..715ec0de263 100644
--- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporter.cs
+++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/OtlpLogExporter.cs
@@ -30,8 +30,8 @@ namespace OpenTelemetry.Exporter;
///
internal sealed class OtlpLogExporter : BaseExporter
{
- private readonly SdkLimitOptions sdkLimitOptions;
private readonly IExportClient exportClient;
+ private readonly OtlpLogRecordTransformer otlpLogRecordTransformer;
private OtlpResource.Resource processResource;
@@ -58,8 +58,6 @@ internal OtlpLogExporter(
Debug.Assert(exporterOptions != null, "exporterOptions was null");
Debug.Assert(sdkLimitOptions != null, "sdkLimitOptions was null");
- this.sdkLimitOptions = sdkLimitOptions;
-
// Each of the Otlp exporters: Traces, Metrics, and Logs set the same value for `OtlpKeyValueTransformer.LogUnsupportedAttributeType`
// and `ConfigurationExtensions.LogInvalidEnvironmentVariable` so it should be fine even if these exporters are used together.
OtlpKeyValueTransformer.LogUnsupportedAttributeType = (string tagValueType, string tagKey) =>
@@ -80,6 +78,8 @@ internal OtlpLogExporter(
{
this.exportClient = exporterOptions.GetLogExportClient();
}
+
+ this.otlpLogRecordTransformer = new OtlpLogRecordTransformer(sdkLimitOptions, new());
}
internal OtlpResource.Resource ProcessResource => this.processResource ??= this.ParentProvider.GetResource().ToOtlpResource();
@@ -90,11 +90,9 @@ public override ExportResult Export(in Batch logRecordBatch)
// Prevents the exporter's gRPC and HTTP operations from being instrumented.
using var scope = SuppressInstrumentationScope.Begin();
- var request = new OtlpCollector.ExportLogsServiceRequest();
-
try
{
- request.AddBatch(this.sdkLimitOptions, this.ProcessResource, logRecordBatch);
+ var request = this.otlpLogRecordTransformer.BuildExportRequest(this.ProcessResource, logRecordBatch);
if (!this.exportClient.SendExportRequest(request))
{
diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md
index 183df4498f4..2f53e327ecc 100644
--- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md
+++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/README.md
@@ -218,6 +218,17 @@ values of the log record limits
* `OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT`
* `OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT`
+## Environment Variables for Experimental Features
+
+### Otlp Log Exporter
+
+* `OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EXCEPTION_LOG_ATTRIBUTES`
+
+When set to `true`, it enables export of attributes corresponding to
+`LogRecord.Exception`. The attributes `exception.type`, `exception.message` and
+`exception.stacktrace` are defined in
+[specification](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/exceptions/exceptions-logs.md#attributes).
+
## Configure HttpClient
The `HttpClientFactory` option is provided on `OtlpExporterOptions` for users
diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs
index 7a32a4a34eb..0c2e6c06f9b 100644
--- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs
+++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs
@@ -17,12 +17,14 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Reflection;
+using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Moq;
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation;
using OpenTelemetry.Exporter.OpenTelemetryProtocol.Implementation.ExportClient;
+using OpenTelemetry.Internal;
using OpenTelemetry.Logs;
using OpenTelemetry.Tests;
using OpenTelemetry.Trace;
@@ -178,8 +180,10 @@ public void OtlpLogRecordTestWhenStateValuesArePopulated()
Assert.Single(logRecords);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+
var logRecord = logRecords[0];
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.NotNull(otlpLogRecord);
Assert.Equal("Hello from tomato 2.99.", otlpLogRecord.Body.StringValue);
@@ -223,7 +227,7 @@ public void CheckToOtlpLogRecordLoggerCategory()
Assert.Single(logRecords);
var logRecord = logRecords[0];
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions, new());
Assert.NotNull(otlpLogRecord);
Assert.Single(otlpLogRecord.Attributes);
@@ -237,7 +241,7 @@ public void CheckToOtlpLogRecordLoggerCategory()
Assert.Single(logRecords);
logRecord = logRecords[0];
- otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions, new());
Assert.NotNull(otlpLogRecord);
Assert.Empty(otlpLogRecord.Attributes);
}
@@ -261,7 +265,7 @@ public void CheckToOtlpLogRecordEventId()
Assert.Single(logRecords);
var logRecord = logRecords[0];
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions, new());
Assert.NotNull(otlpLogRecord);
Assert.Equal("Hello from tomato 2.99.", otlpLogRecord.Body.StringValue);
@@ -278,7 +282,7 @@ public void CheckToOtlpLogRecordEventId()
Assert.Single(logRecords);
logRecord = logRecords[0];
- otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions, new());
Assert.NotNull(otlpLogRecord);
Assert.Equal("Hello from tomato 2.99.", otlpLogRecord.Body.StringValue);
@@ -306,8 +310,10 @@ public void CheckToOtlpLogRecordTimestamps()
var logger = loggerFactory.CreateLogger("OtlpLogExporterTests");
logger.LogInformation("Log message");
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+
var logRecord = logRecords[0];
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.True(otlpLogRecord.TimeUnixNano > 0);
Assert.True(otlpLogRecord.ObservedTimeUnixNano > 0);
@@ -327,8 +333,11 @@ public void CheckToOtlpLogRecordTraceIdSpanIdFlagWithNoActivity()
var logger = loggerFactory.CreateLogger("OtlpLogExporterTests");
logger.LogInformation("Log when there is no activity.");
+
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+
var logRecord = logRecords[0];
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.Null(Activity.Current);
Assert.True(otlpLogRecord.TraceId.IsEmpty);
@@ -360,8 +369,10 @@ public void CheckToOtlpLogRecordSpanIdTraceIdAndFlag()
expectedSpanId = activity.SpanId;
}
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+
var logRecord = logRecords[0];
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.Equal(expectedTraceId.ToString(), ActivityTraceId.CreateFromBytes(otlpLogRecord.TraceId.ToByteArray()).ToString());
Assert.Equal(expectedSpanId.ToString(), ActivitySpanId.CreateFromBytes(otlpLogRecord.SpanId.ToByteArray()).ToString());
@@ -392,8 +403,10 @@ public void CheckToOtlpLogRecordSeverityLevelAndText(LogLevel logLevel)
logger.Log(logLevel, "Hello from {name} {price}.", "tomato", 2.99);
Assert.Single(logRecords);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+
var logRecord = logRecords[0];
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.NotNull(otlpLogRecord);
#pragma warning disable CS0618 // Type or member is obsolete
@@ -445,8 +458,10 @@ public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage)
logger.LogInformation("OpenTelemetry {Greeting} {Subject}!", "Hello", "World");
Assert.Single(logRecords);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+
var logRecord = logRecords[0];
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.NotNull(otlpLogRecord);
if (includeFormattedMessage)
@@ -465,7 +480,7 @@ public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage)
Assert.Single(logRecords);
logRecord = logRecords[0];
- otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.NotNull(otlpLogRecord);
@@ -481,7 +496,7 @@ public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage)
Assert.Single(logRecords);
logRecord = logRecords[0];
- otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.NotNull(otlpLogRecord);
@@ -489,9 +504,10 @@ public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage)
Assert.Equal("state", otlpLogRecord.Body.StringValue);
}
- /*
- [Fact]
- public void CheckToOtlpLogRecordExceptionAttributes()
+ [Theory]
+ [InlineData("true")]
+ [InlineData("false")]
+ public void CheckToOtlpLogRecordExceptionAttributes(string emitExceptionAttributes)
{
var logRecords = new List();
using var loggerFactory = LoggerFactory.Create(builder =>
@@ -507,20 +523,40 @@ public void CheckToOtlpLogRecordExceptionAttributes()
var logRecord = logRecords[0];
var loggedException = logRecord.Exception;
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var configuration = new ConfigurationBuilder()
+ .AddInMemoryCollection(new Dictionary { [ExperimentalOptions.EMITLOGEXCEPTIONATTRIBUTES] = emitExceptionAttributes })
+ .Build();
+
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new(configuration));
+
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.NotNull(otlpLogRecord);
var otlpLogRecordAttributes = otlpLogRecord.Attributes.ToString();
- Assert.Contains(SemanticConventions.AttributeExceptionType, otlpLogRecordAttributes);
- Assert.Contains(logRecord.Exception.GetType().Name, otlpLogRecordAttributes);
- Assert.Contains(SemanticConventions.AttributeExceptionMessage, otlpLogRecordAttributes);
- Assert.Contains(logRecord.Exception.Message, otlpLogRecordAttributes);
+ if (emitExceptionAttributes == "true")
+ {
+ Assert.Contains(SemanticConventions.AttributeExceptionType, otlpLogRecordAttributes);
+ Assert.Contains(logRecord.Exception.GetType().Name, otlpLogRecordAttributes);
+
+ Assert.Contains(SemanticConventions.AttributeExceptionMessage, otlpLogRecordAttributes);
+ Assert.Contains(logRecord.Exception.Message, otlpLogRecordAttributes);
- Assert.Contains(SemanticConventions.AttributeExceptionStacktrace, otlpLogRecordAttributes);
- Assert.Contains(logRecord.Exception.ToInvariantString(), otlpLogRecordAttributes);
+ Assert.Contains(SemanticConventions.AttributeExceptionStacktrace, otlpLogRecordAttributes);
+ Assert.Contains(logRecord.Exception.ToInvariantString(), otlpLogRecordAttributes);
+ }
+ else
+ {
+ Assert.DoesNotContain(SemanticConventions.AttributeExceptionType, otlpLogRecordAttributes);
+ Assert.DoesNotContain(logRecord.Exception.GetType().Name, otlpLogRecordAttributes);
+
+ Assert.DoesNotContain(SemanticConventions.AttributeExceptionMessage, otlpLogRecordAttributes);
+ Assert.DoesNotContain(logRecord.Exception.Message, otlpLogRecordAttributes);
+
+ Assert.DoesNotContain(SemanticConventions.AttributeExceptionStacktrace, otlpLogRecordAttributes);
+ Assert.DoesNotContain(logRecord.Exception.ToInvariantString(), otlpLogRecordAttributes);
+ }
}
- */
[Fact]
public void CheckToOtlpLogRecordRespectsAttributeLimits()
@@ -544,8 +580,10 @@ public void CheckToOtlpLogRecordRespectsAttributeLimits()
var logger = loggerFactory.CreateLogger(string.Empty);
logger.LogInformation("OpenTelemetry {AttributeOne} {AttributeTwo} {AttributeThree}!", "I'm an attribute", "I too am an attribute", "I get dropped :(");
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(sdkLimitOptions, new());
+
var logRecord = logRecords[0];
- var otlpLogRecord = logRecord.ToOtlpLog(sdkLimitOptions);
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.NotNull(otlpLogRecord);
Assert.Equal(1u, otlpLogRecord.DroppedAttributesCount);
@@ -657,7 +695,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsFalse_DoesNotContainScopeAttribu
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
var actualScope = TryGetAttribute(otlpLogRecord, expectedScopeKey);
Assert.Null(actualScope);
}
@@ -692,7 +731,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_ContainsScopeAttributeStrin
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.Single(otlpLogRecord.Attributes);
var actualScope = TryGetAttribute(otlpLogRecord, scopeKey);
Assert.NotNull(actualScope);
@@ -731,7 +771,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_ContainsScopeAttributeBoolV
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.Single(otlpLogRecord.Attributes);
var actualScope = TryGetAttribute(otlpLogRecord, scopeKey);
Assert.NotNull(actualScope);
@@ -782,7 +823,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_ContainsScopeAttributeIntVa
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.Single(otlpLogRecord.Attributes);
var actualScope = TryGetAttribute(otlpLogRecord, scopeKey);
Assert.NotNull(actualScope);
@@ -821,7 +863,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_ContainsScopeAttributeDoubl
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.Single(otlpLogRecord.Attributes);
var actualScope = TryGetAttribute(otlpLogRecord, scopeKey);
Assert.NotNull(actualScope);
@@ -860,7 +903,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_ContainsScopeAttributeDoubl
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.Single(otlpLogRecord.Attributes);
var actualScope = TryGetAttribute(otlpLogRecord, scopeKey);
Assert.NotNull(actualScope);
@@ -893,7 +937,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndScopeStateIsOfTypeString
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.NotNull(otlpLogRecord);
Assert.Empty(otlpLogRecord.Attributes);
}
@@ -928,7 +973,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndScopeStateIsOfPrimitiveT
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.NotNull(otlpLogRecord);
Assert.Empty(otlpLogRecord.Attributes);
}
@@ -960,7 +1006,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndScopeStateIsOfDictionary
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.Single(otlpLogRecord.Attributes);
var actualScope = TryGetAttribute(otlpLogRecord, scopeKey);
Assert.NotNull(actualScope);
@@ -999,7 +1046,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndScopeStateIsOfEnumerable
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
Assert.Single(otlpLogRecord.Attributes);
var actualScope = TryGetAttribute(otlpLogRecord, scopeKey);
Assert.NotNull(actualScope);
@@ -1039,7 +1087,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndMultipleScopesAreAdded_C
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
var allScopeValues = otlpLogRecord.Attributes
.Where(_ => _.Key == scopeKey1 || _.Key == scopeKey2)
.Select(_ => _.Value.StringValue);
@@ -1080,7 +1129,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndMultipleScopeLevelsAreAd
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
var allScopeValues = otlpLogRecord.Attributes
.Where(_ => _.Key == scopeKey1 || _.Key == scopeKey2)
.Select(_ => _.Value.StringValue);
@@ -1126,7 +1176,8 @@ public void ToOtlpLog_WhenOptionsIncludeScopesIsTrue_AndScopeIsUsedInLogMethod_C
// Assert.
var logRecord = logRecords.Single();
- var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
+ var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new());
+ var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
var allScopeValues = otlpLogRecord.Attributes
.Where(_ => _.Key == scopeKey1 || _.Key == scopeKey2)
.Select(_ => _.Value.StringValue);