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

Resolve log SDK context inconsistencies #3350

Closed
wants to merge 2 commits into from

Conversation

jack-berg
Copy link
Member

Related to #3268.

The log SDK is inconsistent with Context: LogRecordProcessor#onEmit's accepts context and ReadWriteLogRecord as arguments, yet ReadWriteLogRecord provides access to Context, making the context argument appear unnecessary. Additionally, ReadableLogRecord says receivers have access to Context.

This is incorrect. It's important that ReadWriteLogRecord and ReadableLogRecord only have access to TraceContext, not the full Context, since we need to release references to the full Context ASAP to allow GC. This was the original intent behind making context an argument in LogRecordProcessor#onEmit rather than relying on accessing it via ReadWriteLogRecord.

This PR resolves this inconsistency by clarifying that ReadWriteLogRecord and ReadableLogRecord only can access TraceContext.

@jack-berg jack-berg requested review from a team March 29, 2023 17:55
@@ -235,9 +238,7 @@ therefore it SHOULD NOT block or throw exceptions.
* `logRecord` - a [ReadWriteLogRecord](#readwritelogrecord) for the
emitted `LogRecord`.
* `context` - the `Context` that the SDK determined (the explicitly
Copy link
Member Author

Choose a reason for hiding this comment

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

@CodeBlanch / @martinkuba we also chatted about whether this argument should be renamed to parentContext to match the trace SDK. I do not think we should do this. Tracing needs to differentiate between the parent context and the current span's context. Logs do not. The log context is just the context in which the record was recorded.

There's a similar concept in metrics where ExemplarFilter and ExemplarReservoir receive context arguments. The arguments are similarly called context, not parentContext, because there's no concept of parent in either logs or metrics.

@jack-berg
Copy link
Member Author

@open-telemetry/specs-logs-approvers PTAL.

Comment on lines +138 to +140
information added to the [LogRecord](bridge-api.md#logrecord), with the
exception that only [TraceContext](./data-model.md#trace-context-fields) is
available rather than [Context](../context/README.md). It MUST also be able to
Copy link
Member

Choose a reason for hiding this comment

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

Why is Context listed as a parameter of a LogRecord in the bridge API spec here? The LogRecord data model does not have a Context Field. It only has fields relevant to trace context (trace/span id and flags).

The API emits LogRecords using the LogRecord data model.

A function receiving this as an argument MUST be able to set the following parameters:

Shouldn't this just be

The API emits LogRecords using the LogRecord data model.

A function receiving this as an argument MUST be able to set the following parameters:

If this were the case, then it seems we would not require the clarification this PR is posing.

Copy link
Contributor

Choose a reason for hiding this comment

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

My understanding is that having the Context on the LogRecord is the mechanism to explicitly provide a Context per LogRecord to processors' OnEmit function.

Copy link
Member

Choose a reason for hiding this comment

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

That seems to differ from what has done with both traces and metrics. Take the Go SDK for example - which requires explicitly passing around context:

  • Example from the trace API: the tracer.Start API accepts context as a parameter.
  • Example from the metric API: the counter.Add API accepts context as a parameter.

I can only imagine that Go's eventual log bridge API would have an logger.Emit(ctx Context, log LogRecord) method also explicitly taking a context. Calling on @MrAlias, because like really... who am I to be attempting to represent Go? 😆

Speaking for .NET, though, the current context is simply available via ambient state, so we've no need to explicitly pass it around either on the LogRecord or as a parameter. This is what we've used with traces and metrics.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think that splitting out context into a separate argument for onEmit also makes sense, and avoids the need for the changes this PR makes to ReadWriteLogRecord and ReadableLogRecord.

@alanwest care to open up a PR with that suggestion? If folks prefer that solution, we can close this and move forward.

Copy link
Member

@tigrannajaryan tigrannajaryan Mar 31, 2023

Choose a reason for hiding this comment

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

@alanwest here is the Go draft prototype. Context is indeed the first parameter of Emit().

However Emit does not accept a LogRecord, but rather an option list. This mimics the Go Trace API. So, you could say that this is the idiomatic way to pass a context-associated LogRecord in Go.

Copy link
Member

Choose a reason for hiding this comment

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

One possible way to alter the Emit function description is to say that it may accept a LogRecord directly as a parameter or to accept the same information in some other form that is more idiomatic to the language (to allow what Go does).

Copy link
Member

@tigrannajaryan tigrannajaryan Mar 31, 2023

Choose a reason for hiding this comment

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

Here is another reference point, the Start Span function. All possible parameters (including the Context) are listed individually. I don't know if we want to to change Emit to also look like this in the spec (i.e. disaggregate LogRecord into separately listed parameters).

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't know if we want to to change Emit to also look like this in the spec (i.e. disaggregate LogRecord into separately listed parameters).

I think that's a decision individual languages can / should make. In java, we commonly use the builder pattern across tracing and metrics, and it makes sense for us to do the same for logs. The emit API ends up looking like:

logger
  .logRecordBuilder()
  .setSeverity(Severity.INFO)
  .setBody("A log message from a custom appender without a span")
  .setAttribute(AttributeKey.stringKey("key"), "value")
  .setContext(...)
  .emit()

Context is just another setter alongside the other LogRecord fields. In my read, this is conformant with the current version of the spec, and would also be conformant to a version where Context is a separate parameter.

Copy link
Member

@tigrannajaryan tigrannajaryan Mar 31, 2023

Choose a reason for hiding this comment

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

@jack-berg I agree with you. I think some of the confusion comes from the fact that in the spec we list LogRecord as just a single parameter and then there seems to be an expectation that this should be translated to a language API literally, and Emit() should become a function call with just one parameter. But we don't really do this neither in Java, nor in Go. The SDK developers translate the spec's English prose into idiomatic API designs and as part of that translation they can choose to e.g. disaggregate parameters logically spec-ed as one parameter into separate parameters.

Copy link
Member

Choose a reason for hiding this comment

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

Submitted #3354 as an alternative to this PR. It attempts to clarify that the spec does not require languages to literally have context as a parameter to the Emit() function.

@jack-berg
Copy link
Member Author

Closing in favor of #3354.

@jack-berg jack-berg closed this Apr 3, 2023
jack-berg pushed a commit that referenced this pull request Apr 8, 2023
Supersedes #3350

Clarifies the parameters for emitting a log record.

Context was particularly confusing. Context is not a property of the
`LogRecord` data model. Cleans up section of bridge API spec that seems
to suggest that Context is a field of `LogRecord`. Also, clarifies that
Context can be associated with an emitted LogRecord. We have similar
language in the trace API that leaves room for languages to achieve this
in an idiomatic way. See


https://github.com/open-telemetry/opentelemetry-specification/blob/d25734a47e6534a1bc8a52cb2bd51d42e987024b/specification/trace/api.md?plain=1#L365-L370

---------

Co-authored-by: Reiley Yang <reyang@microsoft.com>
carlosalberto pushed a commit to carlosalberto/opentelemetry-specification that referenced this pull request Oct 31, 2024
Supersedes open-telemetry#3350

Clarifies the parameters for emitting a log record.

Context was particularly confusing. Context is not a property of the
`LogRecord` data model. Cleans up section of bridge API spec that seems
to suggest that Context is a field of `LogRecord`. Also, clarifies that
Context can be associated with an emitted LogRecord. We have similar
language in the trace API that leaves room for languages to achieve this
in an idiomatic way. See


https://github.com/open-telemetry/opentelemetry-specification/blob/d25734a47e6534a1bc8a52cb2bd51d42e987024b/specification/trace/api.md?plain=1#L365-L370

---------

Co-authored-by: Reiley Yang <reyang@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants