Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ OpenTelemetry.Logs.LogRecordData.TraceFlags.get -> System.Diagnostics.ActivityTr
OpenTelemetry.Logs.LogRecordData.TraceFlags.set -> void
OpenTelemetry.Logs.LogRecordData.TraceId.get -> System.Diagnostics.ActivityTraceId
OpenTelemetry.Logs.LogRecordData.TraceId.set -> void
OpenTelemetry.Logs.LogRecordData.EventName.get -> string?
OpenTelemetry.Logs.LogRecordData.EventName.set -> void
OpenTelemetry.Logs.LogRecordSeverity
OpenTelemetry.Logs.LogRecordSeverity.Debug = 5 -> OpenTelemetry.Logs.LogRecordSeverity
OpenTelemetry.Logs.LogRecordSeverity.Debug2 = 6 -> OpenTelemetry.Logs.LogRecordSeverity
Expand Down
4 changes: 4 additions & 0 deletions src/OpenTelemetry.Api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Notes](../../RELEASENOTES.md).

## Unreleased

* Experimental (only in pre-release versions): Added the `EventName` property
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This should be added below the existing entries in the "Unreleased" section

to `LogRecordData`
([#6306](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6306))

* Added `AddLink(SpanContext, SpanAttributes?)` to `TelemetrySpan` to support
linking spans and associating optional attributes for advanced trace relationships.
([#6305](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6305))
Expand Down
5 changes: 5 additions & 0 deletions src/OpenTelemetry.Api/Logs/LogRecordData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ public DateTime Timestamp
/// </summary>
public string? Body { get; set; } = null;

/// <summary>
/// Gets or sets the name of the event associated with the log.
/// </summary>
public string? EventName { get; set; } = null;

internal static void SetActivityContext(ref LogRecordData data, Activity? activity)
{
if (activity != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ Notes](../../RELEASENOTES.md).
write position, resulting in gRPC protocol errors.
([#6280](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6280))

* If `EventName` is specified either through `ILogger` or the experimental
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good writeup!

log bridge API, it is exported as `EventName` by default instead of
`logrecord.event.name` which was previously behind the
`OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES` feature flag.
Note that exporting `logrecord.event.id` is still behind that same feature
flag. ([#6306](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6306))

## 1.12.0

Released 2025-Apr-29
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ internal sealed class ExperimentalOptions
{
public const string LogRecordEventIdAttribute = "logrecord.event.id";

public const string LogRecordEventNameAttribute = "logrecord.event.name";

public const string EmitLogEventEnvVar = "OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES";

public const string OtlpRetryEnvVar = "OTEL_DOTNET_EXPERIMENTAL_OTLP_RETRY";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ internal static class ProtobufOtlpLogFieldNumberConstants
internal const int LogRecord_Flags = 8;
internal const int LogRecord_Trace_Id = 9;
internal const int LogRecord_Span_Id = 10;
internal const int LogRecord_Event_Name = 12;

// SeverityNumber
internal const int Severity_Number_Unspecified = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,6 @@ internal static int WriteLogRecord(byte[] buffer, int writePosition, SdkLimitOpt
{
AddLogAttribute(state, ExperimentalOptions.LogRecordEventIdAttribute, logRecord.EventId.Id);
}

if (!string.IsNullOrEmpty(logRecord.EventId.Name))
{
AddLogAttribute(state, ExperimentalOptions.LogRecordEventNameAttribute, logRecord.EventId.Name!);
}
}

if (logRecord.Exception != null)
Expand Down Expand Up @@ -254,6 +249,11 @@ internal static int WriteLogRecord(byte[] buffer, int writePosition, SdkLimitOpt
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteFixed32WithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Flags, (uint)logRecord.TraceFlags);
}

if (logRecord.EventName != null)
{
otlpTagWriterState.WritePosition = ProtobufSerializer.WriteStringWithTag(otlpTagWriterState.Buffer, otlpTagWriterState.WritePosition, ProtobufOtlpLogFieldNumberConstants.LogRecord_Event_Name, logRecord.EventName!);
}

logRecord.ForEachScope(ProcessScope, state);

if (otlpTagWriterState.DroppedTagCount > 0)
Expand Down
2 changes: 2 additions & 0 deletions src/OpenTelemetry/.publicApi/Stable/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
OpenTelemetry.Logs.LogRecord.EventName.get -> string?
OpenTelemetry.Logs.LogRecord.EventName.set -> void
2 changes: 2 additions & 0 deletions src/OpenTelemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Notes](../../RELEASENOTES.md).

## Unreleased

* Added the `EventName` property to `LogRecord`. ([#6306](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6306))

## 1.12.0

Released 2025-Apr-29
Expand Down
9 changes: 9 additions & 0 deletions src/OpenTelemetry/Logs/LogRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,15 @@ public string? Body
set => this.Data.Body = value;
}

/// <summary>
/// Gets or sets the name of the event associated with the log.
/// </summary>
public string? EventName
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this? Export authors can access EventName via existing logRecord.EventId.Name (which they should already be doing). Concerns are it is more public API to maintain and it could introduce confusion in the API.

An alternative approach could be: a) Leave this out for now. b) Wait for EventId to land in the spec. c) Once that happens obsolete LogRecord.EventId and add spots for official EventName and EventId (whatever it ends up being).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. Do you know if there is currently a proposal to add EventId to the spec? I couldn't find anything in the repository for semantic conventions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None that is open/active. (open-telemetry/semantic-conventions#372 is the old one)
A lot has changed in the past few months (EventName being a top-level field is a new thing!), and I think it's best to create a new issue to propose adding EventId.Id to spec/convention

{
get => this.ILoggerData.EventId.Name;
set => this.ILoggerData.EventId = new EventId(this.ILoggerData.EventId.Id, value);
}

/// <summary>
/// Gets or sets the raw state attached to the log.
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions src/OpenTelemetry/Logs/LoggerSdk.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

using Microsoft.Extensions.Logging;
using OpenTelemetry.Internal;

namespace OpenTelemetry.Logs;
Expand Down Expand Up @@ -35,6 +36,7 @@ public override void EmitLog(in LogRecordData data, in LogRecordAttributeList at

logRecord.Data = data;
logRecord.ILoggerData = default;
logRecord.ILoggerData.EventId = new EventId(0, data.EventName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Use something to indicate 0 is a conscious default choice.
new EventId(default, data.EventName) does this work?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that makes sense.


logRecord.Logger = this;

Expand Down
4 changes: 1 addition & 3 deletions src/Shared/Proto/opentelemetry/proto/logs/v1/logs.proto
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,5 @@ message LogRecord {
// as an event.
//
// [Optional].
//
// Status: [Development]
string event_name = 12;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -342,19 +342,18 @@ public void CheckToOtlpLogRecordEventId(string? emitLogEventAttributes)
Assert.NotNull(otlpLogRecord);
Assert.Equal("Hello from tomato 2.99.", otlpLogRecord.Body.StringValue);

Assert.Equal("MyEvent10", otlpLogRecord.EventName);

// Event
otlpLogRecordAttributes = otlpLogRecord.Attributes.ToString();
if (emitLogEventAttributes == "true")
{
Assert.Contains(ExperimentalOptions.LogRecordEventIdAttribute, otlpLogRecordAttributes, StringComparison.Ordinal);
Assert.Contains("10", otlpLogRecordAttributes, StringComparison.Ordinal);
Assert.Contains(ExperimentalOptions.LogRecordEventNameAttribute, otlpLogRecordAttributes, StringComparison.Ordinal);
Assert.Contains("MyEvent10", otlpLogRecordAttributes, StringComparison.Ordinal);
}
else
{
Assert.DoesNotContain(ExperimentalOptions.LogRecordEventIdAttribute, otlpLogRecordAttributes, StringComparison.Ordinal);
Assert.DoesNotContain(ExperimentalOptions.LogRecordEventNameAttribute, otlpLogRecordAttributes, StringComparison.Ordinal);
}
}

Expand Down Expand Up @@ -1478,6 +1477,49 @@ public void LogRecordLoggerNameIsExportedWhenUsingBridgeApi(string? loggerName,
Assert.Equal(expectedScopeName, request.ResourceLogs[0].ScopeLogs[0].Scope?.Name);
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void LogRecordEventNameIsExportedWhenUsingBridgeApi(bool emitEventName)
{
LogRecordAttributeList attributes = default;
attributes.Add("name", "tomato");
attributes.Add("price", 2.99);
attributes.Add("{OriginalFormat}", "Hello from {name} {price}.");

var logRecords = new List<LogRecord>();

using (var loggerProvider = Sdk.CreateLoggerProviderBuilder()
.AddInMemoryExporter(logRecords)
.Build())
{
var logger = loggerProvider.GetLogger();

logger.EmitLog(new LogRecordData
{
Body = "test body",
EventName = emitEventName ? "test event" : null,
});
}

Assert.Single(logRecords);
var logRecord = logRecords[0];

OtlpLogs.LogRecord? otlpLogRecord = ToOtlpLogs(DefaultSdkLimitOptions, new ExperimentalOptions(), logRecord);

Assert.NotNull(otlpLogRecord);
Assert.Equal("test body", otlpLogRecord.Body.StringValue);

if (!emitEventName)
{
Assert.Empty(otlpLogRecord.EventName);
}
else
{
Assert.Equal("test event", otlpLogRecord.EventName);
}
}

[Fact]
public void LogSerialization_ExpandsBufferForLogsAndSerializes()
{
Expand Down