-
Notifications
You must be signed in to change notification settings - Fork 889
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
Conversation
@@ -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 |
There was a problem hiding this comment.
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.
@open-telemetry/specs-logs-approvers PTAL. |
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 |
There was a problem hiding this comment.
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:
- Timestamp
- Observed Timestamp
- Context that contains the TraceContext
- ...
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
Closing in favor of #3354. |
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>
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>
Related to #3268.
The log SDK is inconsistent with
Context
:LogRecordProcessor#onEmit
's acceptscontext
andReadWriteLogRecord
as arguments, yetReadWriteLogRecord
provides access toContext
, making thecontext
argument appear unnecessary. Additionally,ReadableLogRecord
says receivers have access toContext
.This is incorrect. It's important that
ReadWriteLogRecord
andReadableLogRecord
only have access toTraceContext
, not the fullContext
, since we need to release references to the fullContext
ASAP to allow GC. This was the original intent behind makingcontext
an argument inLogRecordProcessor#onEmit
rather than relying on accessing it viaReadWriteLogRecord
.This PR resolves this inconsistency by clarifying that
ReadWriteLogRecord
andReadableLogRecord
only can accessTraceContext
.