opentelemetry-dotnet icon indicating copy to clipboard operation
opentelemetry-dotnet copied to clipboard

[bug] Body and the {OriginalFormat} attribute of LogRecord data don't work together when using logging bridge API.

Open juliuskoval opened this issue 10 months ago • 4 comments

Package

OpenTelemetry.Exporter.OpenTelemetryProtocol

Package Version

Package Name Version
OpenTelemetry.Exporter.OpenTelemetryProtocal 1.11.0-rc.1

Runtime Version

net9.0

Description

If I populate the Body property of the LogRecordData that I'm trying to emit with the formatted message and create a LogRecordAttributeList with the {OriginalFormat} attribute and pass it to the EmitLog method, the body of the exported log will be the value of {OriginalFormat} and the attribute itself as well as the Body of the LogRecordData won't be there.

Steps to Reproduce

using OpenTelemetry.Logs;

#pragma warning disable OTEL1001
using var provider = Sdk
    .CreateLoggerProviderBuilder()
    .AddOtlpExporter()
    .Build();
    
var logger = provider.GetLogger();

var data = new LogRecordData
{
    Body = "formatted message"
};

var attributes = new LogRecordAttributeList { { "{OriginalFormat}", "original format" } };

logger.EmitLog(data, attributes);

Thread.Sleep(10000);

Expected Result

The body of the exported log will be the Body property of the LogRecordData that I emitted and there will be the {OriginalFormat} attribute.

Actual Result

See description

Additional Context

No response

juliuskoval avatar Jan 27 '25 19:01 juliuskoval

Question...

var attributes = new LogRecordAttributeList { { "{OriginalFormat}", "original format" } };

Why are you doing this? {OriginalFormat} is an ILogger thing. It has nothing to do with the log bridge API.

Let's say we want to bridge some logging library into OTel. It supports a formatted message and a message template.

This would be more correct usage of the log bridge:

var data = new LogRecordData
{
    Body = "This is a log bridge from some logging library for requestId = 1"
};

var attributes = new LogRecordAttributeList
{ 
   { "dotnet.logging_library_name.template", "This is a log bridge from some logging library for requestId = {RequestId}" }
};

OTLP exporter would send both without issue.

CodeBlanch avatar Jan 29 '25 20:01 CodeBlanch

I know {OriginalFormat} isn't mentioned in the definition of the log bridge API, but I guess when I was making the NLog library I didn't find a name for log templates in the semantic conventions, so I wanted to mimic the behavior of Microsoft's ILogger to make things consistent between it and NLog. But ultimately I think it's a valid use case regardless of my motivation and the OTLP exporter doesn't allow it.

juliuskoval avatar Jan 29 '25 21:01 juliuskoval

Make your own name 😄 We own the dotnet prefix, really. So dotnet.nlog.template would be fine. Anything with the prefix dotnet.nlog we should be able to drive the semantic conventions.

Strictly speaking, {OriginalFormat} shouldn't be in the OTLP exporter at all. This is a violation of spec! Sort of an evolutionary mistake. dotnet.ilogger.template or something would have been more appropriate and it should be added by the SDK doing the ilogger bridge.

@alanwest What are your thoughts here?

CodeBlanch avatar Jan 29 '25 23:01 CodeBlanch

But ultimately I think it's a valid use case regardless of my motivation and the OTLP exporter doesn't allow it.

I agree that this is a bug and it should be a valid use case, however it is unlikely something we can resolve in the near term.

I also agree with @CodeBlanch and recommend steering clear of using {OriginalFormat} for your use case. This was an ILogger implementation detail that slipped into the OTLP exporter.

I'm personally not keen on using dotnet. as a prefix. I think something like nlog.template would be more inline with what we have defined for other .NET specific frameworks. For example, there are semantic conventions defined for SignalR which leverages a signalr. prefix for attribute names. That said, since the NLog.Targets.OpenTelemetryProtocol library does not exist within the OpenTelemetry organization, so it's not strictly governed by the semantic conventions, but I would highly recommend using the semantic conventions as a guide.

alanwest avatar Jan 30 '25 00:01 alanwest