-
Notifications
You must be signed in to change notification settings - Fork 867
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
Add a logging appender API #4917
Conversation
A couple of thoughts:
|
This README has references to using the |
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.
Few comments, but looks good!
...pi/src/main/java/io/opentelemetry/instrumentation/appender/api/GlobalLogEmitterProvider.java
Outdated
Show resolved
Hide resolved
...-appender-api/src/main/java/io/opentelemetry/instrumentation/appender/api/SdkLogEmitter.java
Outdated
Show resolved
Hide resolved
...ibrary/src/main/java/io/opentelemetry/instrumentation/log4j/v2_16/OpenTelemetryAppender.java
Show resolved
Hide resolved
discussed this with @anuraaga and this appender api is (for the most part) is not really an end-user api (just used for a few appenders), compared to the instrumentation api. although now thinking about it, the appender api may also be useful as a "event api" for end users to emit events. which could be a reason to rename "appender api" to "log emitter api"... (I'd like to gather feedback on these questions, but implement any renames/restructurings as follow-ups, so I can unblock #4927 and start writing some javaagent logging instrumentation in parallel) |
...pi/src/main/java/io/opentelemetry/instrumentation/appender/api/GlobalLogEmitterProvider.java
Outdated
Show resolved
Hide resolved
|
||
import io.opentelemetry.sdk.logs.SdkLogEmitterProvider; | ||
|
||
public final class DelegatingLogEmitterProvider implements LogEmitterProvider { |
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.
In the agent these Delegating...
classes will have to be loaded by the agent classloader (the api classes will be loaded by bootstrap), right? Does it make sense to at least put them into a separate package? (a separate module would probably be "cleaner", but that may be a bit too much for library instrumentations)
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.
oh no, this is absolutely right!
a separate module would probably be "cleaner", but that may be a bit too much for library instrumentations
I went the separate module route so we don't have to do any weird shadow configuration for now, but I'll add this to the list of things to revisit.
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.instrumentation.appender.api; |
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.
WDYT about using ...instrumentation.api.appender
? Or even ...instrumentation.api.logs.appender
; the appender api would under the same parent package as LoggingContextConstants
then
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 flipped it, but didn't add the logs
level, will add this to list of things to revisit.
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.
Looks good to me. A couple of comments.
public static LogEmitterProvider get() { | ||
LogEmitterProvider logEmitterProvider = globalLogEmitterProvider; | ||
if (logEmitterProvider == null) { | ||
synchronized (mutex) { |
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've stared at this way longer that I should have, and I can't poke any holes in its correctness. 😁
It was initially concerning to me that there were two stateful variables being modified, and only one was officially guarded by the mutex. Having symmetry there would be nice for readability, but I assumed the get()
case was trying to avoid the mutex entirely, probably for performance reasons. As we know, the double check that exists here only works correctly when the variable is volatile
(which it is here), but we pay a performance penalty for that as well...
So how about changing globalLogEmitterProvider
to be an atomic reference, get rid of the mutex, make setGlobalCaller
volatile, and use compareAndSet()
in the set()
implementation and just get()
in the get()
implementation? Definitely cleaner.
The docs say that the memory semantics of AtomicReference.get()
are the same as a volatile variable, but maybe you have deeper insight about the performance not being the same?
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 copied this from GlobalOpenTelemetry
, would prefer to stay consistent with whatever approach is blessed in the SDK (and see @anuraaga's recent open-telemetry/opentelemetry-java#4009) 😄
I did take a look at your suggestion, but it seemed like I still needed a coordinating synchronized block in both get
and set
. I'm likely missing something though.
...ion-api-appender/src/main/java/io/opentelemetry/instrumentation/api/appender/LogEmitter.java
Outdated
Show resolved
Hide resolved
* <p>Obtain a log builder via {@link #logBuilder()}, add properties using the setters, and emit it | ||
* via {@link LogBuilder#emit()}. | ||
*/ | ||
@ThreadSafe |
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.
We have a deep precedent of adding @ThreadSafe
to interfaces, but it continues to be weird to me because it's just a hint and it's always possible to implement a very thread unsafe implementation of these interfaces. 🤷🏻
FATAL(21), | ||
FATAL2(22), | ||
FATAL3(23), | ||
FATAL4(24); |
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.
are these in the sdk (still?). Maybe we could use the numeric constants from the sdk? I dunno.
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.
ya, this is copied from sdk. the problem is that we this artifact needs to not depend on the sdk.
…strumentation/api/appender/LogEmitter.java Co-authored-by: jason plumb <[email protected]>
I have opened #4935 to track several follow-ups |
* Add logging appender api * noop * Add global * drift * Feedback * compileOnly * fix * fix * Rename instrumentation-appender-api to instrumentation-api-appender * Rename package * Optimization * Split out instrumentation-sdk-appender * Fix * Update instrumentation-api-appender/src/main/java/io/opentelemetry/instrumentation/api/appender/LogEmitter.java Co-authored-by: jason plumb <[email protected]> * Fix * Fix * Fix * Fix sdk-appender package name Co-authored-by: jason plumb <[email protected]>
Resolves #4790
Just a shim on top of the Log SDK
with an additional no-op implementation, and support for an (optional) global
LogEmitterProvider
.