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

OpenTelemetry.Exporter.Console: Print exception attributes according to SemConv #5351

Conversation

gregkalapos
Copy link
Member

Follow up from #5342 (comment) - and open-telemetry/semantic-conventions#689

Changes

ConsoleLogRecordExporter prints exception attributes according to the SemConv spec. With this PR, ConsoleLogRecordExporter behaves similarly to OtlpLogRecordTransformer from OpenTelemetry.Exporter.OpenTelemetryProtocol.

Open questions

  • I'm not familiar with previous design choices, but I really wonder why this is not done directly in /src/OpenTelemetry/Logs? E.g. in LogRecord.cs . With that, all exporters would benefit from this and the responsibility of filling the attributes according to the spec would not be the responsibility of the exporter.

Since I'm fairly new to the code-base I wanted to ask this before I do any such changes - let me know if you think it'd make sense to explore this and I'm happy to update the PR - or open a follow up.

Merge requirement checklist

  • CONTRIBUTING guidelines followed (license requirements, nullable enabled, static analysis, etc.)
  • Unit tests added/updated
  • Appropriate CHANGELOG.md files updated for non-trivial changes
  • Changes in public API reviewed (if applicable)

@gregkalapos gregkalapos marked this pull request as ready for review February 14, 2024 11:24
@gregkalapos gregkalapos requested a review from a team February 14, 2024 11:24
@reyang
Copy link
Member

reyang commented Feb 14, 2024

  • I'm not familiar with previous design choices, but I really wonder why this is not done directly in /src/OpenTelemetry/Logs? E.g. in LogRecord.cs . With that, all exporters would benefit from this and the responsibility of filling the attributes according to the spec would not be the responsibility of the exporter.

Since I'm fairly new to the code-base I wanted to ask this before I do any such changes - let me know if you think it'd make sense to explore this and I'm happy to update the PR - or open a follow up.

Perf. For exporters which do not need the exception string, we don't want the SDK to put pressure on GC heap.

@gregkalapos
Copy link
Member Author

  • I'm not familiar with previous design choices, but I really wonder why this is not done directly in /src/OpenTelemetry/Logs? E.g. in LogRecord.cs . With that, all exporters would benefit from this and the responsibility of filling the attributes according to the spec would not be the responsibility of the exporter.

Since I'm fairly new to the code-base I wanted to ask this before I do any such changes - let me know if you think it'd make sense to explore this and I'm happy to update the PR - or open a follow up.

Perf. For exporters which do not need the exception string, we don't want the SDK to put pressure on GC heap.

Yes, perf is definitely a valid point. However, I was reading the SemConv spec, which says:

Additional information about errors and/or exceptions that are associated with a log record MAY be included in the structured data in the Attributes section of the record. If included, they MUST follow the OpenTelemetry semantic conventions for exception-related attributes.

My interpretation of the If included, they MUST follow the OpenTelemetry semantic conventions was that if an exception is captured, then it's always in Attributes - as specified above.

But this is not yet part of this PR anyways, so I'm happy close this question.

@@ -81,23 +83,35 @@ public override ExportResult Export(in Batch<LogRecord> batch)
this.WriteLine($"{"LogRecord.Body:",-RightPaddingLength}{logRecord.Body}");
}

if (logRecord.Attributes != null)
if (logRecord.Attributes != null || logRecord.Exception != null)
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to add this check.

Copy link
Member Author

@gregkalapos gregkalapos Feb 19, 2024

Choose a reason for hiding this comment

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

The idea here is to treat exception attributes like any other attributes, since SemConv defines them as attributes.

With this, the output is something like this:

LogRecord.Attributes (Key:Value):
    OriginalFormat (a.k.a Body): You divided by 0
    exception.type: DivideByZeroException
    exception.message: Attempted to divide by zero.
    exception.stacktrace: System.DivideByZeroException: Attempted to divide by zero.
   at OpenTelemetry.Exporter.Console.Tests.ConsoleLogRecordExporterTest.VerifyExceptionAttributesAreWritten() in /Users/gregkalapos/repos/gregkalapos_opentelemetry-dotnet/test/OpenTelemetry.Exporter.Console.Tests/ConsoleLogRecordExporterTest.cs:line 39
LogRecord.Exception:               System.DivideByZeroException: Attempted to divide by zero.
   at OpenTelemetry.Exporter.Console.Tests.ConsoleLogRecordExporterTest.VerifyExceptionAttributesAreWritten() in /Users/gregkalapos/repos/gregkalapos_opentelemetry-dotnet/test/OpenTelemetry.Exporter.Console.Tests/ConsoleLogRecordExporterTest.cs:line 3

If we move the logging of exception attributes outside this block, then the LogRecord.Attributes (Key:Value): may not be printed (if no other attribute is present, and I'm not sure we can assume we'll always have any other attribute). Also the indentation of these attributes also matches other attributes' indentation on purpose.

Copy link
Member

Choose a reason for hiding this comment

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

I'm concerned about the readability of the exception callstack, create a tracking issue with my suggestions #5372.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with the concerns raised by @reyang here. YAML has better support for multi-line strings. @gregkalapos Would you be interested in working on updating the ConsoleExporter to print the data in yaml format?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I'd be happy to look into that - I also think it's a good idea. Let's handle it in the issue.

What do we do with this PR?

The issue with the readability of the exception callstack is not new, LogRecord.Exception is already printed a few lines below with this output (that's not changed in the PR):

LogRecord.Exception:               System.DivideByZeroException: Attempted to divide by zero.
   at OpenTelemetry.Exporter.Console.Tests.ConsoleLogRecordExporterTest.VerifyExceptionAttributesAreWritten() in /Users/gregkalapos/repos/gregkalapos_opentelemetry-dotnet/test/OpenTelemetry.Exporter.Console.Tests/ConsoleLogRecordExporterTest.cs:line 39

I see #5372 and this PR orthogonal.

Copy link
Contributor

Choose a reason for hiding this comment

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

The issue with the readability of the exception callstack is not new,
I see #5372 and this PR orthogonal.

I don't see them as orthogonal. The issue clearly talks about new things getting added with no well-defined structure. Just because the ConsoleExporter already has a readability issue, doesn't mean we keep making it worse.

What do we do with this PR?

I would say we should close it and invest in making ConsoleExporter better and extensible for newer changes in a well-defined way. I don't think anyone is blocked on ConsoleExporter not printing out the exception information with Semantic Convention attributes. As you previously mentioned, the exception information is already printed to console in some other format.

}
}

if (logRecord.Exception != null)
Copy link
Contributor

Choose a reason for hiding this comment

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

Move this if block outside of the if (logRecord.Attributes != null) check.

Copy link
Member Author

Choose a reason for hiding this comment

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

Same reasoning as above: #5351 (comment)

{
using var writer = new StringWriter();
System.Console.SetOut(writer);
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
Copy link
Contributor

Choose a reason for hiding this comment

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

Remove traces related code?

.Build();

using ILoggerFactory factory = LoggerFactory
.Create(builder => builder.AddOpenTelemetry(n =>
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Use more intuitive variable names.

Suggested change
.Create(builder => builder.AddOpenTelemetry(n =>
.Create(builder => builder.AddOpenTelemetry(logging =>

using ILoggerFactory factory = LoggerFactory
.Create(builder => builder.AddOpenTelemetry(n =>
{
n.AddConsoleExporter();
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
n.AddConsoleExporter();
logging.AddConsoleExporter();

.AddConsoleExporter()
.Build();

using ILoggerFactory factory = LoggerFactory
Copy link
Contributor

Choose a reason for hiding this comment

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

Since you have been using `var at other places, you could just use it for LoggerFactory and Logger as well to be consistent.

}));

ILogger logger = factory.CreateLogger("Program");
try
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of this setup, you could simply log an exception with a custom message to test this. Something like:

logger.LogError(default(EventId), new Exception("Exception Message"), null);

@gregkalapos
Copy link
Member Author

Thanks for the review @utpilla.

Full agreement on changes in ConsoleLogRecordExporterTest.cs - I pushed an update to that file.

Regarding the suggestions in ConsoleLogRecordExporter.cs, I added some context: #5351 (comment)

Copy link

codecov bot commented Feb 19, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 83.53%. Comparing base (6250307) to head (5ab6630).
Report is 110 commits behind head on main.

❗ Current head 5ab6630 differs from pull request most recent head c6cbb5f. Consider uploading reports for the commit c6cbb5f to get more accurate results

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #5351      +/-   ##
==========================================
+ Coverage   83.38%   83.53%   +0.15%     
==========================================
  Files         297      273      -24     
  Lines       12531    11384    -1147     
==========================================
- Hits        10449     9510     -939     
+ Misses       2082     1874     -208     
Flag Coverage Δ
unittests ?
unittests-Solution-Experimental 83.08% <100.00%> (?)
unittests-Solution-Stable 83.51% <100.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Coverage Δ
...metry.Exporter.Console/ConsoleLogRecordExporter.cs 68.35% <100.00%> (+68.35%) ⬆️

... and 77 files with indirect coverage changes

@gregkalapos gregkalapos requested a review from utpilla February 23, 2024 15:30
Copy link
Contributor

github-actions bot commented Mar 2, 2024

This PR was marked stale due to lack of activity and will be closed in 7 days. Commenting or Pushing will instruct the bot to automatically remove the label. This bot runs once per day.

@github-actions github-actions bot added the Stale Issues and pull requests which have been flagged for closing due to inactivity label Mar 2, 2024
@utpilla
Copy link
Contributor

utpilla commented Mar 4, 2024

#5351 (comment)

@utpilla utpilla closed this Mar 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Stale Issues and pull requests which have been flagged for closing due to inactivity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants