Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OTLP LogExporter to special case {OriginalFormat} to populate body #3182

Merged
Show file tree
Hide file tree
Changes from 3 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 @@ -2,9 +2,12 @@

## Unreleased

* LogExporter to correcly map Severity to OTLP.
* LogExporter to correctly map Severity to OTLP.
([#3177](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3177))

* LogExporter to special case {OriginalFormat} to populate
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* LogExporter to special case {OriginalFormat} to populate
* LogExporter to special case '{OriginalFormat}' to populate

Body. ([#3182](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3182))

## 1.2.0-rc5

Released 2022-Apr-12
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,26 @@ internal static OtlpLogs.LogRecord ToOtlpLog(this LogRecord logRecord)

// TODO: Add logRecord.CategoryName as an attribute

bool bodyPopulatedFromFormattedMessage = false;
if (logRecord.FormattedMessage != null)
{
otlpLogRecord.Body = new OtlpCommon.AnyValue { StringValue = logRecord.FormattedMessage };
bodyPopulatedFromFormattedMessage = true;
}

if (logRecord.StateValues != null)
{
foreach (var stateValue in logRecord.StateValues)
{
var otlpAttribute = stateValue.ToOtlpAttribute();
otlpLogRecord.Attributes.Add(otlpAttribute);
if (stateValue.Key.Equals("{OriginalFormat}") && !bodyPopulatedFromFormattedMessage)
cijothomas marked this conversation as resolved.
Show resolved Hide resolved
{
otlpLogRecord.Body = new OtlpCommon.AnyValue { StringValue = stateValue.Value as string };
}
else
{
var otlpAttribute = stateValue.ToOtlpAttribute();
otlpLogRecord.Attributes.Add(otlpAttribute);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,28 +225,82 @@ public void CheckToOtlpLogRecordSeverityLevelAndText(LogLevel logLevel)
}
}

[Fact]
public void CheckToOtlpLogRecordFormattedMessage()
[Theory]
[InlineData(true)]
[InlineData(false)]
public void CheckToOtlpLogRecordBodyIsPopulated(bool includeFormattedMessage)
{
var logRecords = new List<LogRecord>();
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder.AddOpenTelemetry(options =>
{
options.AddInMemoryExporter(logRecords);
options.IncludeFormattedMessage = true;
options.IncludeFormattedMessage = includeFormattedMessage;
options.ParseStateValues = true;
alanwest marked this conversation as resolved.
Show resolved Hide resolved
});
});

var logger = loggerFactory.CreateLogger("OtlpLogExporterTests");

// Scenario 1 - Using ExtensionMethods on ILogger.Log
logger.LogInformation("OpenTelemetry {Greeting} {Subject}!", "Hello", "World");
Assert.Single(logRecords);

var logRecord = logRecords[0];
var otlpLogRecord = logRecord.ToOtlpLog();

Assert.NotNull(otlpLogRecord);
Assert.Equal(logRecord.FormattedMessage, otlpLogRecord.Body.StringValue);
if (includeFormattedMessage)
{
Assert.Equal(logRecord.FormattedMessage, otlpLogRecord.Body.StringValue);
}
else
{
Assert.Equal("OpenTelemetry {Greeting} {Subject}!", otlpLogRecord.Body.StringValue);
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the "special" treatment of {OriginalFormat} key.

}

logRecords.Clear();

// Scenario 2 - Using the raw ILogger.Log Method
logger.Log(LogLevel.Information, default, "state", exception: null, (st, ex) => "Formatted Message");
Assert.Single(logRecords);

logRecord = logRecords[0];
otlpLogRecord = logRecord.ToOtlpLog();

Assert.NotNull(otlpLogRecord);
if (includeFormattedMessage)
{
Assert.Equal(logRecord.FormattedMessage, otlpLogRecord.Body.StringValue);
}
else
{
Assert.Null(otlpLogRecord.Body);
}

logRecords.Clear();

// Scenario 3 - Using the raw ILogger.Log Method, but with null
// formatter.
logger.Log(LogLevel.Information, default, "state", exception: null, formatter: null);
Assert.Single(logRecords);

logRecord = logRecords[0];
otlpLogRecord = logRecord.ToOtlpLog();

Assert.NotNull(otlpLogRecord);

// There is no formatter, so no way to populate Body.
// Exporter won't even attempt to do ToString() on State.
if (includeFormattedMessage)
{
Assert.Null(otlpLogRecord.Body);
}
else
Copy link
Member Author

Choose a reason for hiding this comment

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

intentionally making the same Assert on If..Else, to make it easy for readers :)

{
Assert.Null(otlpLogRecord.Body);
}
}

[Fact]
Expand Down