open-telemetry / opentelemetry-specification

Specifications for OpenTelemetry
https://opentelemetry.io
Apache License 2.0
3.69k stars 884 forks source link

Do we need a spec for console output format? #3565

Open tigrannajaryan opened 1 year ago

tigrannajaryan commented 1 year ago

Many (all?) language SDKs have a "console" exporter that allows outputting the produced telemetry to standard output. This is very useful for getting started, debugging, etc.

The spec does not define a format for this exporter and I think language maintainers usually come up with the own formats.

Should we define a format that all SDKs can implement uniformly?

We do define a file exporter format, but console likely has requirements that will make it different (i.e. human readability is likely a top priority).

Related to discussion about this in PHP repo: https://github.com/open-telemetry/opentelemetry-php/issues/1050

@open-telemetry/specs-approvers any thoughts?

yurishkuro commented 1 year ago

There two possible categories of output by console exporter, lossless data dump or a summary format like

exporting span id, trace id, name, attr count

tigrannajaryan commented 1 year ago

There two possible categories of output by console exporter, lossless data dump or a summary format like

exporting span id, trace id, name, attr count

Yes.

In Collector we have a human-readable, detailed (but probably ambiguous) text format: https://github.com/open-telemetry/opentelemetry-collector/tree/main/exporter/loggingexporter

PHP SDK's console exporter which I was reviewing recently uses json, which appears to be non-ambiguous, but also is not OTLP/JSON.

It may be worth checking to see what other SDKs do.

svrnm commented 1 year ago

big +1 to this, as it would also significantly improve the docs, right now the outputs per language look very different:

Having a consistent output would make debugging easier and also allow us (@open-telemetry/docs-approvers) to create some more consistent documentation and with that a better experience for the end-users.

To add this as an additional note, there is also no consistency on the name of that exporter (I see console, stdout, logging, ostream), which I am less worried about, but this is also reflected in the value I need to set console output via an environment variable.

arminru commented 1 year ago

Personally, I think it'd be nice to have but not necessary to consolidate the human-readable log output across all SDKs. They all contain pretty much the same information and it should be relatively straightforward to orient oneself quickly when switching between them.

One thing that should be normalized, however, is the representation of the Trace IDs and Span IDs. One might want to grep through their SDK and Collector logs based on a Trace or Span ID and would therefore need to know about the different representations being used and convert between all possible options to grep them in parallel, which would be very cumbersome.

Seems like the following representations are currently used as per the examples that @svrnm (thank you!) gathered above:

JS (lowercase hex string)

  "traceId": "3f1fe6256ea46d19ec3ca97b3409ad6d",
  "parentId": "f0b7b340dd6e08a7",
  "id": "41a27f331c7bfed3",

Erlang (decimal)

{span,64480120921600870463539706779905870846,11592009751350035697,[],
    undefined,<<"/">>,server,-576460731933544855,-576460731890088522,

Java (lowercase hex string)

70c2f04ec863a956e9af975ba0d983ee 7fd145f5cda13625 INTERNAL

Python (lowercase hex string with a 0x prefix)

    "trace_id": "0xdcd253b9501348b63369d83219da0b14",
    "span_id": "0x886c05bc23d2250e",
  "parent_id": null,

C++ (lowercase hex string)

  trace_id      : 05eec7a55d3544434265dad89d7fe96f
  span_id       : 45fb62c58c907f05
  parent_span_id: 0000000000000000

I think going with a lowercase hex string (either with or without the 0x prefix) would be most practical.

dyladan commented 1 year ago

One big advantage is that the output for language SDKs is typically displayed in a format the language developers are already used to seeing. For example in Ruby the => syntax for maps is quite common but a JS developer would find it quite weird. Another advantage is that it discourages people from trying to programmatically consume the console output.

There are several things that could be specified and we can do all or none of them:

  1. What fields are exported. Do we export everything possible? Do we want to define some verbosity levels?
  2. What format are IDs exported in? In at least erlang/elixir trace and span IDs are exported as integers rather than hex making it difficult to quickly see if the same ID is appearing in your collector output for example.
  3. What is the overall structure of the data? JSON, YAML, tabular, et cetera. Is it meant to be human readable, machine readable, or both?

Personally most of the time I'm using the console logger as a debugging tool just to see that spans/metrics/logs are being collected and exported at all. Usually I don't care about most of the data there. Sometimes, when I am developing instrumentation I care about a specific set of attributes. There are many attributes like trace flags that I almost never care about.

Here's what I would suggest we specify:

  1. A minimum set of data that a console exporter should display. If an implementation wants to display more then fine, possibly configured with a verbosity flag. It MUST be possible to see all data attributes
  2. IDs are displayed as hex in order to make comparison between SDKs and collector more easily

I would not specify the structure of the overall object itself such as JSON/YAML/etc. I would leave a non-normative hint that the target audience is developers of the language debugging their telemetry and that the data should be in a format that users of that programming language are likely to be regularly familiar with.

cartermp commented 1 year ago

Hmmm. I like the idea of language-specific idioms. I think the main challenge isn't one of uniformity, but of verbosity. Some languages (like .NET) use a nice and compact format. Others (like JS and Python) do not, so it's harder to scan for things.

dyladan commented 1 year ago

Hmmm. I like the idea of language-specific idioms. I think the main challenge isn't one of uniformity, but of verbosity. Some languages (like .NET) use a nice and compact format. Others (like JS and Python) do not, so it's harder to scan for things.

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.

cartermp commented 1 year ago

Makes sense. I think I'd be unambiguously in favor of the spec offering general guidance on readability/compactness of outputs. If it's a blessed path + there's some general guidelines to follow, then that's a nice thing for outside contributors to pick up as a pure value-add.