diff --git a/src/OpenTelemetry.Exporter.InMemory/AssemblyInfo.cs b/src/OpenTelemetry.Exporter.InMemory/AssemblyInfo.cs new file mode 100644 index 00000000000..f7775c1b9b8 --- /dev/null +++ b/src/OpenTelemetry.Exporter.InMemory/AssemblyInfo.cs @@ -0,0 +1,20 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#if !EXPOSE_EXPERIMENTAL_FEATURES +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests" + AssemblyInfo.PublicKey)] +#endif + +#if SIGNED +file static class AssemblyInfo +{ + public const string PublicKey = ", PublicKey=002400000480000094000000060200000024000052534131000400000100010051C1562A090FB0C9F391012A32198B5E5D9A60E9B80FA2D7B434C9E5CCB7259BD606E66F9660676AFC6692B8CDC6793D190904551D2103B7B22FA636DCBB8208839785BA402EA08FC00C8F1500CCEF28BBF599AA64FFB1E1D5DC1BF3420A3777BADFE697856E9D52070A50C3EA5821C80BEF17CA3ACFFA28F89DD413F096F898"; +} +#else +file static class AssemblyInfo +{ + public const string PublicKey = ""; +} +#endif diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md index 4b0d4a32a85..dcd24114fd1 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md @@ -15,6 +15,12 @@ will be automatically included in exports. ([#5258](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5258)) +* Updated `OtlpLogExporter` to set `body` on the data model from + `LogRecord.Body` if `{OriginalFormat}` attribute is NOT found and + `FormattedMessage` is `null`. This is typically the case when using the + experimental Logs Bridge API. + ([#5268](https://github.com/open-telemetry/opentelemetry-dotnet/pull/5268)) + ## 1.7.0 Released 2023-Dec-08 diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OtlpLogRecordTransformer.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OtlpLogRecordTransformer.cs index 3966efad9af..607f8fa5584 100644 --- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OtlpLogRecordTransformer.cs +++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/OtlpLogRecordTransformer.cs @@ -170,6 +170,14 @@ internal OtlpLogs.LogRecord ToOtlpLog(LogRecord logRecord) AddAttribute(otlpLogRecord, result, attributeCountLimit); } } + + // Supports setting Body directly on LogRecord for the Logs Bridge API. + if (otlpLogRecord.Body == null && logRecord.Body != null) + { + // If {OriginalFormat} is not present in the attributes, + // use logRecord.Body if it is set. + otlpLogRecord.Body = new OtlpCommon.AnyValue { StringValue = logRecord.Body }; + } } if (logRecord.TraceId != default && logRecord.SpanId != default) diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs index bcb88bdbdb8..3656dda54aa 100644 --- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs +++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpLogExporterTests.cs @@ -589,6 +589,63 @@ public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage) Assert.Equal("state", otlpLogRecord.Body.StringValue); } + [Theory] + [InlineData(true)] + [InlineData(false)] + public void LogRecordBodyIsExportedWhenUsingBridgeApi(bool isBodySet) + { + LogRecordAttributeList attributes = default; + attributes.Add("name", "tomato"); + attributes.Add("price", 2.99); + attributes.Add("{OriginalFormat}", "Hello from {name} {price}."); + + var logRecords = new List(); + + using (var loggerProvider = Sdk.CreateLoggerProviderBuilder() + .AddInMemoryExporter(logRecords) + .Build()) + { + var logger = loggerProvider.GetLogger(); + + logger.EmitLog(new LogRecordData() + { + Body = isBodySet ? "Hello world" : null, + }); + + logger.EmitLog(new LogRecordData(), attributes); + } + + Assert.Equal(2, logRecords.Count); + + var otlpLogRecordTransformer = new OtlpLogRecordTransformer(DefaultSdkLimitOptions, new()); + + var otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecords[0]); + + if (isBodySet) + { + Assert.Equal("Hello world", otlpLogRecord.Body?.StringValue); + } + else + { + Assert.Null(otlpLogRecord.Body); + } + + otlpLogRecord = otlpLogRecordTransformer.ToOtlpLog(logRecords[1]); + + Assert.Equal(2, otlpLogRecord.Attributes.Count); + + var index = 0; + var attribute = otlpLogRecord.Attributes[index]; + Assert.Equal("name", attribute.Key); + Assert.Equal("tomato", attribute.Value.StringValue); + + attribute = otlpLogRecord.Attributes[++index]; + Assert.Equal("price", attribute.Key); + Assert.Equal(2.99, attribute.Value.DoubleValue); + + Assert.Equal("Hello from {name} {price}.", otlpLogRecord.Body.StringValue); + } + [Fact] public void CheckToOtlpLogRecordExceptionAttributes() {