[otlp] Add log exception attributes under feature flag (#4892)
Co-authored-by: Cijo Thomas <cijo.thomas@gmail.com>
This commit is contained in:
parent
b0038ae9b3
commit
c18ff6593a
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
// <copyright file="ExperimentalOptions.cs" company="OpenTelemetry Authors">
|
||||
// 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.
|
||||
// </copyright>
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether log exception attributes should be exported.
|
||||
/// </summary>
|
||||
public bool EmitLogExceptionAttributes { get; set; } = false;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// <copyright file="LogRecordExtensions.cs" company="OpenTelemetry Authors">
|
||||
// <copyright file="OtlpLogRecordTransformer.cs" company="OpenTelemetry Authors">
|
||||
// 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 @@ using OtlpResource = OpenTelemetry.Proto.Resource.V1;
|
|||
|
||||
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<LogRecord> logRecordBatch)
|
||||
{
|
||||
var request = new OtlpCollector.ExportLogsServiceRequest();
|
||||
|
||||
var resourceLogs = new OtlpLogs.ResourceLogs
|
||||
{
|
||||
Resource = processResource,
|
||||
|
|
@ -43,16 +54,18 @@ internal static class LogRecordExtensions
|
|||
|
||||
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 class LogRecordExtensions
|
|||
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,15 +117,15 @@ internal static class LogRecordExtensions
|
|||
{
|
||||
otlpLogRecord.AddStringAttribute(nameof(logRecord.EventId.Name), logRecord.EventId.Name, attributeValueLengthLimit, attributeCountLimit);
|
||||
}
|
||||
|
||||
if (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);
|
||||
}
|
||||
*/
|
||||
|
||||
if (this.experimentalOptions.EmitLogExceptionAttributes && logRecord.Exception != null)
|
||||
{
|
||||
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 class LogRecordExtensions
|
|||
}
|
||||
else if (OtlpKeyValueTransformer.Instance.TryTransformTag(attribute, out var result, attributeValueLengthLimit))
|
||||
{
|
||||
otlpLogRecord.AddAttribute(result, attributeCountLimit);
|
||||
AddAttribute(otlpLogRecord, result, attributeCountLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -183,7 +196,7 @@ internal static class LogRecordExtensions
|
|||
{
|
||||
if (OtlpKeyValueTransformer.Instance.TryTransformTag(scopeItem, out var result, attributeValueLengthLimit))
|
||||
{
|
||||
otlpLog.AddAttribute(result, attributeCountLimit);
|
||||
AddAttribute(otlpLog, result, attributeCountLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -198,7 +211,7 @@ internal static class LogRecordExtensions
|
|||
}
|
||||
|
||||
[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 @@ internal static class LogRecordExtensions
|
|||
}
|
||||
|
||||
[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<string, object>(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<string, object>(key, value);
|
||||
if (OtlpKeyValueTransformer.Instance.TryTransformTag(attributeItem, out var result))
|
||||
{
|
||||
logRecord.AddAttribute(result, maxAttributeCount);
|
||||
AddAttribute(logRecord, result, maxAttributeCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -30,8 +30,8 @@ namespace OpenTelemetry.Exporter;
|
|||
/// </summary>
|
||||
internal sealed class OtlpLogExporter : BaseExporter<LogRecord>
|
||||
{
|
||||
private readonly SdkLimitOptions sdkLimitOptions;
|
||||
private readonly IExportClient<OtlpCollector.ExportLogsServiceRequest> exportClient;
|
||||
private readonly OtlpLogRecordTransformer otlpLogRecordTransformer;
|
||||
|
||||
private OtlpResource.Resource processResource;
|
||||
|
||||
|
|
@ -58,8 +58,6 @@ internal sealed class OtlpLogExporter : BaseExporter<LogRecord>
|
|||
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 sealed class OtlpLogExporter : BaseExporter<LogRecord>
|
|||
{
|
||||
this.exportClient = exporterOptions.GetLogExportClient();
|
||||
}
|
||||
|
||||
this.otlpLogRecordTransformer = new OtlpLogRecordTransformer(sdkLimitOptions, new());
|
||||
}
|
||||
|
||||
internal OtlpResource.Resource ProcessResource => this.processResource ??= this.ParentProvider.GetResource().ToOtlpResource();
|
||||
|
|
@ -90,11 +90,9 @@ internal sealed class OtlpLogExporter : BaseExporter<LogRecord>
|
|||
// 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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
Assert.Single(logRecords);
|
||||
|
||||
logRecord = logRecords[0];
|
||||
otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
|
||||
otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
|
||||
|
||||
Assert.NotNull(otlpLogRecord);
|
||||
|
||||
|
|
@ -481,7 +496,7 @@ public class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
Assert.Single(logRecords);
|
||||
|
||||
logRecord = logRecords[0];
|
||||
otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
|
||||
otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecord);
|
||||
|
||||
Assert.NotNull(otlpLogRecord);
|
||||
|
||||
|
|
@ -489,9 +504,10 @@ public class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
Assert.Equal("state", otlpLogRecord.Body.StringValue);
|
||||
}
|
||||
|
||||
/*
|
||||
[Fact]
|
||||
public void CheckToOtlpLogRecordExceptionAttributes()
|
||||
[Theory]
|
||||
[InlineData("true")]
|
||||
[InlineData("false")]
|
||||
public void CheckToOtlpLogRecordExceptionAttributes(string emitExceptionAttributes)
|
||||
{
|
||||
var logRecords = new List<LogRecord>();
|
||||
using var loggerFactory = LoggerFactory.Create(builder =>
|
||||
|
|
@ -507,20 +523,40 @@ public class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
var logRecord = logRecords[0];
|
||||
var loggedException = logRecord.Exception;
|
||||
var otlpLogRecord = logRecord.ToOtlpLog(DefaultSdkLimitOptions);
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddInMemoryCollection(new Dictionary<string, string> { [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.AttributeExceptionStacktrace, otlpLogRecordAttributes);
|
||||
Assert.Contains(logRecord.Exception.ToInvariantString(), otlpLogRecordAttributes);
|
||||
Assert.Contains(SemanticConventions.AttributeExceptionMessage, otlpLogRecordAttributes);
|
||||
Assert.Contains(logRecord.Exception.Message, 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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 class OtlpLogExporterTests : Http2UnencryptedSupportTests
|
|||
|
||||
// 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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue