Skip to content

[feature request] Provide an OpenTelemetry console exporter that is a drop in replacement for the .NET console logger #2848

Open
@sgryphon

Description

@sgryphon

Component

New component: OpenTelemetry.Exporter.SimpleExporter

Is your feature request related to a problem?

Developers may be familiar with the built in console logger in .NET, which is enabled by default. This has a fairly simple layout, with colour indicators.

Changing to OpenTelemetry, there is a console exporter, but it has a fairly verbose output, that is not very useful (e.g. only few outputs can fit on a page).

What is the expected behavior?

If you run a default .NET application, it includes a console logger that outputs two lines per event, with a coloured prefix for info/warn/fail etc, a colon, then the logger name (e.g. Microsoft.Hosting.Lifetime), and the event ID (in square brackets). The next line contains the text of the log message.

It would be good to have a SimpleConsoleExporter that can be used as a drop-in replacement. (There is an existing console exporter, but it is fairly verbose and appears more designed for debugging OTel than as a generally useful logger).

The format should be the same as the .NET logger, although the Trace ID, which is a key component of OpenTelemetry should be added to the end of the first line.

warn: Demo.WebApp.Controllers.WeatherForecastController[4001] f0fe5fb5aa75bf532b5fb464c7f7df5f
      TRACING DEMO: WebApp API weather forecast request forwarded

Which alternative solutions or features have you considered?

The existing OpenTelemetry console exporter.

This could also be implemented by different Formatters for the existing OpenTelemetry.Exporter.Console (similar to how the .NET logger has different formatters). e.g. this format would be format=simple and the original could be format=detailed

Additional context

Existing .NET console logger

Source code: https://github.com/dotnet/runtime/tree/main/src/libraries/Microsoft.Extensions.Logging.Console

Example output:

PS C:\Code\dotnet-distributed-tracing-examples\src\1-basic> dotnet run --project Demo.WebApp --urls "https://*:44302"
Using launch settings from Demo.WebApp\Properties\launchSettings.json...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://[::]:44302
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\Code\dotnet-distributed-tracing-examples\src\1-basic\Demo.WebApp
fail: Microsoft.AspNetCore.SpaServices[0]
      Browserslist: caniuse-lite is outdated. Please run:
fail: Microsoft.AspNetCore.SpaServices[0]
        npx update-browserslist-db@latest
fail: Microsoft.AspNetCore.SpaServices[0]
        Why you should do it regularly: https://github.com/browserslist/update-db#readme
warn: Demo.WebApp.Controllers.WeatherForecastController[4001]
      TRACING DEMO: WebApp API weather forecast request forwarded
info: System.Net.Http.HttpClient.Default.LogicalHandler[100]
      Start processing HTTP request GET https://localhost:44301/WeatherForecast
info: System.Net.Http.HttpClient.Default.ClientHandler[100]
      Sending HTTP request GET https://localhost:44301/WeatherForecast
info: System.Net.Http.HttpClient.Default.ClientHandler[101]
      Received HTTP response headers after 242.112ms - 200
info: System.Net.Http.HttpClient.Default.LogicalHandler[101]
      End processing HTTP request after 249.9746ms - 200

Screen shot:

Image

Note that by default additional properties are not output (e.g. the TraceId), but if you enable "IncludeScopes", then scopes are output on a third line, separated by "=>". ASP.NET inserts the TraceId in the scope, so this will show it (although outside of ASP.NET this won't work, i.e. it's not directly outputting TraceID, just whatever values are in the scopes).

fail: Microsoft.AspNetCore.SpaServices[0]
        Why you should do it regularly: https://github.com/browserslist/update-db#readme
warn: Demo.WebApp.Controllers.WeatherForecastController[4001]
      => SpanId:674f52f50362c931, TraceId:f0fe5fb5aa75bf532b5fb464c7f7df5f, ParentId:0000000000000000 => ConnectionId:0HNDD80PUC6IU => RequestPath:/weatherforecast RequestId:0HNDD80PUC6IU:00000009 => Demo.WebApp.Controllers.WeatherForecastController.Get (Demo.WebApp)
      TRACING DEMO: WebApp API weather forecast request forwarded
info: System.Net.Http.HttpClient.Default.LogicalHandler[100]
      => SpanId:674f52f50362c931, TraceId:f0fe5fb5aa75bf532b5fb464c7f7df5f, ParentId:0000000000000000 => ConnectionId:0HNDD80PUC6IU => RequestPath:/weatherforecast RequestId:0HNDD80PUC6IU:00000009 => Demo.WebApp.Controllers.WeatherForecastController.Get (Demo.WebApp) => HTTP GET https://localhost:44301/WeatherForecast
      Start processing HTTP request GET https://localhost:44301/WeatherForecast
info: System.Net.Http.HttpClient.Default.ClientHandler[100]
      => SpanId:674f52f50362c931, TraceId:f0fe5fb5aa75bf532b5fb464c7f7df5f, ParentId:0000000000000000 => ConnectionId:0HNDD80PUC6IU => RequestPath:/weatherforecast RequestId:0HNDD80PUC6IU:00000009 => Demo.WebApp.Controllers.WeatherForecastController.Get (Demo.WebApp) => HTTP GET https://localhost:44301/WeatherForecast
      Sending HTTP request GET https://localhost:44301/WeatherForecast
info: System.Net.Http.HttpClient.Default.ClientHandler[101]
      => SpanId:674f52f50362c931, TraceId:f0fe5fb5aa75bf532b5fb464c7f7df5f, ParentId:0000000000000000 => ConnectionId:0HNDD80PUC6IU => RequestPath:/weatherforecast RequestId:0HNDD80PUC6IU:00000009 => Demo.WebApp.Controllers.WeatherForecastController.Get (Demo.WebApp) => HTTP GET https://localhost:44301/WeatherForecast
      Received HTTP response headers after 327.1163ms - 200
info: System.Net.Http.HttpClient.Default.LogicalHandler[101]
      => SpanId:674f52f50362c931, TraceId:f0fe5fb5aa75bf532b5fb464c7f7df5f, ParentId:0000000000000000 => ConnectionId:0HNDD80PUC6IU => RequestPath:/weatherforecast RequestId:0HNDD80PUC6IU:00000009 => Demo.WebApp.Controllers.WeatherForecastController.Get (Demo.WebApp) => HTTP GET https://localhost:44301/WeatherForecast
      End processing HTTP request after 339.3572ms - 200

Existing OpenTelemetry Console Exporter:

https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/src/OpenTelemetry.Exporter.Console

Example output:

LogRecord.Timestamp:               2023-09-15T06:07:03.5502083Z
LogRecord.CategoryName:            Program
LogRecord.Severity:                Info
LogRecord.SeverityText:            Information
LogRecord.Body:                    Food `{name}` price changed to `{price}`.
LogRecord.Attributes (Key:Value):
    name: artichoke
    price: 9.99
    OriginalFormat (a.k.a Body): Food `{name}` price changed to `{price}`.
LogRecord.EventId:                 344095174
LogRecord.EventName:               FoodPriceChanged

...

LogRecord.Timestamp:               2023-09-15T06:07:03.5683511Z
LogRecord.CategoryName:            Program
LogRecord.Severity:                Fatal
LogRecord.SeverityText:            Critical
LogRecord.Body:                    A `{productType}` recall notice was published for `{brandName} {productDescription}` produced by `{companyName}` ({recallReasonDescription}).
LogRecord.Attributes (Key:Value):
    brandName: Contoso
    productDescription: Salads
    productType: Food & Beverages
    recallReasonDescription: due to a possible health risk from Listeria monocytogenes
    companyName: Contoso Fresh Vegetables, Inc.
    OriginalFormat (a.k.a Body): A `{productType}` recall notice was published for `{brandName} {productDescription}` produced by `{companyName}` ({recallReasonDescription}).
LogRecord.EventId:                 1338249384
LogRecord.EventName:               FoodRecallNotice

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions