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

Alternative format for console exporter? #3990

Closed
cartermp opened this issue Jul 13, 2023 · 8 comments
Closed

Alternative format for console exporter? #3990

cartermp opened this issue Jul 13, 2023 · 8 comments
Labels

Comments

@cartermp
Copy link
Contributor

Related to: open-telemetry/opentelemetry-specification#3565

I also prefer a compact format most of the time. In JS the reason we decided on the verbose format was mainly because we were using it to develop the SDK itself and were frequently looking at specific data. It was never really meant for end users in the early days. In a lot of ways it still isn't beyond day 0 demos.

I'm curious how we might approach console output looking more readable for end-user local debugging scenarios.

Today, a span gets emitted looking (more or less) like this:

{
  "traceId": "3f1fe6256ea46d19ec3ca97b3409ad6d",
  "parentId": "f0b7b340dd6e08a7",
  "name": "middleware - query",
  "id": "41a27f331c7bfed3",
  "kind": 0,
  "timestamp": 1624982589722992,
  "duration": 417,
  "attributes": {
    "http.route": "/",
    "express.name": "query",
    "express.type": "middleware"
  },
  "status": { "code": 0 },
  "events": []
}

Some things that could improve perhaps:

  • Using a non-JSON format
  • alphabetize attribute names (including on events, links)
  • Right-aligning values so they're easier to scan
  • Removing anything that isn't considered necessary to know
  • Simplifying the display of some things
  • Formatting values
  • Including resource attributes (maybe? makes it longer)

Some ideas that come to mine for me are:

  1. Yaml
Span: middleware - query
  id:        41a27f331c7bfed3
  parentId:  f0b7b340dd6e08a7
  traceId:   3f1fe6256ea46d19ec3ca97b3409ad6d
  duration:  417ms
  kind:      Server
  status:    Unset
  attributes:
    express.name: query
    express.type: middleware
    http.route:   /
  1. Yaml again, but with resources:
Span: middleware - query
  id:        41a27f331c7bfed3
  parentId:  f0b7b340dd6e08a7
  traceId:   3f1fe6256ea46d19ec3ca97b3409ad6d
  duration:  417ms
  kind:      Server
  status:    Unset
  attributes:
    express.name: query
    express.type: middleware
    http.route:   /
  resource:
    telemetry.sdk.language: javascript
    telemetry.sdk.name:     opentelemetry
    telemetry.sdk.version:  1.12.0rc1
    telemetry.auto.version: 0.31b0
    service.name:           unknown_service
  1. Whatever it is the collector does:
Resource labels:
     -> telemetry.sdk.language: STRING(javascript)
     -> telemetry.sdk.name: STRING(opentelemetry)
     -> telemetry.sdk.version: STRING(1.12.0rc1)
     -> telemetry.auto.version: STRING(0.31b0)
     -> service.name: STRING(unknown_service)
InstrumentationLibrarySpans #0
InstrumentationLibrary app
Span #0
    Trace ID       : 3f1fe6256ea46d19ec3ca97b3409ad6d
    Parent ID      : f0b7b340dd6e08a7
    ID             : 41a27f331c7bfed3
    Name           : middleware - query
    Kind           : SPAN_KIND_SERVER
    Start time     : 2022-06-09 20:43:37.390134089 +0000 UTC
    End time       : 2022-06-09 20:43:37.390327687 +0000 UTC
    Status code    : STATUS_CODE_UNSET
    Status message :
Attributes:
     -> express.name: STRING(query)
     -> express.type: STRING(middleware)
     -> http.route: STRING(/)
  1. A less type-y version of the collector output
Span #0
    ID             : 41a27f331c7bfed3
    Parent ID      : f0b7b340dd6e08a7
    Trace ID       : 3f1fe6256ea46d19ec3ca97b3409ad6d
    Name           : middleware - query
    Kind           : Server
    Duration       : 417ms
    Status         : Unset
Attributes:
     -> express.name: query
     -> express.type: middleware
     -> http.route: /
Resource labels:
     -> telemetry.sdk.language: javascript
     -> telemetry.sdk.name:     opentelemetry
     -> telemetry.sdk.version:  1.12.0rc1
     -> telemetry.auto.version: 0.31b0
     -> service.name:           unknown_service
  1. Something similar to what .NET does:
Span.SpanId:             41a27f331c7bfed3
Span.ParentSpanId:       f0b7b340dd6e08a7
Span.TraceId:            54d084eba205a7a39398df4642be8f4a
Span.Name:               /
Span.Kind:               Server
Span.Duration:           417ms
Span.Attributes:
    express.name: query
    express.type: middleware
    http.route:   /
Resource associated with Span:
    telemetry.sdk.language: javascript
    telemetry.sdk.name:     opentelemetry
    telemetry.sdk.version:  1.12.0rc1
    telemetry.auto.version: 0.31b0
    service.name:           unknown_service
@plantfansam
Copy link

I'm pretty interested in a bring-your-own-formatter approach to the console exporter, and would happily contribute a PR. So approximately here, we might do something like:

  private _sendSpans(
    spans: ReadableSpan[],
    done?: (result: ExportResult) => void
  ): void {
    // Could also do consoleExporter.export(spans);
    for (const span of spans) {
      consoleExporter.export((this._exportInfo(span)));
    }
    if (done) {
      return done({ code: ExportResultCode.SUCCESS });
    }
  }

I believe we could pass the formatter to the ConsoleExporter when we construct it (new to TypeScript, very good chance I'm wrong!), like: new ConsoleSpanExporter(MyCoolConsoleFormatter).

@cartermp
Copy link
Contributor Author

cartermp commented Aug 8, 2023

Mmm, yeah, that could be pretty great. And we could define a "custom" format as the default that we use if there's nothing used, but otherwise defer to one the user configures.

@pichlermarc
Copy link
Member

I'm pretty interested in a bring-your-own-formatter approach to the console exporter, and would happily contribute a PR. So approximately here, we might do something like:

  private _sendSpans(
    spans: ReadableSpan[],
    done?: (result: ExportResult) => void
  ): void {
    // Could also do consoleExporter.export(spans);
    for (const span of spans) {
      consoleExporter.export((this._exportInfo(span)));
    }
    if (done) {
      return done({ code: ExportResultCode.SUCCESS });
    }
  }

I believe we could pass the formatter to the ConsoleExporter when we construct it (new to TypeScript, very good chance I'm wrong!), like: new ConsoleSpanExporter(MyCoolConsoleFormatter).

Hmm, I'd rather have a specified format that we, as the JS SIG implement. 🤔

I think anything one could do with a custom formatter, one can also do by implementing the rather simple SpanExporter interface; forceFlush() and shutdown() can be left empty. IMO adding a user-implementable formatter would only increase API surface without adding much value over implementing a new SpanExporter. 😅

It could also allow people to misuse of the formatter to write a custom exporter. 😨

@pichlermarc
Copy link
Member

I think a lot of it comes down to preference, I wrote down my thoughts on it:

Related to: open-telemetry/opentelemetry-specification#3565

I also prefer a compact format most of the time. In JS the reason we decided on the verbose format was mainly because we were using it to develop the SDK itself and were frequently looking at specific data. It was never really meant for end users in the early days. In a lot of ways it still isn't beyond day 0 demos.

I'm curious how we might approach console output looking more readable for end-user local debugging scenarios.

Today, a span gets emitted looking (more or less) like this:

{
  "traceId": "3f1fe6256ea46d19ec3ca97b3409ad6d",
  "parentId": "f0b7b340dd6e08a7",
  "name": "middleware - query",
  "id": "41a27f331c7bfed3",
  "kind": 0,
  "timestamp": 1624982589722992,
  "duration": 417,
  "attributes": {
    "http.route": "/",
    "express.name": "query",
    "express.type": "middleware"
  },
  "status": { "code": 0 },
  "events": []
}

Some things that could improve perhaps:

  • Using a non-JSON format

Yep, I think another reason that JSON was used is that it does not need extra dependencies to format, and it was quick and easy to do.

  • alphabetize attribute names (including on events, links)

I think that would help, yes. 🙂

  • Right-aligning values so they're easier to scan

👍

  • Removing anything that isn't considered necessary to know

This would highly depend on what's deemed necessary. As one is using the ConsoleExporter for troubleshooting, it could be very likely that the specific information you're trying to find is missing because it did not make the cut.

  • Simplifying the display of some things

Yep, writing out strings for enum values instead of integers would definitely help. I run into that every time, then I have to look it up. 😅

  • Formatting values

Hmm, which ones are you thinking about? 🤔

  • Including resource attributes (maybe? makes it longer)

Hmm, sometimes, one might want to troubleshoot resource detectors, so that's information that would help. Though it'd be great to know what users think about this. If they don't need it, It's probably fine to leave it out. 🤔

Some ideas that come to mine for me are:

  1. Yaml

I like this though it seems very compact.

  1. Yaml again, but with resources:

I like this one over 1; see reasoning about about resource attributes.

  1. Whatever it is the collector does:

Not sure about this. Typing info might differ from language to language I'd assume. 🤔

  1. A less type-y version of the collector output

I like this, probably also rather easy to implement.

  1. Something similar to what .NET does:

I think I'd prefer the others over this one. I like having the span-numbering of the collector format to figure out when a new span begins. 🤔

@plantfansam
Copy link

Hmm, I'd rather have a specified format that we, as the JS SIG implement. 🤔

I think anything one could do with a custom formatter, one can also do by implementing the rather simple SpanExporter interface; forceFlush() and shutdown() can be left empty. IMO adding a user-implementable formatter would only increase API surface without adding much value over implementing a new SpanExporter. 😅

It could also allow people to misuse of the formatter to write a custom exporter. 😨

Upon reflection, I think you're right - it's not particularly onerous to write your own ConsoleSpanExporter 😄

@github-actions
Copy link

github-actions bot commented Oct 9, 2023

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 14 days.

@github-actions github-actions bot added the stale label Oct 9, 2023
@pichlermarc pichlermarc removed the stale label Oct 9, 2023
Copy link

github-actions bot commented Jan 8, 2024

This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 14 days.

@github-actions github-actions bot added the stale label Jan 8, 2024
Copy link

This issue was closed because it has been stale for 14 days with no activity.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Feb 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants