-
Notifications
You must be signed in to change notification settings - Fork 73
Description
Problem Statement
Currently, the Java agent (javaagent) and Node.js agent (nodejs) injectors can only be enabled/disabled globally via:
OTEL_EBPF_JAVAAGENT_ENABLED=falseOTEL_EBPF_NODEJS_ENABLED=false
This is problematic when:
- Some applications have library conflicts - e.g., Neo4j bundles caffeine cache which conflicts with OBI's shaded
io.opentelemetry.obi.com.github.benmanes.caffeine.*classes, causingNoClassDefFoundError - Users want eBPF traces but not agent injection for specific services
- Different namespaces have different requirements - production apps may need full instrumentation while third-party databases should be excluded
Current Workaround
Users must either:
- Disable agents globally (losing functionality for ALL Java/Node.js apps)
- Use
exclude_instrumentto exclude the namespace entirely (losing ALL eBPF traces for that service)
Neither option is ideal.
Proposed Solution
Add per-service agent injection control to the instrument discovery configuration, similar to existing per-service options like exports, sampler, and routes.
Option 1: Unified control
discovery:
instrument:
- k8s_namespace: juno
k8s_statefulset_name: neo4j
agent_injection: false # Disable both Java + Node.js agents
- k8s_namespace: production
agent_injection: true # Enable (default)Option 2: Granular control
discovery:
instrument:
- k8s_namespace: juno
javaagent_enabled: false
nodejs_enabled: true
- k8s_pod_labels:
app: legacy-app
javaagent_enabled: falseOption 3: Exclusion list (similar to exclude_instrument)
javaagent:
enabled: true
exclude:
- k8s_namespace: juno
- k8s_statefulset_name: neo4j
nodejs:
enabled: true
exclude:
- k8s_namespace: kube-systemImplementation Notes
Based on code analysis:
-
GlobAttributesstruct (pkg/appolly/services/attr_glob.go) already supports per-service config forexports,sampler,routes,metrics. Addingjavaagent_enabledandnodejs_enabledfields would follow the same pattern. -
attacher.go(pkg/appolly/discover/attacher.go:110-115) currently calls injectors unconditionally:ta.nodeInjector.NewExecutable(&instr.Obj) if ta.javaInjector != nil { if err := ta.javaInjector.NewExecutable(&instr.Obj); err != nil { // ... } }
This would need to check the per-service config before calling the injectors.
-
Namespace is already available in
instr.Obj.FileInfo.Service.UID.NamespaceandMetadata[attr.K8sNamespaceName]at injection time.
Use Case
We run Neo4j (a Java application) in Kubernetes. OBI's Java agent injection causes:
java.lang.NoClassDefFoundError: io/opentelemetry/obi/com/github/benmanes/caffeine/cache/BoundedBuffer$RingBuffer
This happens because Neo4j bundles caffeine cache, and OBI's shaded caffeine classes conflict with it.
We want to:
- ✅ Keep eBPF network-level traces for Neo4j (HTTP, Bolt protocol)
- ✅ Keep Java agent injection for our own Java microservices
- ❌ Disable Java agent injection ONLY for Neo4j
Currently impossible without disabling Java agent globally.
Additional Context
- OBI version: v0.4.1
- Deployment: Kubernetes DaemonSet
- Affected application: Neo4j 5.x (uses caffeine cache internally)
Metadata
Metadata
Assignees
Labels
Type
Projects
Status