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

SpanEvent and Event through LogRecord should be "unified" #3406

Open
jsuereth opened this issue Apr 17, 2023 · 21 comments
Open

SpanEvent and Event through LogRecord should be "unified" #3406

jsuereth opened this issue Apr 17, 2023 · 21 comments
Labels
spec:logs Related to the specification/logs directory spec:trace Related to the specification/trace directory triage:accepted:needs-sponsor Ready to be implemented, but does not yet have a specification sponsor

Comments

@jsuereth
Copy link
Contributor

What are you trying to achieve?

Whether or not a user leverages SpanEvent or LogRecord to fire events should be orthogonal to the representation of the data. If I decide to add an event to a Span, then I should have similar data-model to when I fire off an "unadorned" event via the Event API.

What did you expect to see?

Right now there are fields on LogRecord that do not exist on SpanEvent:

  • SeverityText
  • SeverityNumber
  • Body

I believe this need to be added to (or have a specified encoding in) SpanEvent.

Additional context.

I think we should not try to workaround the issue in particular domains, like: #2926

Instead, allowing events to flow as SpanEvent or LogEvent should both be viable choices.

@jsuereth jsuereth added spec:logs Related to the specification/logs directory spec:trace Related to the specification/trace directory labels Apr 17, 2023
@jkwatson
Copy link
Contributor

I don't think the as-of-yet-incomplete "event" API will support severities, or bodies. Just names and attributes, like our span events do.

@scheler
Copy link
Contributor

scheler commented Apr 18, 2023

  1. In Define the shape of a event by encapsulating the payload in event.data. #2926, we wanted to introduce the notion of payload for Events, via attribute event.data. It is for this payload that @jsuereth and @jack-berg recommend using LogRecord Body instead.
  2. The current Events API and Events SemConv do not talk about Severity. However, in case Events end up needing Severity the recommendation was to use the in-built fields in the LogRecord and not introduce new attributes. That is the reason for including SeverityNumber and SeverityText in this issue. Event API can continue to not have these until the use-cases emerge.
    @jsuereth ObservedTimestamp is another field in LogRecord that could be added to SpanEvent. Only the Context fields could be omitted.

@joaopgrassi
Copy link
Member

joaopgrassi commented Apr 18, 2023

Was it considered if we even need the SpanEvent in the long run? I already saw users getting confused on why "events" are shown in two places and questions as : When I use a span event vs when I use a log.

@jsuereth
Copy link
Contributor Author

@joaopgrassi I believe there was discussion here. The main (huge) difference right now is in how SAMPLING works between the two. Span Events are sampled exactly as Spans are. Log-based events tend to be sampled by severity / log-ingestion configuration.

I suspect we need to wait for the unification between these two channels before we could drop SpanEvents, and in practice I expect we'll have to deal with both for quite some time.

@tigrannajaryan
Copy link
Member

Duplicate/related to #622

@tedsuo
Copy link
Contributor

tedsuo commented Apr 26, 2023

Right now there are fields on LogRecord that do not exist on SpanEvent:

  • SeverityText
  • SeverityNumber
  • Body

Since SpanEvents are a name plus a bag of attributes, it is straight forward to make SpanEvents equivalent to logs. The SpanEvent.Name field can match the event.name log attribute. For log fields where there is no SpanEvent equivalent, we can define SpanEvent attributes using semantic conventions:

  • log.severity_text
  • log.severity_number
  • log.body
  • For writing non-event logs to SpanEvents, the SpanEvent.name can be log.

This would allow data recorded through either API to be emitted using either data model.

I do not recommend adding more fields to the SpanEvents data model, and I do not recommend adding additional API surface area for exposing additional fields on SpanEvents. This is due to the fact that tracing backends do not understand these fields, and would make no use of them.

Once we have a stable Event API and data model, I recommend that we deprecate the SpanEvents API. This will alleviate confusion. Instead of trying to explain why you would use one API versus another, we just say "SpanEvents are deprecated, use Events."

Under the hood, users can choose where they would like data to be recorded based on whether they have a unified backend, or a separate logging and tracing backend. The SDK can be configured to allow users to emit any data recorded through either API to either data model. This is where the above semantic conventions come into play: translating data from one model to another when you have two separate backends.

@jkwatson
Copy link
Contributor

Once we have a stable Event API and data model, I recommend that we deprecate the SpanEvents API. This will alleviate confusion. Instead of trying to explain why you would use one API versus another, we just say "SpanEvents are deprecated, use Events."

I don't know about this... A SpanEvent is explicitly associated to the span to which it is attached. An Event would only potentially be associated with a span via some unknown mechanism. Not all Events that are emitted in the course of a span's execution should be associated to the span, so how would we figure out when we do and do not make this association?

I do not recommend trying to make a SpanEvent and an Event the same thing. Although they are structurally similar, they are not semantically equivalent, and trying to force them to be the same will only lead to user confusion, I fear.

@trask
Copy link
Member

trask commented Apr 26, 2023

Not all Events that are emitted in the course of a span's execution should be associated to the span, so how would we figure out when we do and do not make this association?

it seems ok for the default to use the "current span" (you can still ignore the association in your backend event query), and you can opt-out with EventBuilder.setContext(Context.root())

Although they are structurally similar, they are not semantically equivalent

I agree with this. I think of SpanEvent as more semantically equivalent to a Log.

Instead of trying to explain why you would use one API versus another, we just say "SpanEvents are deprecated, use Events."

Maybe we refine this to be "SpanEvents are deprecated, use Events or Logs"?

@scheler
Copy link
Contributor

scheler commented Apr 27, 2023

For log fields where there is no SpanEvent equivalent, we can define SpanEvent attributes using semantic conventions:

  • log.severity_text
  • log.severity_number
  • log.body
  • For writing non-event logs to SpanEvents, the SpanEvent.name can be log.

What would be the type of value for the log.body attribute - any? So now it's between adding additional fields in SpanEvent vs allowing attribute values of type map?

This is due to the fact that tracing backends do not understand these fields, and would make no use of them.

I know very little about tracing backends, but do they understand SpanEvents as they exist today? Does adding additional fields make it worse?

@MSNev
Copy link
Contributor

MSNev commented Aug 22, 2023

Going over this it seems to me that there is an argument for #2994 to remove the domain and just have the event.name

@MSNev MSNev added this to Logs SIG Sep 20, 2023
@MSNev MSNev moved this to In Progress in Logs SIG Sep 20, 2023
@MSNev MSNev moved this from In Progress to Semantic Conventions in Logs SIG Sep 20, 2023
@MSNev MSNev moved this from What is an event to In progress in Logs SIG Sep 20, 2023
@MSNev MSNev moved this from In progress to Related in Logs SIG Sep 20, 2023
@austinlparker austinlparker added the triage:accepted:needs-sponsor Ready to be implemented, but does not yet have a specification sponsor label May 14, 2024
@tedsuo
Copy link
Contributor

tedsuo commented Jul 12, 2024

Circling back on this. Since we are coming to the end of the Event SIG and this is one of our last remaining issues, let's make a decision so that we can close the SIG down.

Representing Events as SpanEvents

Using the log namespace to define the semantic conventions for representing log fields appears to be straightforwards, except for the log.body attribute. Log body is an Any type that will regularly include nested data. Seems like there are two options.

log.body attribute is represented as as Any type
The advantage of this approach is that it has no additional overhead. There would be no need to expose the Any type in the SpanEvent API.

However, are there any tracing backends in existence that expect an Any type in a SpanEvent? It's not useful to send data that tracing backends do not support. However, all tracing backends could be updated to do something useful with this field. Is it safe to assume that backends would not create errors? What happens if you send Jaeger an Any field? We could assume that backends guard against Any and either drop it or serialize it.

log.body attribute is serialized as a string
Regardless of the type of Log Body, it is stringified as JSON. For the byte type, it is represented as a string with the prefix data:base64.

The advantage of this approach is that it ensures tracing backends do not drop this field. They can choose to deserialize it if they want to. The disadvantage is that there is overhead.

My recommendation is that we should serialize the body field when converting it to an attribute. According to the spec, using the Any type would be a breaking change. Since there's a way to do this without a breaking change, it seems to me that this is the correct decision. But I do not have a strong feeling about it.

Representing Logs as SpanEvents

Events are just LogRecords that require certain attributes to be present. Once we've defined how Events are converted to SpanEvents, it would be trivial to extend this definition to include converting any log to a SpanEvent. There could be an option in the SDK:

  • No conversion
  • Convert only Events
  • Convert all LogRecords

The only additional decision needed to convert all LogRecords would be the value of the SpanEvent Name field. LogRecords that are not Events do not have a name attribute. I propose the value of the Name field should just be log. Seems simple enough.

@trask
Copy link
Member

trask commented Aug 1, 2024

Representing Events as SpanEvents

is this only needed for backwards compatibility, i.e. so we can move existing SpanEvents over to Events?

if so, then we could drop the need to convert (log) event body (since existing SpanEvents don't have a body)

it also would solve the problem of what to do with (log) events which aren't linked to a span (since existing SpanEvents are all linked to a span)

@tigrannajaryan
Copy link
Member

Please also consider adding the Name field to LogRecord. We have in Span Events and we needed it for generic events and added an event.name semconv for it. It will be a backward compatible addition, existing LogRecords will simply have the Name empty and event.name is experimental so we can remove it and replace by Name.

@tedsuo
Copy link
Contributor

tedsuo commented Aug 23, 2024

@tigrannajaryan oh man I would have loved name to be a field a year ago, because I agree that this concept is part of the structure of OTLP. But at this late stage I'm concerned that it would be burdensome. So we have officially switched sides on this issue. 😄

@lmolkova
Copy link
Contributor

Having first-class Name in the LogRecord would eliminate the last difference between logs and events and I feel it'd simplify a lot of things, but I expect @tedsuo will object (and I respect it)

@MSNev
Copy link
Contributor

MSNev commented Aug 23, 2024

and event.name is experimental so we can remove it and replace by Name.

We should NOT remove the event.name attribute as this explicitly calls out that the log record is representing an event and is not just a generic log record.

Whether or not there is a need for another generic log record name attribute should NOT be conflated with the need to explicitly call out that an event is being sent.

@lmolkova
Copy link
Contributor

lmolkova commented Aug 23, 2024

We should NOT remove the event.name attribute as this explicitly calls out that the log record is representing an event and is not just a generic log record.

The non-empty Name conveys the same message.

But it's an important point - if an event is just a named log record, why do we need two notions? I've been in several discussions this week where some people assumed that logs and events are different things and other people assumed that they are the same, but events are named.

Are they different? If so, we need to explain it better (at least provide guidance when someone would report an event vs named log).
If they are the same, let's remove unnecessary notion and simplify things.

@MSNev
Copy link
Contributor

MSNev commented Aug 26, 2024

They are not the same thing and should not be considered to be the same, events are just "reusing" a Log record as a transport. This entire discussion (Span / Log event unification) is (I believe) also highlighting that the general concept of an event is separate to its actual "transport" mechanism used.

As defined in the Sem conv definition of Events

Semantically, an Event is a named occurrence at an instant in time. It signals that "this thing happened at this time" and provides additional specifics about the occurrence.

And as such they SHOULD be treated differently to just a log generic record.

Now "IF" as part of "transporting" the event via a Log Record the semantic convention for any "Log Name" was "defined" that it is itself namespaced and that an event is defined as being "prefixed" as event.<event.name> then technically that could achieve the same thing, with a potential processing advantage that any backend would not need to deserialize all of the attributes to "find" one called event.name to determine that it's an event. But "just" simply "moving" the existing event.name to a log name verbatim (I believe) will cause (bridging) issues and that is the foundation on my objection to "removing" event.name. Would this "stop" issues -- no, unless the semconv / spec was / is defined from the outset to be namespaced.

The non-empty Name conveys the same message.

This is problematic as I would (assume) that there is (or would be) some log bridge that wants to translate some log "name" from some logging system that would want to use a "Log Name".

Now "IF" the semantic convention for any "Log Name" was to "redefine" that any possible Log Name which identified an event WAS "prefixed" as event.<event.name> then technically that could achieve the same thing, so that any backend would not need to deserialize all of the attributes to "find" one called event.name to determine that it's an event. But "just" simply "moving" the existing event.name to a log name verbatim (I believe) will cause (bridging) issues

@trask
Copy link
Member

trask commented Aug 26, 2024

if an event is just a named log record, why do we need two notions?

I'm getting more comfortable with the idea that an event is just a named log record

At the same time, keeping the separate notion of event could have value

  • it could help explain the OpenTelemetry vision by separating the desired (events) from the more legacy (logs)
  • it allows us to give users a first-class OpenTelemetry Event API (promoting our vision), while side-stepping the contentiousness of introducing something called a Logging API

@MSNev
Copy link
Contributor

MSNev commented Aug 26, 2024

Ok, I just asked CoPilot to give me a list of logging systems that support each log record having a "name" (so the potential bridge situation) and this is the list it gave (they are possibly wrong and depending on the existing bridge may not exist), but these are the "potential" name clashing items that I would be concerned about.

Several logging systems allow you to send a “name” with each log record, which can be very useful for categorizing and filtering logs. Here are a few examples:

@lmolkova
Copy link
Contributor

lmolkova commented Aug 27, 2024

named loggers are not related to named log.

Logger name goes to the instrumentation scope. Logger name is used for filtering for the category (e.g. enable all logs from com.foo.MyClass with level INFO and above).

The named log record discussed in open-telemetry/semantic-conventions#1339 is a name of the event for this record.

If we create gen_ai events in OpenAI instrumentations using logging facades:

  • in .NET: scope name: OpenAI.ChatClient, event/log record name would be gen_ai.user.message
  • in Python: scope name: opentelemetry-instrumentation-openai.chat, event/log record name - gen_ai.user.message

Event/log record name identifies event globally (or users can choose to give custom events names that are unique within the scope - that's unfortunate for these users, but not the end of the world - they can also fix it).

So I don't understand the clashing concern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
spec:logs Related to the specification/logs directory spec:trace Related to the specification/trace directory triage:accepted:needs-sponsor Ready to be implemented, but does not yet have a specification sponsor
Projects
Status: Related
Status: Spec - Accepted
Development

No branches or pull requests