-
Notifications
You must be signed in to change notification settings - Fork 872
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 code attributes for Logback #6591
Add code attributes for Logback #6591
Conversation
@@ -25,6 +25,7 @@ public class OpenTelemetryAppender extends UnsynchronizedAppenderBase<ILoggingEv | |||
new LogEmitterProviderHolder(); | |||
|
|||
private volatile boolean captureExperimentalAttributes = false; | |||
private volatile boolean captureCodeAttributes = false; |
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 wanted first that the captureCodeAttributes
property would be an AtomicBoolean
, but I have noticed after that captureExperimentalAttributes
is a boolean
, so I keep the same way of doing
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.
nice 👍
instrumentation/logback/logback-appender-1.0/javaagent/build.gradle.kts
Outdated
Show resolved
Hide resolved
@@ -62,6 +65,17 @@ public void setCaptureExperimentalAttributes(boolean captureExperimentalAttribut | |||
this.captureExperimentalAttributes = captureExperimentalAttributes; | |||
} | |||
|
|||
/** | |||
* Sets whether the code attributes (file name, class name, method name and line number) should be | |||
* set to logs. |
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.
https://logback.qos.ch/manual/layouts.html states Generating the line number information is not particularly fast. Thus, its use should be avoided unless execution speed is not an issue.
(same for other code attributes). Should we also mention this here?
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.
Sure, I have added a sentence about this.
I'm looking into the CI failure, I suspect that is my doing... |
I merged in main to fix CI |
StackTraceElement[] callerData = loggingEvent.getCallerData(); | ||
if (callerData != null && callerData.length > 0) { | ||
StackTraceElement firstStackElement = callerData[0]; | ||
attributes.put(SemanticAttributes.CODE_FILEPATH, firstStackElement.getFileName()); |
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.
StackTraceElement#getFileName()
might return null, let's null-check it before passing it to attributes
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.
Done, I did not know that null attributes have not to bet set
attributes.put(SemanticAttributes.CODE_FILEPATH, firstStackElement.getFileName()); | ||
attributes.put(SemanticAttributes.CODE_NAMESPACE, firstStackElement.getClassName()); | ||
attributes.put(SemanticAttributes.CODE_FUNCTION, firstStackElement.getMethodName()); | ||
attributes.put(SemanticAttributes.CODE_LINENO, firstStackElement.getLineNumber()); |
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.
StackTraceElement#getLineNumber()
might return -1 -- in which case we probably don't want to add the attribute at all, since it represents an absent value.
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.
Done
assertThat(log.getAttributes().get(SemanticAttributes.EXCEPTION_TYPE)).isEqualTo(IllegalStateException.getName()) | ||
assertThat(log.getAttributes().get(SemanticAttributes.EXCEPTION_MESSAGE)).isEqualTo("hello") | ||
assertThat(log.getAttributes().get(SemanticAttributes.EXCEPTION_STACKTRACE)).contains(LogbackTest.name) | ||
} else { | ||
assertThat(log.getAttributes().size()).isEqualTo(2) | ||
assertThat(log.getAttributes().size()).isEqualTo(2 + 4) // 4 code attributes |
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.
Can you add code attributes assertions to the javaagent test too?
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.
Because of the nature of the Groovy test, the attribute values are not very readable:
file = NativeMethodAccessorImpl.java
codeClass = jdk.internal.reflect.NativeMethodAccessorImpl
method = invoke0
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.
Eh, forgot that was groovy. Nevermind 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.
ya, it would be nice to have validation that the attributes are working inside of the Java agent as well, but can get to that later, I've opened #6604 to track
@@ -115,13 +114,27 @@ void logWithExtras() { | |||
.isLessThan(TimeUnit.MILLISECONDS.toNanos(Instant.now().toEpochMilli())); | |||
assertThat(logData.getSeverity()).isEqualTo(Severity.INFO); | |||
assertThat(logData.getSeverityText()).isEqualTo("INFO"); | |||
assertThat(logData.getAttributes().size()).isEqualTo(3); | |||
assertThat(logData.getAttributes().size()).isEqualTo(3 + 4); // 4 code attributes |
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 refactoring this to use OpenTelemetryAssertions
and AttributesAssert
? Would be way more terse than the current code
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 was not aware about these classes. Thanks! I have a first look at the OpenTelemetryAssertions
and AttributesAssert
classes. From what I have seen, I have not the feeling that the assertions would be shorter and easier to read (for example the assertAttributes
method of AttributesAssert
requires a Map). Maybe I could look at this thing more in depth and propose potential improvements in another PR?
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.
Sure, that sounds fine 👍
...java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java
Outdated
Show resolved
Hide resolved
…java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java Co-authored-by: Mateusz Rzeszutek <[email protected]>
@@ -44,6 +44,13 @@ class LogbackTest extends AgentInstrumentationSpecification { | |||
waitForTraces(1) | |||
} | |||
|
|||
String jvmVersion = System.getProperty("java.vm.specification.version") | |||
int codeAttributes = 3 | |||
boolean jvmVersionGreaterThanOrEqualTo18 = jvmVersion.startsWith("1.8") && Integer.parseInt(jvmVersion) >= 18 |
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.
won't this throw NumberFormatException for 1.8?
if you need to test locally with different Java versions, check out https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/contributing/running-tests.md#executing-tests-with-specific-java-version
int codeAttributes = 3 | ||
boolean jvmVersionGreaterThanOrEqualTo18 = jvmVersion.startsWith("1.8") && Integer.parseInt(jvmVersion) >= 18 | ||
if (jvmVersionGreaterThanOrEqualTo18) { | ||
codeAttributes = 4 // Java 18 specificity on line number |
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.
can you add a bit more detail to this comment, I'm not familiar with why Java 18 would have different behavior here
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 have added a thing
@jeanbisutti heads up I merged main into your branch to get CI fix for markdown link |
@@ -44,6 +44,13 @@ class LogbackTest extends AgentInstrumentationSpecification { | |||
waitForTraces(1) | |||
} | |||
|
|||
String jvmVersion = System.getProperty("java.vm.specification.version") |
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.
can we use this instead? (this is the property we check for java version in the agent)
String jvmVersion = System.getProperty("java.vm.specification.version") | |
String jvmVersion = System.getProperty("java.version") |
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.
No. System.getProperty("java.version")
contains the minor JVM version and the number parsing just after will fail
int codeAttributes = 3 | ||
boolean jvmVersionGreaterThanOrEqualTo18 = !jvmVersion.startsWith("1.8") && Integer.parseInt(jvmVersion) >= 18 | ||
if (jvmVersionGreaterThanOrEqualTo18) { | ||
codeAttributes = 4 // Java 18 specificity on line number (lineNumber > 0 check) |
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 wonder if this is because of groovy, I would be surprised to see different behavior for a regular Java class, I may try to convert this test to Java after merging it
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.
Line number is negative for Java <= 17 and this Groovy test, everything is fine for the library test based on JUnit 5
* Add code attributes for Logback * Rename property * Add a note about performance * Add null check on file name * Add check on line number * Fix test following new behavior * spotless * Update instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java Co-authored-by: Mateusz Rzeszutek <[email protected]> * Fix test * Adapt test for Java 18 * codenarc * Test fix Co-authored-by: Trask Stalnaker <[email protected]> Co-authored-by: Mateusz Rzeszutek <[email protected]>
* Add code attributes for Logback * Rename property * Add a note about performance * Add null check on file name * Add check on line number * Fix test following new behavior * spotless * Update instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java Co-authored-by: Mateusz Rzeszutek <[email protected]> * Fix test * Adapt test for Java 18 * codenarc * Test fix Co-authored-by: Trask Stalnaker <[email protected]> Co-authored-by: Mateusz Rzeszutek <[email protected]>
* Add code attributes for Logback * Rename property * Add a note about performance * Add null check on file name * Add check on line number * Fix test following new behavior * spotless * Update instrumentation/logback/logback-appender-1.0/library/src/main/java/io/opentelemetry/instrumentation/logback/appender/v1_0/internal/LoggingEventMapper.java Co-authored-by: Mateusz Rzeszutek <[email protected]> * Fix test * Adapt test for Java 18 * codenarc * Test fix Co-authored-by: Trask Stalnaker <[email protected]> Co-authored-by: Mateusz Rzeszutek <[email protected]>
Add code attributes for Logback: