-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for jboss-logmanager (open-telemetry#5737)
* initialize the package Signed-off-by: Cuichen Li <[email protected]> * add jboss-logmanger 2.1 instrumentation Signed-off-by: Cuichen Li <[email protected]> * rename the test Signed-off-by: Cuichen Li <[email protected]> * clean comment Signed-off-by: Cuichen Li <[email protected]> * Revert "Add JBoss java.util.logging support (open-telemetry#5498)" This reverts commit 8b26cef. * Remove extra directory * Remove old jboss log manager test * Ensure no cross interference * Change base version to 1.1 * fix styles Signed-off-by: Cuichen Li <[email protected]> * run spotless apply Signed-off-by: Cuichen Li <[email protected]> * fix codenarc Signed-off-by: Cuichen Li <[email protected]> * change the package version and additional module name Signed-off-by: Cuichen Li <[email protected]> Co-authored-by: Trask Stalnaker <[email protected]>
- Loading branch information
Showing
10 changed files
with
323 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 0 additions & 25 deletions
25
instrumentation/java-util-logging/jboss-testing/build.gradle.kts
This file was deleted.
Oops, something went wrong.
29 changes: 29 additions & 0 deletions
29
instrumentation/jboss-logmanager-1.1/javaagent/build.gradle.kts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
plugins { | ||
id("otel.javaagent-instrumentation") | ||
} | ||
|
||
muzzle { | ||
pass { | ||
group.set("org.jboss.logmanager") | ||
module.set("jboss-logmanager") | ||
versions.set("[1.1.0.GA,)") | ||
assertInverse.set(true) | ||
} | ||
} | ||
|
||
dependencies { | ||
library("org.jboss.logmanager:jboss-logmanager:1.1.0.GA") | ||
|
||
compileOnly(project(":instrumentation-appender-api-internal")) | ||
|
||
// ensure no cross interference | ||
testInstrumentation(project(":instrumentation:java-util-logging:javaagent")) | ||
|
||
testImplementation("org.awaitility:awaitility") | ||
} | ||
|
||
tasks.withType<Test>().configureEach { | ||
// TODO run tests both with and without experimental log attributes | ||
jvmArgs("-Dotel.instrumentation.jboss-logmanager.experimental.capture-mdc-attributes=*") | ||
jvmArgs("-Dotel.instrumentation.jboss-logmanager.experimental-log-attributes=true") | ||
} |
61 changes: 61 additions & 0 deletions
61
...emetry/javaagent/instrumentation/jbosslogmanager/v1_1/JbossLogmanagerInstrumentation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.instrumentation.jbosslogmanager.v1_1; | ||
|
||
import static net.bytebuddy.matcher.ElementMatchers.isMethod; | ||
import static net.bytebuddy.matcher.ElementMatchers.isPublic; | ||
import static net.bytebuddy.matcher.ElementMatchers.named; | ||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument; | ||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments; | ||
|
||
import io.opentelemetry.instrumentation.api.appender.internal.LogEmitterProvider; | ||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; | ||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; | ||
import io.opentelemetry.javaagent.instrumentation.api.CallDepth; | ||
import net.bytebuddy.asm.Advice; | ||
import net.bytebuddy.description.type.TypeDescription; | ||
import net.bytebuddy.matcher.ElementMatcher; | ||
import org.jboss.logmanager.ExtLogRecord; | ||
import org.jboss.logmanager.Logger; | ||
|
||
public class JbossLogmanagerInstrumentation implements TypeInstrumentation { | ||
@Override | ||
public ElementMatcher<TypeDescription> typeMatcher() { | ||
return named("org.jboss.logmanager.Logger"); | ||
} | ||
|
||
@Override | ||
public void transform(TypeTransformer transformer) { | ||
transformer.applyAdviceToMethod( | ||
isMethod() | ||
.and(isPublic()) | ||
.and(named("logRaw")) | ||
.and(takesArguments(1)) | ||
.and(takesArgument(0, named("org.jboss.logmanager.ExtLogRecord"))), | ||
JbossLogmanagerInstrumentation.class.getName() + "$CallLogRawAdvice"); | ||
} | ||
|
||
@SuppressWarnings("unused") | ||
public static class CallLogRawAdvice { | ||
@Advice.OnMethodEnter(suppress = Throwable.class) | ||
public static void methodEnter( | ||
@Advice.This() Logger logger, | ||
@Advice.Argument(0) ExtLogRecord record, | ||
@Advice.Local("otelCallDepth") CallDepth callDepth) { | ||
// need to track call depth across all loggers in order to avoid double capture when one | ||
// logging framework delegates to another | ||
callDepth = CallDepth.forClass(LogEmitterProvider.class); | ||
if (callDepth.getAndIncrement() == 0) { | ||
LoggingEventMapper.INSTANCE.capture(logger, record); | ||
} | ||
} | ||
|
||
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) | ||
public static void methodExit(@Advice.Local("otelCallDepth") CallDepth callDepth) { | ||
callDepth.decrementAndGet(); | ||
} | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
.../javaagent/instrumentation/jbosslogmanager/v1_1/JbossLogmanagerInstrumentationModule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.instrumentation.jbosslogmanager.v1_1; | ||
|
||
import static java.util.Collections.singletonList; | ||
|
||
import com.google.auto.service.AutoService; | ||
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; | ||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; | ||
import java.util.List; | ||
|
||
@AutoService(InstrumentationModule.class) | ||
public class JbossLogmanagerInstrumentationModule extends InstrumentationModule { | ||
|
||
public JbossLogmanagerInstrumentationModule() { | ||
super("jboss-logmanager", "jboss-logmanager-1.1"); | ||
} | ||
|
||
@Override | ||
public List<TypeInstrumentation> typeInstrumentations() { | ||
return singletonList(new JbossLogmanagerInstrumentation()); | ||
} | ||
} |
145 changes: 145 additions & 0 deletions
145
...a/io/opentelemetry/javaagent/instrumentation/jbosslogmanager/v1_1/LoggingEventMapper.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/* | ||
* Copyright The OpenTelemetry Authors | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.opentelemetry.javaagent.instrumentation.jbosslogmanager.v1_1; | ||
|
||
import static java.util.Collections.emptyList; | ||
|
||
import io.opentelemetry.api.common.AttributeKey; | ||
import io.opentelemetry.api.common.Attributes; | ||
import io.opentelemetry.api.common.AttributesBuilder; | ||
import io.opentelemetry.context.Context; | ||
import io.opentelemetry.instrumentation.api.appender.internal.LogBuilder; | ||
import io.opentelemetry.instrumentation.api.appender.internal.Severity; | ||
import io.opentelemetry.instrumentation.api.cache.Cache; | ||
import io.opentelemetry.instrumentation.api.config.Config; | ||
import io.opentelemetry.javaagent.instrumentation.api.appender.internal.AgentLogEmitterProvider; | ||
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes; | ||
import java.io.PrintWriter; | ||
import java.io.StringWriter; | ||
import java.util.List; | ||
import java.util.Map; | ||
import org.jboss.logmanager.ExtLogRecord; | ||
import org.jboss.logmanager.Level; | ||
import org.jboss.logmanager.Logger; | ||
import org.jboss.logmanager.MDC; | ||
|
||
public final class LoggingEventMapper { | ||
|
||
public static final LoggingEventMapper INSTANCE = new LoggingEventMapper(); | ||
|
||
private static final Cache<String, AttributeKey<String>> mdcAttributeKeys = Cache.bounded(100); | ||
|
||
private final List<String> captureMdcAttributes; | ||
|
||
private static final boolean captureExperimentalAttributes = | ||
Config.get() | ||
.getBoolean("otel.instrumentation.jboss-logmanager.experimental-log-attributes", false); | ||
|
||
// cached as an optimization | ||
private final boolean captureAllMdcAttributes; | ||
|
||
private LoggingEventMapper() { | ||
this.captureMdcAttributes = | ||
Config.get() | ||
.getList( | ||
"otel.instrumentation.jboss-logmanager.experimental.capture-mdc-attributes", | ||
emptyList()); | ||
this.captureAllMdcAttributes = | ||
captureMdcAttributes.size() == 1 && captureMdcAttributes.get(0).equals("*"); | ||
} | ||
|
||
public void capture(Logger logger, ExtLogRecord record) { | ||
String instrumentationName = logger.getName(); | ||
if (instrumentationName == null || instrumentationName.isEmpty()) { | ||
instrumentationName = "ROOT"; | ||
} | ||
|
||
LogBuilder builder = | ||
AgentLogEmitterProvider.get().logEmitterBuilder(instrumentationName).build().logBuilder(); | ||
|
||
String message = record.getFormattedMessage(); | ||
if (message != null) { | ||
builder.setBody(message); | ||
} | ||
|
||
java.util.logging.Level level = record.getLevel(); | ||
if (level != null) { | ||
builder.setSeverity(levelToSeverity(level)); | ||
builder.setSeverityText(level.toString()); | ||
} | ||
|
||
AttributesBuilder attributes = Attributes.builder(); | ||
|
||
Throwable throwable = record.getThrown(); | ||
if (throwable != null) { | ||
// TODO (trask) extract method for recording exception into | ||
// instrumentation-appender-api-internal | ||
attributes.put(SemanticAttributes.EXCEPTION_TYPE, throwable.getClass().getName()); | ||
attributes.put(SemanticAttributes.EXCEPTION_MESSAGE, throwable.getMessage()); | ||
StringWriter writer = new StringWriter(); | ||
throwable.printStackTrace(new PrintWriter(writer)); | ||
attributes.put(SemanticAttributes.EXCEPTION_STACKTRACE, writer.toString()); | ||
} | ||
captureMdcAttributes(attributes); | ||
|
||
if (captureExperimentalAttributes) { | ||
Thread currentThread = Thread.currentThread(); | ||
attributes.put(SemanticAttributes.THREAD_NAME, currentThread.getName()); | ||
attributes.put(SemanticAttributes.THREAD_ID, currentThread.getId()); | ||
} | ||
|
||
builder.setAttributes(attributes.build()); | ||
|
||
builder.setContext(Context.current()); | ||
|
||
builder.emit(); | ||
} | ||
|
||
private void captureMdcAttributes(AttributesBuilder attributes) { | ||
|
||
Map<String, String> context = MDC.copy(); | ||
|
||
if (captureAllMdcAttributes) { | ||
if (context != null) { | ||
for (Map.Entry<String, String> entry : context.entrySet()) { | ||
attributes.put( | ||
getMdcAttributeKey(String.valueOf(entry.getKey())), String.valueOf(entry.getValue())); | ||
} | ||
} | ||
return; | ||
} | ||
|
||
for (String key : captureMdcAttributes) { | ||
Object value = context.get(key); | ||
if (value != null) { | ||
attributes.put(key, value.toString()); | ||
} | ||
} | ||
} | ||
|
||
public static AttributeKey<String> getMdcAttributeKey(String key) { | ||
return mdcAttributeKeys.computeIfAbsent( | ||
key, k -> AttributeKey.stringKey("jboss-logmanager.mdc." + k)); | ||
} | ||
|
||
private static Severity levelToSeverity(java.util.logging.Level level) { | ||
int levelInt = level.intValue(); | ||
if (levelInt >= Level.FATAL.intValue()) { | ||
return Severity.FATAL; | ||
} else if (levelInt >= Level.ERROR.intValue()) { | ||
return Severity.ERROR; | ||
} else if (levelInt >= Level.WARNING.intValue()) { | ||
return Severity.WARN; | ||
} else if (levelInt >= Level.INFO.intValue()) { | ||
return Severity.INFO; | ||
} else if (levelInt >= Level.DEBUG.intValue()) { | ||
return Severity.DEBUG; | ||
} else if (levelInt >= Level.TRACE.intValue()) { | ||
return Severity.TRACE; | ||
} | ||
return Severity.UNDEFINED_SEVERITY_NUMBER; | ||
} | ||
} |
Oops, something went wrong.