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

Added initial commit of camunda instrumentation #12830

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a631796
Added initial commit of camunda instrumentation
cb645j Dec 3, 2024
979c377
Add module to parent settings
cb645j Dec 5, 2024
4fbdbf8
Reorganized project structure and fixed gradle settings
cb645j Dec 9, 2024
7b268c0
fix the version reference in the build settings
cb645j Dec 9, 2024
c6aa4c2
Fixed the formatting for spotless
cb645j Dec 11, 2024
80b0e67
Fix formatting for lib folder also per spotless
cb645j Dec 11, 2024
b267316
fix bad import in span name extractor class
cb645j Dec 11, 2024
fb19def
Added dependencies to javaagent module, changed library instead of im…
cb645j Dec 11, 2024
b44bc9d
Fix import statements and remove dead code
cb645j Dec 12, 2024
26df3f1
Fix more errors on compile
cb645j Dec 12, 2024
9fb1aed
remove unused dependencies and supress warning
cb645j Dec 12, 2024
d7f179f
Add private constructor for singletons
cb645j Dec 12, 2024
308f6a8
Removed javadocs with no description and unused fields
cb645j Dec 12, 2024
fd44b57
remove print line and fix scope
cb645j Dec 12, 2024
bdd9ea1
Surpress unused warning in instrumentation
cb645j Dec 13, 2024
628d839
Surpress false warnings so build doesnt fail
cb645j Dec 13, 2024
75f3fdc
Combine supress warnings into one
cb645j Dec 16, 2024
0cd3185
remove empty if blocks from the code
cb645j Dec 16, 2024
3f9833a
Add extra dependency for muzzle check
cb645j Dec 16, 2024
38ff7f0
Consolidated similiar type instrumentations into single module
cb645j Dec 16, 2024
7fcfa7d
fix spotless java format
cb645j Dec 16, 2024
da9e851
Fix typos and compilation errors
cb645j Dec 16, 2024
4355c63
remove the label from method
cb645j Dec 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions instrumentation/camunda/camunda-7.0/javaagent/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
plugins {
id("otel.javaagent-instrumentation")
}

muzzle {
pass {
group.set("org.camunda.bpm")
module.set("camunda-engine")

// have not tested with versions prior to 7.18.0
versions.set("[7.18.0,)")
extraDependency("org.camunda.bpm:camunda-external-task-client:7.18.0")
}
}

dependencies {
implementation(project(":instrumentation:camunda:camunda-7.0:library"))

library("org.camunda.bpm:camunda-engine:7.18.0")
library("org.camunda.bpm:camunda-external-task-client:7.18.0")

annotationProcessor("com.google.auto.value:auto-value:1.6")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.camunda.v7_0.behavior;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
import io.opentelemetry.instrumentation.camunda.v7_0.behavior.CamundaBehaviorSpanNameExtractor;
import io.opentelemetry.instrumentation.camunda.v7_0.common.CamundaCommonRequest;
import io.opentelemetry.instrumentation.camunda.v7_0.common.CamundaVariableAttributeExtractor;

public class CamundaBehaviorSingletons {

private static final Instrumenter<CamundaCommonRequest, String> instrumenter;

private static final OpenTelemetry opentelemetry;

static {
opentelemetry = GlobalOpenTelemetry.get();

InstrumenterBuilder<CamundaCommonRequest, String> builder =
Instrumenter.<CamundaCommonRequest, String>builder(
opentelemetry,
"io.opentelemetry.camunda-behavior",
new CamundaBehaviorSpanNameExtractor())
.addAttributesExtractor(new CamundaVariableAttributeExtractor());

instrumenter = builder.buildInstrumenter();
}

public static OpenTelemetry getOpentelemetry() {
return opentelemetry;
}

public static Instrumenter<CamundaCommonRequest, String> getInstumenter() {
return instrumenter;
}

private CamundaBehaviorSingletons() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.camunda.v7_0.behavior;

import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasSuperType;
import static io.opentelemetry.javaagent.instrumentation.camunda.v7_0.behavior.CamundaBehaviorSingletons.getInstumenter;
import static io.opentelemetry.javaagent.instrumentation.camunda.v7_0.behavior.CamundaBehaviorSingletons.getOpentelemetry;
import static net.bytebuddy.matcher.ElementMatchers.named;

import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.camunda.v7_0.behavior.CamundaActivityExecutionGetter;
import io.opentelemetry.instrumentation.camunda.v7_0.behavior.CamundaVariableMapSetter;
import io.opentelemetry.instrumentation.camunda.v7_0.common.CamundaCommonRequest;
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import java.util.Optional;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.matcher.ElementMatchers;
import org.camunda.bpm.engine.impl.pvm.delegate.ActivityExecution;
import org.camunda.bpm.engine.variable.VariableMap;

public class CamundaCallableElementActivityBehaviorInstrumentation implements TypeInstrumentation {

@Override
public ElementMatcher<ClassLoader> classLoaderOptimization() {
return hasClassesNamed(
"org.camunda.bpm.engine.impl.bpmn.behavior.CallableElementActivityBehavior");
}

@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return hasSuperType(
named("org.camunda.bpm.engine.impl.bpmn.behavior.CallableElementActivityBehavior"));
}

@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
ElementMatchers.isMethod().and(ElementMatchers.named("startInstance")),
this.getClass().getName() + "$CamundaCallableElementActivityBehaviorAdvice");
}

@SuppressWarnings("unused")
public static class CamundaCallableElementActivityBehaviorAdvice {

@Advice.OnMethodEnter(suppress = Throwable.class)
public static void addTracingEnter(
@Advice.Argument(0) ActivityExecution execution,
@Advice.Argument(1) VariableMap variables,
@Advice.Local("request") CamundaCommonRequest request,
@Advice.Local("otelParentScope") Scope parentScope,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {

if (execution == null) {
// log warning
return;
}

request = new CamundaCommonRequest();
request.setProcessDefinitionId(Optional.ofNullable(execution.getProcessDefinitionId()));
request.setProcessInstanceId(Optional.ofNullable(execution.getProcessInstanceId()));
request.setActivityId(Optional.ofNullable(execution.getCurrentActivityId()));
request.setActivityName(Optional.ofNullable(execution.getCurrentActivityName()));
request.setBusinessKey(Optional.ofNullable(execution.getProcessBusinessKey()));

if (Java8BytecodeBridge.currentContext() == Java8BytecodeBridge.rootContext()) {
// log
}

Context parentContext =
getOpentelemetry()
.getPropagators()
.getTextMapPropagator()
.extract(
Java8BytecodeBridge.currentContext(),
execution,
new CamundaActivityExecutionGetter());

parentScope = parentContext.makeCurrent();

if (getInstumenter().shouldStart(Java8BytecodeBridge.currentContext(), request)) {
context = getInstumenter().start(Java8BytecodeBridge.currentContext(), request);
scope = context.makeCurrent();

// Inject subflow trace context as pi variables so they are propagated and
// accessible

SpanContext currentSpanContext =
Java8BytecodeBridge.spanFromContext(context).getSpanContext();
if (currentSpanContext.isValid()) {
getOpentelemetry()
.getPropagators()
.getTextMapPropagator()
.inject(context, variables, new CamundaVariableMapSetter());
}
}
}

@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void closeTrace(
@Advice.Argument(0) ActivityExecution execution,
@Advice.Local("request") CamundaCommonRequest request,
@Advice.Local("otelParentScope") Scope parentScope,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope,
@Advice.Thrown Throwable throwable) {

if (context != null && scope != null) {
getInstumenter().end(context, request, "NA", throwable);
scope.close();
}

if (parentScope != null) {
parentScope.close();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.camunda.v7_0.behavior;

import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;

import com.google.auto.service.AutoService;
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import net.bytebuddy.matcher.ElementMatcher;

@AutoService(InstrumentationModule.class)
public class CamundaCallableElementActivityBehaviorModule extends InstrumentationModule {

public CamundaCallableElementActivityBehaviorModule() {
super("camunda", "camunda-behavior", "camunda-behavior-7_18");
}

@Override
public boolean defaultEnabled(ConfigProperties config) {
return config.getBoolean("otel.instrumentation.common.default-enabled", true);
}

@Override
public List<TypeInstrumentation> typeInstrumentations() {
return Collections.singletonList(new CamundaCallableElementActivityBehaviorInstrumentation());
}

@Override
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
return hasClassesNamed(
"org.camunda.bpm.engine.impl.bpmn.behavior.CallableElementActivityBehavior");
}

String[] helperClassnames = {
"io.opentelemetry.javaagent.instrumentation.camunda.v7_0.behavior",
"io.opentelemetry.instrumentation.camunda.v7_0.behavior",
"io.opentelemetry.instrumentation.camunda.v7_0.common"
};

@Override
public boolean isHelperClass(String classname) {
return super.isHelperClass(classname)
|| Arrays.stream(helperClassnames).anyMatch(c -> classname.startsWith(c));
}
}
Loading
Loading