Configuration-based Java Trace SDK
The configuration-based Java Trace SDK enables a declarative specification of spans and tags that the spans should carry, and creates spans by executing certain methods of your application.
The expressiveness is comparable to that of the @Span annotation and SpanSupport.annotate() facilities of the programmatic Java Trace SDK.
Before you implement custom tracing, read the tracing best practices.
Introduction
The configuration-based SDK is brittle against changes in your application. You might rename a class or a method, and all of a sudden the configuration does no longer match, and you lose your tracing data. Whenever possible, you are advised to use the Java Trace SDK, which is far more resilient against code changes and has more features to help you accomplish your goals.
Configuration
To use the configuration-based Java Trace SDK, you need to enable the Java Trace SDK as described in Enabling Java Trace SDK.
Notes:
-
Changes to the configuration of the configuration-based Java Trace SDK are automatically picked up by the Instana agent. Already instrumented applications need to be restarted to use the changed configuration.
-
The configuration-based Java Trace SDK is available in the Java Trace Sensor version
1.2.351or later.
Format
The following listing describes the general format of the configuration:
# Java Tracing
com.instana.plugin.javatrace:
instrumentation:
sdk:
targets:
- match:
type: 'interface'|'class'|'baseclass'
name: '<type-name>'
method: '<method-name>'
[argumentTypes:
- '<argument-type-index0>'
- '<argument-type-indexn>']
[returnType: '<return-type-name>']
span:
name: '<span-name>'
[type: '<span-type>']
[stackDepth: <depth>]
[tags:
- kind: 'argument'
name: 'name'
index: 0
- kind: 'return'
name: 'name'
- kind: 'constant'
name: 'name'
value: 'constant-value']
Multiple targets can be defined within the targets key, each of which specifies one span to be created. The match object of one target specifies the method to apply the instrumentation to. The span object specifies how to build the span, including its name (which is used for example in Unbounded Analytics for the call.name filter) and which tags should be set.
Matching methods to instrument
This object describes the code point at which an instrumentation should take place:
-
type: Type of the code to instrument; supported values:-
class, match a concrete class -
interface, match all classes implementing the interface -
baseclass, match all classes extending the base class
-
-
name: Fully qualified name of the class, interface or base class to match For nested classes, the notationa.b.c.OutsideClass$NestedClassis expected -
method: Name of the method of the given class, interface or base class of which an invocation should be recorded -
argumentTypes: List of fully qualified argument types of the method to match (optional)- If missing, arguments are not matched, and the instrumentation will be applied to all method in case of overloading
- If present, all arguments have to match the given types in order, otherwise the method will not match
-
returnType: Fully qualified returned type of the method to match (optional)- If missing, return type is not considered
- If present, return type has to match the given type, otherwise the method will not match
Specifying how the spans will look like
This object describes properties of the span that will be created if the method described in match is invoked:
-
name: Span name -
type: Span type (optional); supported values:-
ENTRY, used to indicate "incoming" calls from external systems -
INTERMEDIATE, used to capture internal calls to "interesting" methods (default) -
EXIT, used to indicate "outgoing" calls to external systems
-
-
stackDepth: Number of stack frames to capture of the method invocation (optional); default is0 -
tags: List of tags/annotations to capture and how to obtain their values (optional); supported values:-
constant, capture a constant value-
kind:constant -
name: Name of the tag to create -
value: Constant value of the tag to create
-
-
return, capture the return value of the method invocation-
kind:return -
name: Name of the tag to create; value will be the value of the returned object
-
-
argument, capture a specific argument value of the method invocation-
kind:argument -
name: Name of the tag to create -
index: 0-based index of the argument to capture as value of the tag
-
-
null or Optional.empty the defined tag will not be added. Spans with missing tags can be looked up in Unbounded Analytics using the is not present operator in conjunction with the call.tag filter.Erroneous Spans
If a Throwable propagates outside of an instrumented method, the span will be automatically marked as erroneous, and the value of Throwable#getMessage() will be set as the error message, which you can search in Unbounded Analytics via the call.error.message tag.
Verifying your SDK configuration
- Verify that the configuration was parsed successfully. In the agent logs, look for a message similar to:
Parsed configuration file /instana-agent/etc/instana/configuration.yaml - Verify that the instrumentation was applied. After parsing, the agent will log a message showing that it performed SDK instrumentation:
... Spent XX ms and XXX KiB of Metaspace for instrumentation [sdk] ... - Enable and verify SDK span trace logs. To validate that spans are actually being created, enable trace logging by adding the following YAML:
com.instana.plugin.javatrace: instrumentation: log: type: trace file: /tmp/trace.log
Once the instrumentation is active and the instrumented code is executed, you should see SDK spans emitted. Example trace log format:
-|EN|052d6bf37f16034c7:0:52d6bf37f16034c7|sdk:sdk.quarkus-hello|*com.instana.agent.instrumentation.sdk.SdkPlugin:start:789:SdkPlugin.java
Example
The following snippet shows an example configuration of how an application handling batch jobs could be traced:
com.instana.plugin.javatrace:
instrumentation:
sdk:
targets:
- match:
type: class
name: com.instana.java.sdk.BatchApplication
method: processBatch
span:
name: Job
type: ENTRY
stackDepth: 2
tags:
- kind: constant
name: endpoint
value: BatchJob
- kind: argument
name: batch.job
index: 0
- match:
type: class
name: com.instana.java.sdk.BatchApplication
method: updateDatabase
span:
name: DatabaseCall
type: EXIT
stackDepth: 2
tags:
- kind: constant
name: db.connection_string
value: jdbc:mysql://127.0.0.1:3306/jobs
- kind: argument
name: db.statement
index: 0
First the method processBatch in class com.instana.java.sdk.BatchApplication is instrumented to create entry spans with name Job, the annotation endpoint with the constant value BatchJob, and the annotation batch.job with the first argument as its value.
Furthermore, outgoing DB calls during the batch processing, that is invocations of method updateDatabase in the same class, will create exit spans with name DatabaseCall and the annotation db.connection_string with the constant value jdbc:mysql://127.0.0.1:3306/jobs and annotation db.statement with the first argument of the method invocation.
Processing a new batch with processBatch will start a new trace and subsequent DB updates with updateDatabase will be listed as child spans within it. All Instana features, like Unbounded Analytics, can be used identically to traces created with Instana AutoTrace.
Limitations
The following restrictions apply to the configuration-based Java Trace SDK:
- Instrumenting constructors is not supported.
- Starting a span in one method and closing it in another is not supported; that is, the configuration-based SDK has no equivalent for the
@Span.Startand@Span.Endannotations. - Capturing all arguments or the return value without explicitly creating a
tagis not supported. - Specifying placeholders in the argument list for unimportant arguments or all the rest is not supported; the arguments-based match is executed in a strict fashion.
- Specifying name patterns for classes or methods is not supported.
- Restoring a trace context before creating a span is not supported; that is, the configuration-based SDK does not have a capability equivalent to
SpanSupport.inheritNext().