diff --git a/.gitignore b/.gitignore
index f9a50e1..f69f244 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
.project
.settings
.classpath
+target
diff --git a/LICENSE b/LICENSE
index 8dada3e..9060297 100644
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright {yyyy} {name of copyright owner}
+ Copyright 2018 Dynatrace LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/README.md b/README.md
old mode 100644
new mode 100755
index abb82c6..06a4e61
--- a/README.md
+++ b/README.md
@@ -1,76 +1,149 @@
-**Disclaimer: This SDK is currently in early access and still work in progress.**
-
# Dynatrace OneAgent SDK for Java
-This SDK allows Dynatrace customers to instrument java applications. This is useful to enhance the visibility for proprietary frameworks or custom frameworks not directly supported by Dynatrace OneAgent out-of-the-box.
-
-It provides the Java implementation of the [Dynatrace OneAgent SDK](https://github.com/Dynatrace/OneAgent-SDK).
+This SDK allows Dynatrace customers to instrument java applications. This is useful to enhance the visibility for proprietary frameworks or
+custom frameworks not directly supported by Dynatrace OneAgent out-of-the-box.
+
+This is the official Java implementation of the [Dynatrace OneAgent SDK](https://github.com/Dynatrace/OneAgent-SDK).
+
+## Table of Contents
+
+* [Package contents](#package-contents)
+* [Requirements](#requirements)
+* [Integration](#integration)
+ * [Dependencies](#dependencies)
+ * [Troubleshooting](#troubleshooting)
+* [API concepts](#api-concepts)
+ * [OneAgentSDK object](#oneagentsdk-object)
+ * [Trace Context](#tracecontext)
+ * [Tracers](#tracers)
+* [Features](#features)
+ * [Trace incoming and outgoing remote calls](#trace-incoming-and-outgoing-remote-calls)
+ * [In process linking](#in-process-linking)
+ * [Add custom request attributes](#add-custom-request-attributes)
+ * [Custom services](#custom-services)
+ * [Trace web requests](#trace-web-requests)
+ * [Trace incoming web requests](#trace-incoming-web-requests)
+ * [Trace outgoing web requests](#trace-outgoing-web-requests)
+ * [Trace messaging](#trace-messaging)
+ * [Trace SQL database requests](#trace-sql-database-requests)
+* [Further reading](#further-reading)
+* [Help & support](#help-&-support)
+* [Release notes](#release-notes)
## Package contents
-- `samples`: contains sample application, which demonstrates the usage of the SDK. see readme inside the samples directory for more details
-- `LICENSE`: license under which the whole SDK and sample applications are published
+* `samples`: contains sample application, which demonstrates the usage of the SDK. See readme inside the samples directory for more details.
+* `docs`: contains the reference documentation (javadoc). The most recent version is also available online at [https://dynatrace.github.io/OneAgent-SDK-for-Java/](https://dynatrace.github.io/OneAgent-SDK-for-Java/).
+* `LICENSE`: license under which the whole SDK and sample applications are published.
-## Features
-Dynatrace OneAgent SDK for Java currently implements support for the following features (corresponding to features specified in [Dynatrace OneAgent SDK](https://github.com/Dynatrace/OneAgent-SDK)):
-- outgoing and incoming remote calls
+## Requirements
+
+* An JRE that is both supported with a supported version of OneAgent and at least JRE 1.6-compatible.
+* Dynatrace OneAgent (for required versions, see table below)
+* The OneAgent SDK is not supported on serverless code modules, including those for AWS Lambda.
+ Consider using [OpenTelemetry](https://www.dynatrace.com/support/help/shortlink/opentel-lambda)
+ instead in these scenarios.
+
+|OneAgent SDK for Java|Required OneAgent version|Support status|
+|:--------------------|:------------------------|:-------------|
+|1.9.0 |>=1.261 |Supported |
+|1.8.0 |>=1.201 |Supported |
+|1.7.0 |>=1.167 |Deprecated with support ending 2023-09-01 |
+|1.6.0 |>=1.161 |Deprecated with support ending 2023-09-01 |
+|1.4.0 |>=1.151 |Deprecated with support ending 2023-09-01 |
+|1.3.0 |>=1.149 |Deprecated with support ending 2023-09-01 |
+|1.2.0 |>=1.147 |Deprecated with support ending 2023-09-01 |
+|1.1.0 |>=1.143 |Deprecated with support ending 2023-09-01 |
+|1.0.3 |>=1.135 |Deprecated with support ending 2023-09-01 |
-## Integrating into your application
+## Integration
### Dependencies
-If you want to integrate the OneAgent SDK into your application, just add the following maven dependency:
-
- com.dynatrace.oneagent.sdk.java
- oneagent-sdk
- 1.0.3
- compile
-
+If you want to integrate the OneAgent SDK into your application, just add the following Maven dependency:
-If you prefer to integrate the SDK using plain jar file, just download them from mavenCentral - Dynatrace OneAgent SDK for Java [binary](https://search.maven.org/remotecontent?filepath=com/dynatrace/oneagent/sdk/java/oneagent-sdk/1.0.3/oneagent-sdk-1.0.3.jar), [source](https://search.maven.org/remotecontent?filepath=com/dynatrace/oneagent/sdk/java/oneagent-sdk/1.0.3/oneagent-sdk-1.0.3-sources.jar) and [javadoc](https://search.maven.org/remotecontent?filepath=com/dynatrace/oneagent/sdk/java/oneagent-sdk/1.0.3/oneagent-sdk-1.0.3-javadoc.jar)
+```xml
+
+ com.dynatrace.oneagent.sdk.java
+ oneagent-sdk
+ 1.9.0
+ compile
+
+```
+
+If you prefer to integrate the SDK using plain jar file, just download them from Maven Central, e.g. from
+.
The Dynatrace OneAgent SDK for Java has no further dependencies.
### Troubleshooting
-If the SDK can't connect to the OneAgent (see usage of SDKState in samples) or you you don't see the desired result in the Dynatrace UI, you can set the following system property to print debug information to standard out:
-
- -Dcom.dynatrace.oneagent.sdk.debug=true
-Additionally you should/have to ensure, that you have set a `LoggingCallback`. For usage see class `StdErrLoggingCallback` in `remotecall-server` module (in samples/remotecall folder).
+If the SDK can't connect to the OneAgent (see usage of SDKState in samples) or you you don't see the desired result in the Dynatrace UI,
+you can set the following system property to print debug information to standard out:
-## OneAgent SDK for Java Requirements
+```java
+-Dcom.dynatrace.oneagent.sdk.debug=true
+```
-- JRE 1.6 or higher
-- Dynatrace OneAgent Java (supported versions see below)
+Additionally you should/have to ensure, that you have set a `LoggingCallback`. For usage see class `StdErrLoggingCallback` in
+`remotecall-server` module (in samples/remotecall folder).
-# API Concepts
+## API concepts
-Common concepts of the Dynatrace OneAgent SDK are explained the [Dynatrace OneAgent SDK repository](https://github.com/Dynatrace/OneAgent-SDK).
+Common concepts of the Dynatrace OneAgent SDK are explained in the [Dynatrace OneAgent SDK repository](https://github.com/Dynatrace/OneAgent-SDK#apiconcepts).
-## Get an Api object
+### OneAgentSDK object
-Use OneAgentSDKFactory.createInstance() to obtain an OneAgentSDK instance. You should reuse this object over the whole application
-and if possible JVM lifetime:
+Use OneAgentSDKFactory.createInstance() to obtain an OneAgentSDK instance. You should reuse this object throughout the whole application
+and, if possible, JVM lifetime:
```Java
OneAgentSDK oneAgentSdk = OneAgentSDKFactory.createInstance();
switch (oneAgentSdk.getCurrentState()) {
case ACTIVE:
- break;
+ break;
case PERMANENTLY_INACTIVE:
- break;
+ break;
case TEMPORARILY_INACTIVE:
- break;
+ break;
default:
- break;
+ break;
}
```
-It is good practice to check the SDK state regularly as it may change at every point of time (except PERMANENTLY_INACTIVE never changes over JVM lifetime).
+It is good practice to check the SDK state regularly as it may change at any point in time (except for PERMANENTLY_INACTIVE, which never
+changes throughout the JVM lifetime).
+
+
+
-## Common concepts: Tracers
+## Trace Context
-To trace any kind of call you first need to create a Tracer. The Tracer object represents the logical and physical endpoint that you want to call. A Tracer serves two purposes. First to time the call (duraction, cpu and more) and report errors. That is why each Tracer has these three methods. The error method must be called only once, and it must be in between start and end.
+An instance of the `OneAgentSDK` can be used to get the current `ITraceContextInfo` which holds information
+about the *Trace-Id* and *Span-Id* of the current PurePath node.
+This information can then be used to provide e.g. additional context in log messages.
+
+Please note that `TraceContextInfo` is not intended for tagging or context-propagation use cases.
+Dedicated APIs (e.g. [remote calls](#remoting) or [web requests](#webrequests)) as well as
+built-in OneAgent sensors take care of linking services correctly.
+
+```Java
+TraceContextInfo traceContextInfo = oneAgentSdk.getTraceContextInfo();
+String traceId = traceContextInfo.getTraceId();
+String spanId = traceContextInfo.getSpanId();
+System.out.printf("[!dt dt.trace_id=%s,dt.span_id=%s] sending request... have trace ctx: %s%n",
+traceId, spanId, traceContextInfo.isValid());
+```
+
+### Tracers
+
+To trace any kind of call you first need to create a Tracer. The Tracer object represents the logical and physical endpoint that
+you want to call. A Tracer serves two purposes. First, to time the call (duration, cpu and more) and report errors. That is why
+each Tracer has these three methods. The error method must be called only once, and it must be in between start and end.
+
+A Tracer instance can only be used from the thread on which it was created.
+See [in process linking](#in-process-linking) for tracing across thread boundaries, and see further below in this section
+for how to cross process boundaries.
```Java
void start();
@@ -79,17 +152,59 @@ void error(String message);
void end();
```
-The second purpose of a Tracer is to allow tracing across process boundaries. To achieve that these kind of traces supply so called tags. Tags are strings or byte arrays that enable Dynatrace to trace a transaction end to end. As such the tag is the one information that you need to transport across these calls yourselfs.
+`start()` records the active PurePath node on the current Java thread
+as parent (if any; whether created by another Tracer or the OneAgent), creates a new PurePath node
+and sets the new one as the currently active one. The OneAgent also requires that a child node ends
+before all parent nodes (Stated another way, tracers on the same thread must be ended in the opposite
+order of how they were started. While this may sound odd if you hear it the first time, it corresponds
+to the most natural usage pattern and you usually don't even need to think about it).
+
+While the tracer's automatic parent-child relationship works very intuitively in most cases,
+it does not work with **asynchronous patterns**, where the same thread handles multiple logically
+separate operations in an interleaved way on the same Java thread. If you need to instrument
+such patterns, it is recommended to use the OneAgent's [OpenTelemetry interoperability][oa-otel].
+
+[oa-otel]: https://www.dynatrace.com/support/help/shortlink/opent-java
-## Using the Dynatrace OneAgent SDK to trace remote calls
+The second purpose of a Tracer is to allow tracing across process boundaries. To achieve that these kind of traces supply so called
+tags. Tags are strings or byte arrays that enable Dynatrace to trace a transaction end to end. As such the tag is the one information
+that you need to transport across these calls as an SDK user.
+
+## Features
+
+The feature sets differ slightly with each language implementation. More functionality will be added over time, see Planned features for OneAgent SDK
+for details on upcoming features.
+
+A more detailed specification of the features can be found in [Dynatrace OneAgent SDK](https://github.com/Dynatrace/OneAgent-SDK#features).
+
+|Feature |Required OneAgent SDK for Java version|
+|:----------------------------------------------|:-------------------------------------|
+|Trace context for log enrichment |>=1.9.0 |
+|Custom services |>=1.8.0 |
+|Trace database requests |>=1.7.0 |
+|Trace messaging |>=1.6.0 |
+|Outgoing web requests |>=1.4.0 |
+|Incoming web requests |>=1.3.0 |
+|Custom request attributes |>=1.2.0 |
+|In process linking |>=1.1.0 |
+|Trace incoming and outgoing remote calls |>=1.0.3 |
-You can use the SDK to trace proprietary IPC communication from one process to the other. This will enable you to see full Service Flow, PurePath and Smartscape topology for remoting technologies that Dynatrace is not aware of.
-To trace any kind of remote call you first need to create a Tracer. The Tracer object represents the endpoint that you want to call, as such you need to supply the name of the remote service and remote method. In addition you need to transport the tag in your remote call to the server side if you want to trace it end to end.
+
+
+### Trace incoming and outgoing remote calls
+
+You can use the SDK to trace proprietary IPC communication from one process to the other. This will enable you to see full Service Flow, PurePath
+and Smartscape topology for remoting technologies that Dynatrace is not aware of.
+
+To trace any kind of remote call you first need to create a Tracer. The Tracer object represents the endpoint that you want to call, as such you
+need to supply the name of the remote service and remote method. In addition you need to transport the tag in your remote call to the server side
+if you want to trace it end to end.
```Java
-OutgoingRemoteCallTracer outgoingRemoteCall = OneAgentSDK.traceOutgoingRemoteCall("remoteMethodToCall", "RemoteServiceName", "rmi://Endpoint/service", ChannelType.TCP_IP, "remoteHost:1234");
+OneAgentSDK oneAgentSdk = OneAgentSDKFactory.createInstance();
+OutgoingRemoteCallTracer outgoingRemoteCall = oneAgentSdk.traceOutgoingRemoteCall("remoteMethodToCall", "RemoteServiceName", "rmi://Endpoint/service", ChannelType.TCP_IP, "remoteHost:1234");
outgoingRemoteCall.setProtocolName("RMI/custom");
outgoingRemoteCall.start();
try {
@@ -97,15 +212,18 @@ try {
// make the call and transport the tag across to server
} catch (Throwable e) {
outgoingRemoteCall.error(e);
+ // rethrow or add your exception handling
} finally {
outgoingRemoteCall.end();
}
```
-On the server side you need to wrap the handling and processing of your remote call as well. This will not only trace the server side call and everything that happens, it will also connect it to the calling side.
+On the server side you need to wrap the handling and processing of your remote call as well. This will not only trace the server side call and
+everything that happens, it will also connect it to the calling side.
```Java
-IncomingRemoteCallTracer incomingRemoteCall = OneAgentSDK.traceIncomingRemoteCall("remoteMethodToCall", "RemoteServiceName", "rmi://Endpoint/service");
+OneAgentSDK oneAgentSdk = OneAgentSDKFactory.createInstance();
+IncomingRemoteCallTracer incomingRemoteCall = oneAgentSdk.traceIncomingRemoteCall("remoteMethodToCall", "RemoteServiceName", "rmi://Endpoint/service");
incomingRemoteCall.setDynatraceStringTag(tag);
incomingRemoteCall.start();
try {
@@ -113,22 +231,336 @@ try {
doSomeWork(); // process the remoteCall
} catch (Exception e) {
incomingRemoteCall.error(e);
-}finally{
+ // rethrow or add your exception handling
+} finally{
incomingRemoteCall.end();
}
```
-### Compatibility OneAgent SDK for Java releases with OneAgent for Java releases
-|OneAgent SDK for Java|Dynatrace OneAgent Java|
-|:------|:--------|
-|1.0.3 |>=1.135 |
+### In process linking
+
+You can use the SDK to link inside a single process. To link for eg. an asynchronous execution, you need the following code:
+
+```Java
+OneAgentSDK oneAgentSdk = OneAgentSDKFactory.createInstance();
+InProcessLink inProcessLink = oneAgentSdk.createInProcessLink();
+```
+
+Provide the returned ``inProcessLink`` to the code, that does the asynchronous execution:
+
+```Java
+OneAgentSDK oneAgentSdk = OneAgentSDKFactory.createInstance();
+InProcessLinkTracer inProcessLinkTracer = oneAgentSdk.traceInProcessLink(inProcessLink);
+inProcessLinkTracer.start();
+try {
+ // do the work ...
+} catch (Exception e) {
+ inProcessLinkTracer.error(e);
+ // rethrow or add your exception handling
+} finally {
+ inProcessLinkTracer.end();
+}
+```
+
+### Add custom request attributes
+
+You can use the SDK to add custom request attributes to the current traced service. Custom request attributes allow you to do advanced filtering of
+your requests in Dynatrace.
+
+Adding custom request attributes to the currently traced service call is simple. Just call one of the addCustomRequestAttribute methods with your key and value:
+
+```Java
+oneAgentSDK.addCustomRequestAttribute("region", "EMEA");
+oneAgentSDK.addCustomRequestAttribute("salesAmount", 2500);
+```
+
+When no service call is being traced, the custom request attributes are dropped.
+
+### Custom services
+
+You can use the SDK to trace custom service methods. A custom service method is a meaningful
+part of your code that you want to trace but that does not fit any other tracer.
+An example could be the callback of a periodic timer.
+
+```Java
+String serviceMethod = "onTimer";
+String serviceName = "PeriodicCleanupTask";
+CustomServiceTracer tracer = oneAgentSDK.traceCustomService(serviceMethod, serviceName);
+tracer.start();
+try {
+ doMyCleanup();
+} catch (Exception e) {
+ tracer.error(e.getMessage());
+ throw e;
+} finally {
+ tracer.end();
+}
+```
+
+
+
+### Trace web requests
+
+#### Trace incoming web requests
+
+You can use the SDK to trace incoming web requests. This might be useful if Dynatrace does not support the respective web server framework or language
+processing the incoming web requests.
+
+To trace an incoming web request you first need to create a WebApplicationInfo object. The info object represents the endpoint of your web server (web server name, application name and context root). This object should be reused for all traced web requests within for the same application.
+
+```Java
+WebApplicationInfo wsInfo = oneAgentSdk.createWebApplicationInfo("WebShopProduction", "CheckoutService", "/api/service/checkout");
+```
+
+To trace a specific incoming web request you then need to create a Tracer object. Make sure you provide all http headers from the request
+to the SDK by calling `addRequestHeader(...)`. This ensures that tagging with our built-in sensors will work.
+
+**Note**:
+
+* Previous OneAgent versions only supported the proprietary Dynatrace tracing header (`x-dynatrace`).
+* Starting with OneAgent version `1.317`, [**W3C Trace Context**](https://www.w3.org/TR/trace-context) headers will be processed as well if they are provided via `addRequestHeader`.
+
+```Java
+IncomingWebRequestTracer tracer = oneAgentSdk.traceIncomingWebRequest(wsInfo,"https://www.oursupershop.com/api/service/checkout/save", "POST")
+
+for (Entry headerField : httpRequest.getHeaders().entrySet()) {
+ tracer.addRequestHeader(headerField.getKey(), headerField.getValue());
+}
+
+for (Entry> parameterEntry : httpRequest.getParameters().entrySet()) {
+ for (String value : parameterEntry.getValue()) {
+ tracer.addParameter(parameterEntry.getKey(), value);
+ }
+}
+
+tracer.setRemoteAddress(httpRequest.getRemoteHostName());
+
+tracer.start();
+try {
+ int statusCodeReturnedToClient = processWebRequest();
+ tracer.setStatusCode(statusCodeReturnedToClient);
+} catch (Exception e) {
+ tracer.setStatusCode(500); // we expect that the container sends HTTP 500 status code in case request processing throws an exception
+ tracer.error(e);
+ throw e;
+} finally {
+ tracer.end();
+}
+```
+
+#### Trace outgoing web requests
+
+You can use the SDK to trace outgoing web requests. This might be useful if Dynatrace does not support the respective http library or
+language sending the request.
+
+To trace an outgoing web request you need to create a Tracer object. It is important to send the Dynatrace Header. This ensures that
+tagging with our built-in sensor will work.
+
+```Java
+OutgoingWebRequestTracer outgoingWebRequestTracer = oneAgentSdk.traceOutgoingWebRequest(url, "GET");
+
+// provide all request headers to outgoingWebRequestTracer (optional):
+for (Entry entry : yourHttpClient.getRequestHeaders().entrySet()) {
+ outgoingWebRequestTracer.addRequestHeader(entry.getKey(), entry.getValue());
+}
+
+outgoingWebRequestTracer.start();
+try {
+ yourHttpClient.setUrl(url);
+
+ // sending HTTP header OneAgentSDK.DYNATRACE_HTTP_HEADERNAME is necessary for tagging:
+ yourHttpClient.addRequestHeader(OneAgentSDK.DYNATRACE_HTTP_HEADERNAME, outgoingWebRequestTracer.getDynatraceStringTag());
+
+ yourHttpClient.processHttpRequest();
+
+ for (Entry> entry : yourHttpClient.getHeaderFields().entrySet()) {
+ for (String value : entry.getValue()) {
+ outgoingWebRequestTracer.addResponseHeader(entry.getKey(), value);
+ }
+ }
+ outgoingWebRequestTracer.setStatusCode(yourHttpClient.getResponseCode());
+
+} catch (Exception e) {
+ outgoingWebRequestTracer.error(e);
+ // rethrow or add your exception handling
+} finally {
+ outgoingWebRequestTracer.end();
+}
+```
+
+### Trace messaging
+
+You can use the SDK to trace messages sent or received via messaging & queuing systems. When tracing messages, we distinguish between:
+
+* sending a message
+* receiving a message
+* processing a received message
+
+To trace an outgoing message, you simply need to create a MessagingSystemInfo and call traceOutgoingMessage with that instance:
+
+```Java
+MessagingSystemInfo messagingSystemInfo = oneAgentSDK.createMessagingSystemInfo("myMessagingSystem",
+ "requestQueue", MessageDestinationType.QUEUE, ChannelType.TCP_IP, "localhost:4711");
+OutgoingMessageTracer outgoingMessageTracer = oneAgentSDK.traceOutgoingMessage(messagingSystemInfo);
+outgoingMessageTracer.start();
+try {
+ // transport the dynatrace tag along with the message:
+ messageToSend.setHeaderField(
+ OneAgentSDK.DYNATRACE_MESSAGE_PROPERTYNAME, outgoingMessageTracer.getDynatraceStringTag());
+ // optional: add application provided correlationId
+ outgoingMessageTracer.setCorrelationId(toSend.correlationId);
+
+ theQueue.send(messageToSend);
+
+ // optional: add messageid provided from messaging system
+ outgoingMessageTracer.setVendorMessageId(toSend.getMessageId());
+} catch (Exception e) {
+ outgoingMessageTracer.error(e.getMessage());
+ // rethrow or add your exception handling
+} finally {
+ outgoingMessageTracer.end();
+}
+```
+
+On the incoming side, we need to differentiate between the blocking receiving part and processing the received message. Therefore two
+different tracers are being used: `IncomingMessageReceiveTracer` and `IncomingMessageProcessTracer`.
+
+```Java
+MessagingSystemInfo messagingSystemInfo = oneAgentSDK.createMessagingSystemInfo("myMessagingSystem",
+ "requestQueue", MessageDestinationType.QUEUE, ChannelType.TCP_IP, "localhost:4711");
+
+// message receiving daemon task:
+while(true) {
+ IncomingMessageReceiveTracer incomingMessageReceiveTracer =
+ oneAgentSDK.traceIncomingMessageReceive(messagingSystemInfo);
+ incomingMessageReceiveTracer.start();
+ try {
+ // blocking call - until message is being available:
+ Message queryMessage = theQueue.receive("client queries");
+ IncomingMessageProcessTracer incomingMessageProcessTracer = oneAgentSDK
+ .traceIncomingMessageProcess(messagingSystemInfo);
+ incomingMessageProcessTracer.setDynatraceStringTag(
+ queryMessage.getHeaderField(OneAgentSDK.DYNATRACE_MESSAGE_PROPERTYNAME));
+ incomingMessageProcessTracer.setVendorMessageId(queryMessage.msgId);
+ incomingMessageProcessTracer.setCorrelationId(queryMessage.correlationId);
+ incomingMessageProcessTracer.start();
+ try {
+ // do the work ...
+ } catch (Exception e) {
+ incomingMessageProcessTracer.error(e.getMessage());
+ Logger.logError(e);
+ } finally {
+ incomingMessageProcessTracer.end();
+ }
+ } catch (Exception e) {
+ incomingMessageReceiveTracer.error(e.getMessage());
+ // rethrow or add your exception handling
+ } finally {
+ incomingMessageReceiveTracer.end();
+ }
+}
+```
+
+In case of non-blocking receive (e. g. via event handler), there is no need to use `IncomingMessageReceiveTracer` - just trace processing
+of the message by using the `IncomingMessageProcessTracer`:
+
+```Java
+MessagingSystemInfo messagingSystemInfo = oneAgentSDK.createMessagingSystemInfo("myMessagingSystem",
+ "requestQueue", MessageDestinationType.QUEUE, ChannelType.TCP_IP, "localhost:4711");
+
+public void onMessage(Message message) {
+ IncomingMessageProcessTracer incomingMessageProcessTracer = oneAgentSDK
+ .traceIncomingMessageProcess(messagingSystemInfo);
+ incomingMessageProcessTracer.setDynatraceStringTag((String)
+ message.getObjectProperty(OneAgentSDK.DYNATRACE_MESSAGE_PROPERTYNAME));
+ incomingMessageProcessTracer.setVendorMessageId(queryMessage.msgId);
+ incomingMessageProcessTracer.setCorrelationId(queryMessage.correlationId);
+ incomingMessageProcessTracer.start();
+ try {
+ // do the work ...
+ } catch (Exception e) {
+ incomingMessageProcessTracer.error(e.getMessage());
+ // rethrow or add your exception handling
+ } finally {
+ incomingMessageProcessTracer.end();
+ }
+}
+```
+
+> Please also see the [documentation on messaging tracers in the specification repository](https://github.com/Dynatrace/OneAgent-SDK#messaging).
+
+### Trace SQL database requests
+
+A SQL database request is traced by calling `traceSqlDatabaseRequest`. For details about usage see the [OneAgentSDK specification](https://github.com/Dynatrace/OneAgent-SDK#database)
+
+```java
+String sql = "SELECT * FROM transformationdata WHERE transformation_id = " + id;
+
+DatabaseInfo databaseInfo = oneAgentSdk.createDatabaseInfo("TransformationDb", DatabaseVendor.FIREBIRD.getVendorName(), ChannelType.TCP_IP, "db-serv01.acme.com:2323");
+
+DatabaseRequestTracer databaseTracer = oneAgentSdk.traceSqlDatabaseRequest(databaseInfo, sql);
+databaseTracer.start();
+try {
+ Result result = executeTheDatabaseCall(sql);
+ databaseTracer.setReturnedRowCount(result.getRows().getLength());
+} catch (InterruptedException e) {
+ databaseTracer.error(e);
+ // handle or rethrow
+} finally {
+ databaseTracer.end();
+}
+```
+
+Please note that SQL database traces are only created if they occur within some other SDK trace (e.g. incoming remote call)
+or a OneAgent built-in trace (e.g. incoming web request).
+
+## Further reading
+
+* What is the OneAgent SDK? in the Dynatrace documentation
+* Feedback & Roadmap thread in AnswerHub
+* Blog: Dynatrace OneAgent SDK for Java: End-to-end monitoring for proprietary Java frameworks
+
+## Help & support
+
+### Support policy
+
+The Dynatrace OneAgent SDK for Java has GA status. The features are fully supported by Dynatrace.
+
+For detailed support policy see [Dynatrace OneAgent SDK help](https://github.com/Dynatrace/OneAgent-SDK#help).
+
+### Get help
+
+* Ask a question in the product forums
+* Read the product documentation
+
+**Open a GitHub issue to:**
+
+* Report minor defects, minor items or typos
+* Ask for improvements or changes in the SDK API
+* Ask any questions related to the community effort
+
+SLAs don't apply for GitHub tickets
+
+**Customers can open a ticket on the Dynatrace support portal to:**
+
+* Get support from the Dynatrace technical support engineering team
+* Manage and resolve product related technical issues
+
+SLAs apply according to the customer's support level.
+
+## Release notes
+
+### Version 1.9.0
+
+* [Add support to retrieve W3C trace context information for log enrichment.](#tracecontext)
+
+### Other announcements
-## Feedback
+* [**W3C Trace Context**](https://www.w3.org/TR/trace-context/) headers for [incoming web requests](#trace-incoming-web-requests) are
+supported with OneAgent versions starting from `1.317`.
-In case of questions, issues or feature requests feel free to contact [Michael Kopp](https://github.com/mikopp), [Alram Lechner](https://github.com/AlramLechnerDynatrace) or file an issue. Your feedback is welcome!
+* ⚠️ **Deprecation announcement for older SDK versions:** Version 1.7 and all older versions have been put on the path to deprecation and will no longer be supported starting September 1, 2023. We advise customers to upgrade to newest version. Customers need to upgrade to at least 1.8 but are encouraged to upgrade to the newest available version (1.9).
+### Older versions
-## OneAgent SDK for Java release notes
-|Version|Date|Description|
-|:------|:----------|:------------------|
-|1.0.3 |01.2018 |Initial release |
+See for older release notes.
diff --git a/docs/META-INF/MANIFEST.MF b/docs/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..59499bc
--- /dev/null
+++ b/docs/META-INF/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+
diff --git a/docs/allclasses-frame.html b/docs/allclasses-frame.html
new file mode 100755
index 0000000..51df98b
--- /dev/null
+++ b/docs/allclasses-frame.html
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+All Classes (sdk 1.9.0 API)
+
+
+
+
+
+
+
+
+
+
+
+All Classes
+
+
+
Provides a OneAgentSDK instance, that has to be used to create
+ transactions. It is safe to use returned OneAgentSDK instance in
+ multiple threads. Every application should only create one single SDK
+ instance during its lifetime.
+
+
+
+
Returns:
never null. if no OneAgent present, NOOP implementation gets
+ returned.
+Represents the server side of a remote call. This Interface extends
+ Tracer - it is important to respect the mentioned requirements when
+ working with IncomingRemoteCallTracer.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Method Summary
+
+
+
+ void
+
setProtocolName(java.lang.String protocolName)
+
+
+ Sets the name of the used remoting protocol.
+
+
+
+
+
+
Methods inherited from interface com.dynatrace.oneagent.sdk.api.Tracer
Validates and sets the remote IP address of the incoming web request. This
+ information is very useful to gain information about Load balancers, Proxies
+ and ultimately the end user that is sending the request.
+
+LoggingCallback gets called only inside a OneAgentSDK API call when an
+ error/warning has occurred.
+ Never call any SDK API inside one of these callback methods.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Method Summary
+
+
+
+ void
+
error(java.lang.String message)
+
+
+ Something that should be done can't be done.
+
+
+
+ void
+
warn(java.lang.String message)
+
+
+ Just a warning.
+
+
+
+
+
+
+
+
+
+
+
+Method Detail
+
+
+
+
+warn
+
+void warn(java.lang.String message)
+
+
Just a warning. Something is missing, but OneAgent is working normal.
+
+
+
Parameters:
message - message text. never null.
Since:
+
1.0
+
+
+
+
+
+
+error
+
+void error(java.lang.String message)
+
+
Something that should be done can't be done. (e. g. PurePath could not be
+ started)
+
+Root interface contains provided Agent SDK API calls. Basically the whole API
+ is designed according to following rules:
+
+
API calls never throw any exception
+
API calls never return null values. e. g. they returning NOOP Objects in
+ case of any issue or required parameters are null.
+
+ Single API calls might differ from that rules. Those rules are explicitly
+ documented.
+
+
+
+
+
+
+
+
+
+
+
+
+Field Summary
+
+
+
+static java.lang.String
+
DYNATRACE_HTTP_HEADERNAME
+
+
+ Using this headername to transport Dynatrace tag inside an outgoing http
+ request ensures compatibility to Dynatrace built-in sensors.
+
+
+
+static java.lang.String
+
DYNATRACE_MESSAGE_PROPERTYNAME
+
+
+ Using this propertyname to transport Dynatrace tag along with the message, ensures compatibility to Dynatrace built-in sensors.
createWebApplicationInfo(java.lang.String webServerName,
+ java.lang.String applicationID,
+ java.lang.String contextRoot)
+
+
+ Initializes a WebApplicationInfo instance that is required for tracing
+ incoming web requests.
getTraceContextInfo()
+
+
+ Returns the current W3C trace context for log enrichment
+ (not meant for tagging and context-propagation but for log-enrichment).
traceCustomService(java.lang.String serviceMethod,
+ java.lang.String serviceName)
+
+
+ Creates a tracer for a custom transaction (Dynatrace calls them Custom service).
Initializes a DatabaseInfo instance that is required for tracing database requests.
+
+
+
Parameters:
name - name of the database
vendor - database vendor name (e.g. Oracle, MySQL, ...), can be a user defined name
+ If possible use a constant defined in DatabaseVendor
channelType - communication protocol used to communicate with the database.
channelEndpoint - this represents the communication endpoint for the database. This information allows Dynatrace to tie the database requests to a specific process or cloud service. It is optional.
+ * for TCP/IP: host name/IP of the server-side (can include port in the form of "host:port")
+ * for UNIX domain sockets: name of domain socket file
+ * for named pipes: name of pipe
+
Initializes a WebApplicationInfo instance that is required for tracing
+ incoming web requests. This information determines the identity and name of
+ the resulting Web Request service in dynatrace. Also see
+ https://www.dynatrace.com/support/help/server-side-services/introduction/how-does-dynatrace-detect-and-name-services/#web-request-services
+ for detail description of the meaning of the parameters.
+
+
+
Parameters:
webServerName - logical name of the web server. In case of a cluster every node in
+ the cluster must report the same name here. Attention: Make sure
+ not to use the host header for this parameter. Host headers are
+ often spoofed and contain things like google or baidoo which do
+ not reflect your setup.
applicationID - application ID of the web application
contextRoot - context root of the application. All URLs traced with the returned
+ WebApplicationInfo, should start with provided context root.
+
webApplicationInfo - information about web application
url - (parts of a) URL, which will be parsed into: scheme,
+ hostname/port, path & query Note: the hostname will be resolved by
+ the Agent at start() call
Adds a custom request attribute to currently traced service call. Might be
+ called multiple times, to add more than one attribute. Check via
+ setLoggingCallback(LoggingCallback) if error happened. If two
+ attributes with same key are set, both attribute-values are captured.
+
+
+
Parameters:
key - key of the attribute. required parameter.
value - value of the attribute. required parameter.
Since:
+
1.2
+
+
+
+
+
+
+addCustomRequestAttribute
+
+void addCustomRequestAttribute(java.lang.String key,
+ long value)
channelEndpoint - optional and depending on protocol:
+ * for TCP/IP: host name/IP of the server-side (can include port)
+ * for UNIX domain sockets: name of domain socket file
+ * for named pipes: name of pipe
+
Installs a callback that gets informed, if any SDK action has failed. For
+ details see LoggingCallback interface. The provided callback must be
+ thread-safe, when using this OneAgentSDK instance in multi-threaded
+ environments.
+
+
+
Parameters:
loggingCallback - may be null, to remove current callback. provided callback
+ replaces any previously set callback.
Creates a tracer for a custom transaction (Dynatrace calls them Custom service). Used whenever a transaction
+ should be traced, that does not match any of the specialised transaction types (e. g. DB-request, webrequest, ...).
+
+
+
Parameters:
serviceMethod - service method being used for service creation.
serviceName - service name being used for service creation.
+
Returns the current W3C trace context for log enrichment
+ (not meant for tagging and context-propagation but for log-enrichment).
+ See TraceContextInfo for details.
+
+
+
+
Returns:
current trace context at the time of the call - never null (but may contain all-zero ID).
+Represents the client side of a remote call.
+
+ This Interface extends Tracer - it is important to respect the
+ mentioned requirements when working with OutgoingRemoteCallTracer.
+
+
+
+
+
+
+
+
+
+
+
+
+
+Method Summary
+
+
+
+ void
+
setProtocolName(java.lang.String protocolName)
+
+
+ Sets the name of the used remoting protocol.
+
+
+
+
+
+
Methods inherited from interface com.dynatrace.oneagent.sdk.api.Tracer
getDynatraceStringTag()
+
+
+ Creates a Dynatrace tag and returns the String representation of it.
+
+
+
+
+
+
+
+
+
+
+
+Method Detail
+
+
+
+
+getDynatraceStringTag
+
+java.lang.String getDynatraceStringTag()
+
+
Creates a Dynatrace tag and returns the String representation of it. This tag
+ has to be transported with the remoting protocol to the destination.
+ See IncomingTaggable how to continue a path with provided tag on the
+ server side.
+
+Represents client side of an outgoing webrequest.
+
+
+
+
+
Since:
+
1.4
+
+
+
+
+
+
+
+
+
+
+
+Method Summary
+
+
+
+ void
+
addRequestHeader(java.lang.String name,
+ java.lang.String value)
+
+
+ All HTTP request headers should be provided to this method.
+
+
+
+ void
+
addResponseHeader(java.lang.String name,
+ java.lang.String value)
+
+
+ All HTTP response headers returned by the server should be provided to this
+ method.
+
+
+
+ void
+
setStatusCode(int statusCode)
+
+
+ Sets the HTTP response status code.
+
+
+
+
+
+
Methods inherited from interface com.dynatrace.oneagent.sdk.api.Tracer
All HTTP response headers returned by the server should be provided to this
+ method. Selective capturing will be done based on sensor configuration.
+
+
+
+
+
+
Parameters:
name - HTTP response header field name
value - HTTP response header field value
+
+
+
+
+
+setStatusCode
+
+void setStatusCode(int statusCode)
+
+
Sets the HTTP response status code.
+
+
+
+
+
+
Parameters:
statusCode - HTTP status code retrieved from server
Ends timing of a node. Typically this method is called via finally block.
+
+ start(), end(), error(String),
+ error(Throwable) are not thread-safe. They must be called from the
+ same thread where start() has been invoked.
+
+
+
Since:
+
1.0
+
+
+
+
+
+
+error
+
+void error(java.lang.String message)
+
+
Marks the node as 'exited by exception'. An additional error message can be
+ provided as String.
+ start(), end(), error(String),
+ error(Throwable) are not thread-safe. They must be called from the
+ same thread where start() has been invoked.
+
+
+
Parameters:
message - error message with details about occurred error (eg. return code).
+ must not be null.
Since:
+
1.0
+
+
+
+
+
+
+error
+
+void error(java.lang.Throwable throwable)
+
+
Marks the node as 'exited by exception'.Additional information can be
+ provided as Throwable.
+ start(), end(), error(String),
+ error(Throwable) are not thread-safe. They must be called from the
+ same thread where start() has been invoked.
+
+
+
Parameters:
throwable - exception, that occurred. must not null.
Returns an array containing the constants of this enum type, in
+the order they are declared. This method may be used to iterate
+over the constants as follows:
+
+for (ChannelType c : ChannelType.values())
+ System.out.println(c);
+
+
+
+
+
Returns:
an array containing the constants of this enum type, in
+the order they are declared
Returns the enum constant of this type with the specified name.
+The string must match exactly an identifier used to declare an
+enum constant in this type. (Extraneous whitespace characters are
+not permitted.)
+
+
+
Parameters:
name - the name of the enum constant to be returned.
+
Returns:
the enum constant with the specified name
+
Throws:
+
java.lang.IllegalArgumentException - if this enum type has no constant
+with the specified name
+
java.lang.NullPointerException - if the argument is null
Returns an array containing the constants of this enum type, in
+the order they are declared. This method may be used to iterate
+over the constants as follows:
+
+for (DatabaseVendor c : DatabaseVendor.values())
+ System.out.println(c);
+
+
+
+
+
Returns:
an array containing the constants of this enum type, in
+the order they are declared
Returns the enum constant of this type with the specified name.
+The string must match exactly an identifier used to declare an
+enum constant in this type. (Extraneous whitespace characters are
+not permitted.)
+
+
+
Parameters:
name - the name of the enum constant to be returned.
+
Returns:
the enum constant with the specified name
+
Throws:
+
java.lang.IllegalArgumentException - if this enum type has no constant
+with the specified name
+
java.lang.NullPointerException - if the argument is null
Returns an array containing the constants of this enum type, in
+the order they are declared. This method may be used to iterate
+over the constants as follows:
+
+for (MessageDestinationType c : MessageDestinationType.values())
+ System.out.println(c);
+
+
+
+
+
Returns:
an array containing the constants of this enum type, in
+the order they are declared
Returns the enum constant of this type with the specified name.
+The string must match exactly an identifier used to declare an
+enum constant in this type. (Extraneous whitespace characters are
+not permitted.)
+
+
+
Parameters:
name - the name of the enum constant to be returned.
+
Returns:
the enum constant with the specified name
+
Throws:
+
java.lang.IllegalArgumentException - if this enum type has no constant
+with the specified name
+
java.lang.NullPointerException - if the argument is null
Returns an array containing the constants of this enum type, in
+the order they are declared. This method may be used to iterate
+over the constants as follows:
+
+for (MessageSystemVendor c : MessageSystemVendor.values())
+ System.out.println(c);
+
+
+
+
+
Returns:
an array containing the constants of this enum type, in
+the order they are declared
Returns the enum constant of this type with the specified name.
+The string must match exactly an identifier used to declare an
+enum constant in this type. (Extraneous whitespace characters are
+not permitted.)
+
+
+
Parameters:
name - the name of the enum constant to be returned.
+
Returns:
the enum constant with the specified name
+
Throws:
+
java.lang.IllegalArgumentException - if this enum type has no constant
+with the specified name
+
java.lang.NullPointerException - if the argument is null
ACTIVE
+
+
+ SDK is connected to OneAgent and capturing data.
+
+
+
PERMANENTLY_INACTIVE
+
+
+ SDK isn't connected to OneAgent, so it will never capture data.
+
+
+
TEMPORARILY_INACTIVE
+
+
+ SDK is connected to OneAgent, but capturing is disabled.It is good practice
+ to skip creating SDK transactions to save resources.
SDK is connected to OneAgent, but capturing is disabled.It is good practice
+ to skip creating SDK transactions to save resources. The SDK state should be
+ checked regularly as it may change at every point in time.
+
SDK isn't connected to OneAgent, so it will never capture data. This SDK
+ state will never change during the lifetime of a JVM. It is good practice to
+ never call any SDK API to save resources.
+
Returns an array containing the constants of this enum type, in
+the order they are declared. This method may be used to iterate
+over the constants as follows:
+
+for (SDKState c : SDKState.values())
+ System.out.println(c);
+
+
+
+
+
Returns:
an array containing the constants of this enum type, in
+the order they are declared
Returns the enum constant of this type with the specified name.
+The string must match exactly an identifier used to declare an
+enum constant in this type. (Extraneous whitespace characters are
+not permitted.)
+
+
+
Parameters:
name - the name of the enum constant to be returned.
+
Returns:
the enum constant with the specified name
+
Throws:
+
java.lang.IllegalArgumentException - if this enum type has no constant
+with the specified name
+
java.lang.NullPointerException - if the argument is null
+This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
+Overview
+
+
+
+The Overview page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.
+
+Package
+
+
+
+Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain four categories:
+
Interfaces (italic)
Classes
Enums
Exceptions
Errors
Annotation Types
+
+
+Class/Interface
+
+
+
+Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:
+
Class inheritance diagram
Direct Subclasses
All Known Subinterfaces
All Known Implementing Classes
Class/interface declaration
Class/interface description
+
+
Nested Class Summary
Field Summary
Constructor Summary
Method Summary
+
+
Field Detail
Constructor Detail
Method Detail
+Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.
+
+
+Annotation Type
+
+
+
+Each annotation type has its own separate page with the following sections:
+
Annotation Type declaration
Annotation Type description
Required Element Summary
Optional Element Summary
Element Detail
+
+
+
+Enum
+
+
+
+Each enum has its own separate page with the following sections:
+
Enum declaration
Enum description
Enum Constant Summary
Enum Constant Detail
+
+
+Tree (Class Hierarchy)
+
+There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with java.lang.Object. The interfaces do not inherit from java.lang.Object.
+
When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
+
+
+Deprecated API
+
+The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.
+
+Index
+
+The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.
+
+Prev/Next
+These links take you to the next or previous class, interface, package, or related page.
+Frames/No Frames
+These links show and hide the HTML frames. All pages are available with or without frames.
+
+
+Serialized Form
+Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
+
Provides information about a PurePath node using the TraceContext (Trace-Id, Span-Id) model as defined in
+ traceCustomService(String, String) -
+Method in interface com.dynatrace.oneagent.sdk.api.OneAgentSDK
+
Creates a tracer for a custom transaction (Dynatrace calls them Custom service).
+
+
+
+
+
+
+
+
diff --git a/docs/package-list b/docs/package-list
new file mode 100755
index 0000000..ebefb0a
--- /dev/null
+++ b/docs/package-list
@@ -0,0 +1,4 @@
+com.dynatrace.oneagent.sdk
+com.dynatrace.oneagent.sdk.api
+com.dynatrace.oneagent.sdk.api.enums
+com.dynatrace.oneagent.sdk.api.infos
diff --git a/docs/resources/inherit.gif b/docs/resources/inherit.gif
new file mode 100755
index 0000000..c814867
Binary files /dev/null and b/docs/resources/inherit.gif differ
diff --git a/docs/stylesheet.css b/docs/stylesheet.css
new file mode 100755
index 0000000..6ea9e51
--- /dev/null
+++ b/docs/stylesheet.css
@@ -0,0 +1,29 @@
+/* Javadoc style sheet */
+
+/* Define colors, fonts and other style attributes here to override the defaults */
+
+/* Page background color */
+body { background-color: #FFFFFF; color:#000000 }
+
+/* Headings */
+h1 { font-size: 145% }
+
+/* Table colors */
+.TableHeadingColor { background: #CCCCFF; color:#000000 } /* Dark mauve */
+.TableSubHeadingColor { background: #EEEEFF; color:#000000 } /* Light mauve */
+.TableRowColor { background: #FFFFFF; color:#000000 } /* White */
+
+/* Font used in left-hand frame lists */
+.FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 }
+.FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 }
+.FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 }
+
+/* Navigation bar fonts and colors */
+.NavBarCell1 { background-color:#EEEEFF; color:#000000} /* Light mauve */
+.NavBarCell1Rev { background-color:#00008B; color:#FFFFFF} /* Dark Blue */
+.NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;color:#000000;}
+.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;color:#FFFFFF;}
+
+.NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000}
+.NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000}
+
diff --git a/samples/README.md b/samples/README.md
index 889427b..029f30b 100644
--- a/samples/README.md
+++ b/samples/README.md
@@ -1,10 +1,14 @@
-# Sample applications for OneAgent SDK for Java
+# Sample applications for OneAgent SDK for Java
Sample applications showing how to use Dynatrace OneAgent SDK for Java to create custom specific PurePaths and service calls.
## Contents
- `remotecall`: shows usage of remote call API. Allows you to tag remote calls in the same or between different JVMs.
+- `in-process-linking`: shows usage of in-process-linking API. Allows you to tag eg. asynchronous execution inside the same process.
+- `webrequest`: shows usage of outgoing and incoming web request tracing
+- `messaging`: shows usage of messaging
+- `database`: shows usage of database request tracing
## Build and prepare running sample applications
@@ -14,10 +18,50 @@ Sample applications showing how to use Dynatrace OneAgent SDK for Java to create
- run `mvn package` in root directory of the desired sample
### Run RemoteCall sample application
+
This Application shows how to trace remote calls and tag them. To run this sample you need to start a server and client sample application - both with Dynatrace OneAgent injected.
- Server: `mvn -pl remotecall-server exec:exec`
- Client: `mvn -pl remotecall-client exec:exec`
-Check your Dynatrace environment for newly created services.
\ No newline at end of file
+Check your Dynatrace environment for newly created service like that:
+
+
+### Run InProcessLinking sample application
+
+This Application shows how to in-process-linking and custom service attributes are being used. To run this sample you need to create a custom service for your tenant - and of course Dynatrace OneAgent must be installed.
+
+- ensure you have custom service for method `startAsyncOperation` in class `com.dynatrace.oneagent.sdk.samples.inprocesslinking.InProcessLinkingApp`
+- run sample: `mvn exec:exec`
+
+Check your Dynatrace environment for newly created services like that:
+
+
+### Run WebRequest sample application
+
+This Application shows how to trace outgoing- and incoming webrequests. To run this sample you just go into the sample directory and run the sample by typing:
+
+- run sample: `mvn exec:exec`
+
+### Run Messaging sample application
+
+This Application shows how to trace outgoing, receiving and processing of incoming messages. To run this sample you just go into the sample directory and run the sample by typing:
+
+- run sample: `mvn exec:exec`
+
+### Run DatabaseRequest sample application
+
+This Application shows how to trace database requests. To run this sample you just go into the sample directory and run the sample by typing:
+
+- run sample: `mvn exec:exec`
+
+To run this sample you need to create a custom service for your tenant. See source of sample app for details.
+
+### Run custom service sample application
+
+This Application shows how to trace a custom service.
+To run this sample, go into the sample directory and run the sample by typing:
+
+- run sample: `mvn exec:exec`
+
diff --git a/samples/custom-service/pom.xml b/samples/custom-service/pom.xml
new file mode 100644
index 0000000..2963ce5
--- /dev/null
+++ b/samples/custom-service/pom.xml
@@ -0,0 +1,84 @@
+
+ 4.0.0
+
+ com.dynatrace.oneagent.sdk.samples.customservice
+ custom-service-sample
+ 1.8.0
+ jar
+
+
+
+ com.dynatrace.oneagent.sdk.java
+ oneagent-sdk
+ 1.8.0
+ compile
+
+
+
+ https://github.com/Dynatrace/OneAgent-SDK-Java
+ Dynatrace OneAgent SDK Java custom service sample
+
+ Dynatrace
+ http://www.dynatrace.com
+
+
+
+ 1.6
+ 1.6
+ UTF-8
+ UTF-8
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+
+ true
+ com.dynatrace.oneagent.sdk.samples.customservice.CustomServiceApp
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+
+ exec
+
+
+
+
+ java
+
+ ${agent.agentpath}
+ -classpath
+
+ com.dynatrace.oneagent.sdk.samples.customservice.CustomServiceApp
+
+
+
+
+
+
+
diff --git a/samples/custom-service/src/main/java/com/dynatrace/oneagent/sdk/samples/customservice/CustomServiceApp.java b/samples/custom-service/src/main/java/com/dynatrace/oneagent/sdk/samples/customservice/CustomServiceApp.java
new file mode 100644
index 0000000..a300515
--- /dev/null
+++ b/samples/custom-service/src/main/java/com/dynatrace/oneagent/sdk/samples/customservice/CustomServiceApp.java
@@ -0,0 +1,77 @@
+package com.dynatrace.oneagent.sdk.samples.customservice;
+
+import com.dynatrace.oneagent.sdk.OneAgentSDKFactory;
+import com.dynatrace.oneagent.sdk.api.CustomServiceTracer;
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+
+/**
+ * Sample application that shows how a custom service should be traced.
+ *
+ * @author wolfgang.ziegler@dynatrace.com
+ *
+ */
+public class CustomServiceApp {
+
+ private final OneAgentSDK oneAgentSdk;
+
+ static CustomServiceApp instance;
+
+ private CustomServiceApp() {
+ oneAgentSdk = OneAgentSDKFactory.createInstance();
+ oneAgentSdk.setLoggingCallback(new StdErrLoggingCallback());
+ switch (oneAgentSdk.getCurrentState()) {
+ case ACTIVE:
+ System.out.println("SDK is active and capturing.");
+ break;
+ case PERMANENTLY_INACTIVE:
+ System.err.println(
+ "SDK is PERMANENTLY_INACTIVE; Probably no OneAgent injected or OneAgent is incompatible with SDK.");
+ break;
+ case TEMPORARILY_INACTIVE:
+ System.err.println(
+ "SDK is TEMPORARILY_INACTIVE; OneAgent has been deactivated - check OneAgent configuration.");
+ break;
+ default:
+ System.err.println("SDK is in unknown state.");
+ break;
+ }
+ instance = this;
+ }
+
+ public static void main(String args[]) {
+ System.out.println("*************************************************************");
+ System.out.println("** Running custom service request sample **");
+ System.out.println("*************************************************************");
+ try {
+ CustomServiceApp app = new CustomServiceApp();
+
+ app.traceCustomService();
+
+ System.out.println("sample application stopped. sleeping a while, so OneAgent is able to send data to server ...");
+ Thread.sleep(15000 * 3); // we have to wait - so OneAgent is able to send data to server
+ } catch (Exception e) {
+ System.err.println("custom service request sample failed: " + e.getMessage());
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ private void traceCustomService() throws Exception {
+ String serviceMethod = "onTimer";
+ String serviceName = "PeriodicCleanupTask";
+ CustomServiceTracer tracer = oneAgentSdk.traceCustomService(serviceMethod, serviceName);
+ tracer.start();
+ try {
+ doOtherThings();
+ } catch (Exception e) {
+ tracer.error(e.getMessage());
+ throw e;
+ } finally {
+ tracer.end();
+ }
+ }
+
+ private void doOtherThings() {
+ // ...
+ }
+}
diff --git a/samples/custom-service/src/main/java/com/dynatrace/oneagent/sdk/samples/customservice/StdErrLoggingCallback.java b/samples/custom-service/src/main/java/com/dynatrace/oneagent/sdk/samples/customservice/StdErrLoggingCallback.java
new file mode 100644
index 0000000..58d5080
--- /dev/null
+++ b/samples/custom-service/src/main/java/com/dynatrace/oneagent/sdk/samples/customservice/StdErrLoggingCallback.java
@@ -0,0 +1,37 @@
+package com.dynatrace.oneagent.sdk.samples.customservice;
+
+/*
+ * Copyright 2021 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.dynatrace.oneagent.sdk.api.LoggingCallback;
+
+/**
+ * Implementation of OneAgent Logging Callback. Just printing output messages to
+ * std err.
+ */
+public class StdErrLoggingCallback implements LoggingCallback {
+
+ @Override
+ public void error(String message) {
+ System.err.println("[OneAgent SDK ERROR]: " + message);
+ }
+
+ @Override
+ public void warn(String message) {
+ System.err.println("[OneAgent SDK WARNING]: " + message);
+ }
+
+}
diff --git a/samples/database/pom.xml b/samples/database/pom.xml
new file mode 100644
index 0000000..d77592c
--- /dev/null
+++ b/samples/database/pom.xml
@@ -0,0 +1,84 @@
+
+ 4.0.0
+
+ com.dynatrace.oneagent.sdk.samples.messaging
+ messaging-sample
+ 1.7.0
+ jar
+
+
+
+ com.dynatrace.oneagent.sdk.java
+ oneagent-sdk
+ 1.7.0
+ compile
+
+
+
+ https://github.com/Dynatrace/OneAgent-SDK-Java
+ Dynatrace OneAgent SDK Java database request sample
+
+ Dynatrace
+ http://www.dynatrace.com
+
+
+
+ 1.6
+ 1.6
+ UTF-8
+ UTF-8
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+
+ true
+ com.dynatrace.oneagent.sdk.samples.database.DatabaseApp
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+
+ exec
+
+
+
+
+ java
+
+ ${agent.agentpath}
+ -classpath
+
+ com.dynatrace.oneagent.sdk.samples.database.DatabaseApp
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/database/src/main/java/com/dynatrace/oneagent/sdk/samples/database/DatabaseApp.java b/samples/database/src/main/java/com/dynatrace/oneagent/sdk/samples/database/DatabaseApp.java
new file mode 100644
index 0000000..5056081
--- /dev/null
+++ b/samples/database/src/main/java/com/dynatrace/oneagent/sdk/samples/database/DatabaseApp.java
@@ -0,0 +1,85 @@
+package com.dynatrace.oneagent.sdk.samples.database;
+
+import com.dynatrace.oneagent.sdk.OneAgentSDKFactory;
+import com.dynatrace.oneagent.sdk.api.DatabaseRequestTracer;
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+import com.dynatrace.oneagent.sdk.api.enums.ChannelType;
+import com.dynatrace.oneagent.sdk.api.infos.DatabaseInfo;
+
+/**
+ * Sample application shows how database requests should be traced.
+ *
+ * @author Alram.Lechner
+ *
+ */
+public class DatabaseApp {
+
+ private final OneAgentSDK oneAgentSdk;
+
+ static DatabaseApp instance;
+
+ private DatabaseApp() {
+ oneAgentSdk = OneAgentSDKFactory.createInstance();
+ oneAgentSdk.setLoggingCallback(new StdErrLoggingCallback());
+ switch (oneAgentSdk.getCurrentState()) {
+ case ACTIVE:
+ System.out.println("SDK is active and capturing.");
+ break;
+ case PERMANENTLY_INACTIVE:
+ System.err.println(
+ "SDK is PERMANENTLY_INACTIVE; Probably no OneAgent injected or OneAgent is incompatible with SDK.");
+ break;
+ case TEMPORARILY_INACTIVE:
+ System.err.println(
+ "SDK is TEMPORARILY_INACTIVE; OneAgent has been deactivated - check OneAgent configuration.");
+ break;
+ default:
+ System.err.println("SDK is in unknown state.");
+ break;
+ }
+ instance = this;
+ }
+
+ public static void main(String args[]) {
+ System.out.println("*************************************************************");
+ System.out.println("** Running database request sample **");
+ System.out.println("*************************************************************");
+ try {
+ DatabaseApp app = new DatabaseApp();
+
+ app.traceSqlRequest("Select * from anyTable");
+
+ System.out.println("sample application stopped. sleeping a while, so OneAgent is able to send data to server ...");
+ Thread.sleep(15000 * 3); // we have to wait - so OneAgent is able to send data to server
+ } catch (Exception e) {
+ System.err.println("database request sample failed: " + e.getMessage());
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ /**
+ * You need to add a custom service for this method. a database request will only be captured, if it s part of an already
+ * started transaction.
+ * see Dynatrace help
+ * for more information about a custom service.
+ */
+ private void traceSqlRequest(String sql) {
+ DatabaseInfo databaseInfo = oneAgentSdk.createDatabaseInfo("myCoolDatabase", "UnsupportedDatabaseVendor", ChannelType.TCP_IP, "theDbHost.localdomain:3434");
+ DatabaseRequestTracer databaseRequestTracer = oneAgentSdk.traceSqlDatabaseRequest(databaseInfo, sql);
+ databaseRequestTracer.start();
+ try {
+ executeRequest(sql);
+ } catch(Exception e) {
+ databaseRequestTracer.error(e);
+ // handle or re-throw exception!
+ } finally {
+ databaseRequestTracer.end();
+ }
+ }
+
+ private void executeRequest(String sql) {
+ // run the sql against the db ...
+ }
+
+}
diff --git a/samples/database/src/main/java/com/dynatrace/oneagent/sdk/samples/database/StdErrLoggingCallback.java b/samples/database/src/main/java/com/dynatrace/oneagent/sdk/samples/database/StdErrLoggingCallback.java
new file mode 100644
index 0000000..c6d131d
--- /dev/null
+++ b/samples/database/src/main/java/com/dynatrace/oneagent/sdk/samples/database/StdErrLoggingCallback.java
@@ -0,0 +1,37 @@
+package com.dynatrace.oneagent.sdk.samples.database;
+
+/*
+ * Copyright 2018 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.dynatrace.oneagent.sdk.api.LoggingCallback;
+
+/**
+ * Implementation of OneAgent Logging Callback. Just printing output messages to
+ * std err.
+ */
+public class StdErrLoggingCallback implements LoggingCallback {
+
+ @Override
+ public void error(String message) {
+ System.err.println("[OneAgent SDK ERROR]: " + message);
+ }
+
+ @Override
+ public void warn(String message) {
+ System.err.println("[OneAgent SDK WARNING]: " + message);
+ }
+
+}
diff --git a/samples/img/in-process-linking-service.png b/samples/img/in-process-linking-service.png
new file mode 100644
index 0000000..a448e53
Binary files /dev/null and b/samples/img/in-process-linking-service.png differ
diff --git a/samples/img/remotecall-service.png b/samples/img/remotecall-service.png
new file mode 100644
index 0000000..f54dd5f
Binary files /dev/null and b/samples/img/remotecall-service.png differ
diff --git a/samples/img/webrequest-service.png b/samples/img/webrequest-service.png
new file mode 100644
index 0000000..7b6d1ab
Binary files /dev/null and b/samples/img/webrequest-service.png differ
diff --git a/samples/in-process-linking/.gitignore b/samples/in-process-linking/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/samples/in-process-linking/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/samples/in-process-linking/pom.xml b/samples/in-process-linking/pom.xml
new file mode 100644
index 0000000..d8f7dcc
--- /dev/null
+++ b/samples/in-process-linking/pom.xml
@@ -0,0 +1,84 @@
+
+ 4.0.0
+
+ com.dynatrace.oneagent.sdk.samples.inprocesslinking
+ in-process-linking-sample
+ 1.2.0
+ jar
+
+
+
+ com.dynatrace.oneagent.sdk.java
+ oneagent-sdk
+ 1.2.0
+ compile
+
+
+
+ https://github.com/Dynatrace/OneAgent-SDK-Java
+ Dynatrace OneAgent SDK Java In-Process-Linking sample
+
+ Dynatrace
+ http://www.dynatrace.com
+
+
+
+ 1.6
+ 1.6
+ UTF-8
+ UTF-8
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+
+ true
+ com.dynatrace.oneagent.sdk.samples.inprocesslinking.InProcessLinkingApp
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+
+ exec
+
+
+
+
+ java
+
+ ${agent.agentpath}
+ -classpath
+
+ com.dynatrace.oneagent.sdk.samples.inprocesslinking.InProcessLinkingApp
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/InProcessLinkingApp.java b/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/InProcessLinkingApp.java
new file mode 100644
index 0000000..8d82c91
--- /dev/null
+++ b/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/InProcessLinkingApp.java
@@ -0,0 +1,121 @@
+package com.dynatrace.oneagent.sdk.samples.inprocesslinking;
+
+/*
+ * Copyright 2018 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.net.URL;
+import java.sql.SQLException;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+import javax.net.ssl.HttpsURLConnection;
+
+import com.dynatrace.oneagent.sdk.OneAgentSDKFactory;
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+
+/**
+ * ServerApp is listing for remote call requests from remote-call client.
+ *
+ * @author Alram.Lechner
+ *
+ */
+public class InProcessLinkingApp {
+
+ private final OneAgentSDK oneAgentSdk;
+
+ private BlockingQueue blockingQueue = new ArrayBlockingQueue(5);
+
+ private InProcessLinkingApp() {
+ oneAgentSdk = OneAgentSDKFactory.createInstance();
+ oneAgentSdk.setLoggingCallback(new StdErrLoggingCallback());
+ switch (oneAgentSdk.getCurrentState()) {
+ case ACTIVE:
+ System.out.println("SDK is active and capturing.");
+ break;
+ case PERMANENTLY_INACTIVE:
+ System.err.println(
+ "SDK is PERMANENT_INACTIVE; Probably no OneAgent injected or OneAgent is incompatible with SDK.");
+ break;
+ case TEMPORARILY_INACTIVE:
+ System.err.println(
+ "SDK is TEMPORARY_INACTIVE; OneAgent has been deactivated - check OneAgent configuration.");
+ break;
+ default:
+ System.err.println("SDK is in unknown state.");
+ break;
+ }
+ }
+
+ public static void main(String args[]) {
+ System.out.println("*************************************************************");
+ System.out.println("** Running in-process-linking sample **");
+ System.out.println("*************************************************************");
+ try {
+ InProcessLinkingApp app = new InProcessLinkingApp();
+ // start worker thread, responsible for downloading files in background. thread waits on provided blocking queue.
+ new UrlDownloaderThread(app.blockingQueue).start();
+ String latestVersion = app.startAsyncOperation();
+ System.err.println("Found latest OneAgent SDK for Java: " + latestVersion);
+ System.out.println("sample application stopped. sleeping a while, so OneAgent is able to send data to server ...");
+ Thread.sleep(15000); // we have to wait - so OneAgent is able to send data to server
+ app.end();
+ } catch (Exception e) {
+ System.err.println("in-process-linking sample failed: " + e.getMessage());
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ /**
+ * TODO: add custom service for this method
+ * check for latest version and start downloading them asynchronously.
+ */
+ private String startAsyncOperation() throws IOException, ClassNotFoundException, InterruptedException, SQLException {
+ System.out.println("Executor started ...");
+
+ // do some sync work - eg. check for latest version:
+ HttpsURLConnection url = (HttpsURLConnection) new URL("https://github.com/Dynatrace/OneAgent-SDK-for-Java/releases/latest").openConnection();
+
+ // we expect redirect to latest release url:
+ url.setInstanceFollowRedirects(false);
+ int responseStatus = url.getResponseCode();
+ if (responseStatus != 302) {
+ System.out.println("no redirect retrieved!");
+ return null;
+ }
+
+ // e. g.: https://github.com/Dynatrace/OneAgent-SDK-for-Java/releases/tag/v1.0.3
+ String location = url.getHeaderField("Location");
+ String latestVersion = location.substring(location.lastIndexOf('/') + 1);
+
+ // tag this request using the found SDK version:
+ oneAgentSdk.addCustomRequestAttribute("oneagentsdk.java.version", latestVersion);
+
+ // download the big release archive asynchronously ...
+ UrlDownloadItem asyncWorkItem = new UrlDownloadItem(
+ "https://github.com/Dynatrace/OneAgent-SDK-for-Java/archive/" + latestVersion + ".zip",
+ oneAgentSdk.createInProcessLink());
+ blockingQueue.put(asyncWorkItem);
+
+ return latestVersion;
+ }
+
+ private void end() {
+ blockingQueue.offer(UrlDownloadItem.END);
+ }
+
+}
\ No newline at end of file
diff --git a/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/StdErrLoggingCallback.java b/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/StdErrLoggingCallback.java
new file mode 100644
index 0000000..6f72b80
--- /dev/null
+++ b/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/StdErrLoggingCallback.java
@@ -0,0 +1,37 @@
+package com.dynatrace.oneagent.sdk.samples.inprocesslinking;
+
+/*
+ * Copyright 2018 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.dynatrace.oneagent.sdk.api.LoggingCallback;
+
+/**
+ * Implementation of OneAgent Logging Callback. Just printing output messages to
+ * std err.
+ */
+public class StdErrLoggingCallback implements LoggingCallback {
+
+ @Override
+ public void error(String message) {
+ System.err.println("[OneAgent SDK ERROR]: " + message);
+ }
+
+ @Override
+ public void warn(String message) {
+ System.err.println("[OneAgent SDK WARNING]: " + message);
+ }
+
+}
diff --git a/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/UrlDownloadItem.java b/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/UrlDownloadItem.java
new file mode 100644
index 0000000..a3cb6d1
--- /dev/null
+++ b/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/UrlDownloadItem.java
@@ -0,0 +1,27 @@
+package com.dynatrace.oneagent.sdk.samples.inprocesslinking;
+
+import com.dynatrace.oneagent.sdk.api.InProcessLink;
+
+public class UrlDownloadItem {
+
+ public static final UrlDownloadItem END = new UrlDownloadItem("END", null);
+
+ // async operation - eg. URL to download
+ private String url;
+
+ // trace to link async execution with dynatrace
+ private InProcessLink link;
+
+ public UrlDownloadItem(String url, InProcessLink link) {
+ this.url = url;
+ this.link = link;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public InProcessLink getLink() {
+ return link;
+ }
+}
diff --git a/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/UrlDownloaderThread.java b/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/UrlDownloaderThread.java
new file mode 100644
index 0000000..c85a0a6
--- /dev/null
+++ b/samples/in-process-linking/src/main/java/com/dynatrace/oneagent/sdk/samples/inprocesslinking/UrlDownloaderThread.java
@@ -0,0 +1,69 @@
+package com.dynatrace.oneagent.sdk.samples.inprocesslinking;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.concurrent.BlockingQueue;
+
+import javax.net.ssl.HttpsURLConnection;
+
+import com.dynatrace.oneagent.sdk.OneAgentSDKFactory;
+import com.dynatrace.oneagent.sdk.api.InProcessLinkTracer;
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+
+public class UrlDownloaderThread extends Thread {
+
+ private BlockingQueue queue;
+ private OneAgentSDK oneAgentSdk;
+
+ UrlDownloaderThread(BlockingQueue queue) {
+ this.queue = queue;
+ oneAgentSdk = OneAgentSDKFactory.createInstance();
+ setDaemon(true);
+ }
+
+ @Override
+ public void run() {
+ try {
+ while (true) {
+ UrlDownloadItem item = queue.take();
+ if (item == UrlDownloadItem.END) {
+ System.out.println("[DBWorker] retrieved end - exiting");
+ return;
+ }
+ System.out.println("[UrlDownloaderThread] retrieved item: " + item.getUrl());
+
+ // trace the execution of retrieved SQL:
+ InProcessLinkTracer inProcessLinkTracer = oneAgentSdk.traceInProcessLink(item.getLink());
+ inProcessLinkTracer.start();
+ HttpsURLConnection connection = (HttpsURLConnection) new URL(item.getUrl()).openConnection();
+ try {
+ System.out.println("[UrlDownloaderThread] HTTP status code: " + connection.getResponseCode());
+ InputStream inputStream = connection.getInputStream();
+ int bytesRetrieved = 0;
+ try {
+ byte buffer[] = new byte[1024*10];
+ while(true) {
+ int read = inputStream.read(buffer);
+ if (read < 0) {
+ break;
+ }
+ bytesRetrieved += read;
+ }
+ System.out.println("[UrlDownloaderThread] retrieved " + bytesRetrieved + " bytes");
+ } finally {
+ inputStream.close();
+ }
+ } catch (Exception e) {
+ inProcessLinkTracer.error(e);
+ System.out.println("[UrlDownloaderThread] *** download operation failed: " + e.getClass().getName() + ": " + e.getMessage());
+ } finally {
+ inProcessLinkTracer.end();
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.exit(-2);
+ }
+ }
+
+}
diff --git a/samples/messaging/pom.xml b/samples/messaging/pom.xml
new file mode 100644
index 0000000..5835fed
--- /dev/null
+++ b/samples/messaging/pom.xml
@@ -0,0 +1,84 @@
+
+ 4.0.0
+
+ com.dynatrace.oneagent.sdk.samples.messaging
+ messaging-sample
+ 1.6.0
+ jar
+
+
+
+ com.dynatrace.oneagent.sdk.java
+ oneagent-sdk
+ 1.6.0
+ compile
+
+
+
+ https://github.com/Dynatrace/OneAgent-SDK-Java
+ Dynatrace OneAgent SDK Java WebRequest sample
+
+ Dynatrace
+ http://www.dynatrace.com
+
+
+
+ 1.6
+ 1.6
+ UTF-8
+ UTF-8
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+
+ true
+ com.dynatrace.oneagent.sdk.samples.messaging.MessagingApp
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+
+ exec
+
+
+
+
+ java
+
+ ${agent.agentpath}
+ -classpath
+
+ com.dynatrace.oneagent.sdk.samples.messaging.MessagingApp
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/FakedQueueManager.java b/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/FakedQueueManager.java
new file mode 100644
index 0000000..ada19f4
--- /dev/null
+++ b/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/FakedQueueManager.java
@@ -0,0 +1,59 @@
+package com.dynatrace.oneagent.sdk.samples.messaging;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+public class FakedQueueManager {
+
+ private BlockingQueue queue = new ArrayBlockingQueue(10);
+ private MessageListener messageListener;
+
+ public FakedQueueManager() {
+ }
+
+ private class QueueManagerThread extends Thread {
+ private QueueManagerThread() {
+ super("QueueManager");
+ setDaemon(true);
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ Message incomingMessage;
+ try {
+ incomingMessage = queue.take();
+ messageListener.onMessage(incomingMessage);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ return;
+ }
+ }
+ }
+ }
+
+ public void registerMessageListener(MessageListener listener) {
+ this.messageListener = listener;
+ new QueueManagerThread().start();
+ }
+
+
+ public void send(String queueName, Message message) {
+ try {
+ queue.put(message);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public Message receive(String queueName) {
+ try {
+ return queue.take();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+
+}
diff --git a/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/Message.java b/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/Message.java
new file mode 100644
index 0000000..9f0404c
--- /dev/null
+++ b/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/Message.java
@@ -0,0 +1,37 @@
+package com.dynatrace.oneagent.sdk.samples.messaging;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Message {
+
+ private Map properties = new HashMap();
+ private String vendorMessageId = null;
+ private String correlationId = null;
+
+ public void addProperty(String propertyName, String propertyValue) {
+ properties.put(propertyName, propertyValue);
+ }
+
+ public String getProperty(String propertyName) {
+ return properties.get(propertyName);
+ }
+
+ public String getVendorMessageId() {
+ return vendorMessageId;
+ }
+
+ public void setVendorMessageId(String vendorMessageId) {
+ this.vendorMessageId = vendorMessageId;
+ }
+
+ public String getCorrelationId() {
+ return correlationId;
+ }
+
+ public void setCorrelationId(String correlationId) {
+ this.correlationId = correlationId;
+ }
+
+
+}
diff --git a/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/MessageListener.java b/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/MessageListener.java
new file mode 100644
index 0000000..a00c12e
--- /dev/null
+++ b/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/MessageListener.java
@@ -0,0 +1,7 @@
+package com.dynatrace.oneagent.sdk.samples.messaging;
+
+public interface MessageListener {
+
+ public void onMessage(Message message);
+
+}
diff --git a/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/MessagingApp.java b/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/MessagingApp.java
new file mode 100644
index 0000000..cebecf7
--- /dev/null
+++ b/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/MessagingApp.java
@@ -0,0 +1,153 @@
+package com.dynatrace.oneagent.sdk.samples.messaging;
+
+import com.dynatrace.oneagent.sdk.OneAgentSDKFactory;
+import com.dynatrace.oneagent.sdk.api.IncomingMessageProcessTracer;
+import com.dynatrace.oneagent.sdk.api.IncomingMessageReceiveTracer;
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+import com.dynatrace.oneagent.sdk.api.OutgoingMessageTracer;
+import com.dynatrace.oneagent.sdk.api.enums.ChannelType;
+import com.dynatrace.oneagent.sdk.api.enums.MessageDestinationType;
+import com.dynatrace.oneagent.sdk.api.infos.MessagingSystemInfo;
+
+/**
+ * Sample application shows how incoming/outgoing messages should be traced.
+ *
+ * @author Alram.Lechner
+ *
+ */
+public class MessagingApp {
+
+ private final OneAgentSDK oneAgentSdk;
+ final FakedQueueManager queueManager;
+
+ static MessagingApp instance;
+
+
+ private MessagingApp() {
+ oneAgentSdk = OneAgentSDKFactory.createInstance();
+ oneAgentSdk.setLoggingCallback(new StdErrLoggingCallback());
+ switch (oneAgentSdk.getCurrentState()) {
+ case ACTIVE:
+ System.out.println("SDK is active and capturing.");
+ break;
+ case PERMANENTLY_INACTIVE:
+ System.err.println(
+ "SDK is PERMANENTLY_INACTIVE; Probably no OneAgent injected or OneAgent is incompatible with SDK.");
+ break;
+ case TEMPORARILY_INACTIVE:
+ System.err.println(
+ "SDK is TEMPORARILY_INACTIVE; OneAgent has been deactivated - check OneAgent configuration.");
+ break;
+ default:
+ System.err.println("SDK is in unknown state.");
+ break;
+ }
+ queueManager = new FakedQueueManager();
+ instance = this;
+ }
+
+ public static void main(String args[]) {
+ System.out.println("*************************************************************");
+ System.out.println("** Running messaging sample **");
+ System.out.println("*************************************************************");
+ try {
+ MessagingApp app = new MessagingApp();
+
+ // sending and blocking receive ...
+ app.sendMessage();
+ app.receiveMessage();
+
+ // or sending and event based receive:
+ app.registerMessageListener();
+ app.sendMessage();
+
+ System.out.println("sample application stopped. sleeping a while, so OneAgent is able to send data to server ...");
+ Thread.sleep(15000 * 3); // we have to wait - so OneAgent is able to send data to server
+ } catch (Exception e) {
+ System.err.println("messaging sample failed: " + e.getMessage());
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ private void registerMessageListener() {
+ queueManager.registerMessageListener(new MessageListener() {
+ @Override
+ public void onMessage(Message message) {
+ MessagingSystemInfo messagingSystemInfo = oneAgentSdk.createMessagingSystemInfo("DynatraceSample", "theQueue", MessageDestinationType.QUEUE, ChannelType.IN_PROCESS, null);
+ IncomingMessageProcessTracer incomingMessageProcessTracer = oneAgentSdk.traceIncomingMessageProcess(messagingSystemInfo);
+ // store incoming tag to tracer:
+ incomingMessageProcessTracer.setDynatraceStringTag(message.getProperty(OneAgentSDK.DYNATRACE_MESSAGE_PROPERTYNAME));
+ incomingMessageProcessTracer.setVendorMessageId(message.getVendorMessageId());
+ incomingMessageProcessTracer.start();
+ try {
+ // do something with the message ...
+ System.out.println("Message received: " + message.toString());
+ } catch (Exception e) {
+ incomingMessageProcessTracer.error(e);
+ } finally {
+ incomingMessageProcessTracer.end();
+ }
+ }
+ });
+
+ }
+
+ private void sendMessage() {
+ MessagingSystemInfo messagingSystemInfo = oneAgentSdk.createMessagingSystemInfo("DynatraceSample", "theQueue", MessageDestinationType.QUEUE, ChannelType.IN_PROCESS, null);
+ OutgoingMessageTracer outgoingMessageTracer = oneAgentSdk.traceOutgoingMessage(messagingSystemInfo);
+
+ outgoingMessageTracer.start();
+ try {
+ Message messageToSend = new Message();
+
+ // add dynatrace tag as property to message ...
+ messageToSend.addProperty(OneAgentSDK.DYNATRACE_MESSAGE_PROPERTYNAME, outgoingMessageTracer.getDynatraceStringTag());
+
+ queueManager.send("theQueue", messageToSend);
+
+ // in case queueManager provided messageId:
+ if (messageToSend.getVendorMessageId() != null) {
+ outgoingMessageTracer.setVendorMessageId(messageToSend.getVendorMessageId());
+ }
+
+ } catch (Exception e) {
+ outgoingMessageTracer.error(e);
+ } finally {
+ outgoingMessageTracer.end();
+ }
+ }
+
+ /** shows how to trace a blocking receive of a message */
+ private void receiveMessage() {
+ MessagingSystemInfo messagingSystemInfo = oneAgentSdk.createMessagingSystemInfo("DynatraceSample", "theQueue", MessageDestinationType.QUEUE, ChannelType.IN_PROCESS, null);
+ IncomingMessageReceiveTracer incomingMessageReceiveTracer = oneAgentSdk.traceIncomingMessageReceive(messagingSystemInfo);
+ incomingMessageReceiveTracer.start();
+ try {
+ Message msg = queueManager.receive("theQeue");
+ if (msg == null) {
+ return; // no message received
+ }
+ IncomingMessageProcessTracer incomingMessageProcessTracer = oneAgentSdk.traceIncomingMessageProcess(messagingSystemInfo);
+ // store incoming tag to tracer:
+ incomingMessageProcessTracer.setDynatraceStringTag(msg.getProperty(OneAgentSDK.DYNATRACE_MESSAGE_PROPERTYNAME));
+ incomingMessageProcessTracer.setVendorMessageId(msg.getVendorMessageId());
+ incomingMessageProcessTracer.start();
+ try {
+ // do something with the message ...
+ System.out.println("Message received: " + msg.toString());
+ } catch (Exception e) {
+ incomingMessageProcessTracer.error(e);
+ } finally {
+ incomingMessageProcessTracer.end();
+ }
+
+
+ } catch (Exception e) {
+ incomingMessageReceiveTracer.error(e);
+ } finally {
+ incomingMessageReceiveTracer.end();
+ }
+ }
+
+}
diff --git a/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/StdErrLoggingCallback.java b/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/StdErrLoggingCallback.java
new file mode 100644
index 0000000..256a8c5
--- /dev/null
+++ b/samples/messaging/src/main/java/com/dynatrace/oneagent/sdk/samples/messaging/StdErrLoggingCallback.java
@@ -0,0 +1,37 @@
+package com.dynatrace.oneagent.sdk.samples.messaging;
+
+/*
+ * Copyright 2018 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.dynatrace.oneagent.sdk.api.LoggingCallback;
+
+/**
+ * Implementation of OneAgent Logging Callback. Just printing output messages to
+ * std err.
+ */
+public class StdErrLoggingCallback implements LoggingCallback {
+
+ @Override
+ public void error(String message) {
+ System.err.println("[OneAgent SDK ERROR]: " + message);
+ }
+
+ @Override
+ public void warn(String message) {
+ System.err.println("[OneAgent SDK WARNING]: " + message);
+ }
+
+}
diff --git a/samples/remotecall/parent/pom.xml b/samples/remotecall/parent/pom.xml
index 078ff03..a32ef25 100644
--- a/samples/remotecall/parent/pom.xml
+++ b/samples/remotecall/parent/pom.xml
@@ -6,15 +6,14 @@
com.dynatrace.oneagent.sdk.samples.remotingparent
- 1.0.3
+ 1.2.0pom
-
com.dynatrace.oneagent.sdk.javaoneagent-sdk
- 1.0.3
+ 1.2.0compile
@@ -34,6 +33,7 @@
,debugOneAgentSdkJava=true-agentpath:"${agent.lib}=name=SdkSample,server=${agent.server}"${agent.options},tenant=${agent.tenant},tenantToken=${agent.tenantToken}
-->
-
+
+
\ No newline at end of file
diff --git a/samples/remotecall/pom.xml b/samples/remotecall/pom.xml
index 200fb80..aed81dc 100644
--- a/samples/remotecall/pom.xml
+++ b/samples/remotecall/pom.xml
@@ -6,7 +6,7 @@
com.dynatrace.oneagent.sdk.samples.remotingremotecall-sample
- 1.0.3
+ 1.2.0pom
diff --git a/samples/remotecall/remotecall-client/pom.xml b/samples/remotecall/remotecall-client/pom.xml
index cfab4d9..5a71fbb 100644
--- a/samples/remotecall/remotecall-client/pom.xml
+++ b/samples/remotecall/remotecall-client/pom.xml
@@ -7,7 +7,7 @@
com.dynatrace.oneagent.sdk.samples.remotingparent
- 1.0.3
+ 1.2.0../parent/pom.xml
@@ -46,7 +46,8 @@
${agent.agentpath}-classpath
- com.dynatrace.oneagent.sdk.samples.remoting.ClientApp
+ com.dynatrace.oneagent.sdk.samples.remoting.ClientApp
+ ${sample.mode}
diff --git a/samples/remotecall/remotecall-client/src/main/java/com/dynatrace/oneagent/sdk/samples/remoting/ClientApp.java b/samples/remotecall/remotecall-client/src/main/java/com/dynatrace/oneagent/sdk/samples/remoting/ClientApp.java
index 53170f0..ccea0c2 100644
--- a/samples/remotecall/remotecall-client/src/main/java/com/dynatrace/oneagent/sdk/samples/remoting/ClientApp.java
+++ b/samples/remotecall/remotecall-client/src/main/java/com/dynatrace/oneagent/sdk/samples/remoting/ClientApp.java
@@ -19,6 +19,8 @@
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import com.dynatrace.oneagent.sdk.OneAgentSDKFactory;
import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
@@ -28,6 +30,7 @@
public class ClientApp {
private final OneAgentSDK oneAgentSdk;
+ private final Logger logger = Logger.getLogger("ClientApp");
private ClientApp() {
oneAgentSdk = OneAgentSDKFactory.createInstance();
@@ -53,17 +56,22 @@ public static void main(String args[]) {
System.out.println("** Running remote call client **");
System.out.println("*************************************************************");
int port = 33744;
+ boolean endlessmode = false;
for (String arg : args) {
if (arg.startsWith("port=")) {
port = Integer.parseInt(arg.substring("port=".length()));
+ } else if (arg.startsWith("endlessmode")) {
+ endlessmode = true;
} else {
System.err.println("unknown argument: " + arg);
}
}
try {
- new ClientApp().run(port);
- System.out.println("remote call client finished. sleeping a while, so OneAgent is able to send data to server ...");
- Thread.sleep(15000); // we have to wait - so OneAgent is able to send data to server.
+ ClientApp clientApp = new ClientApp();
+ do {
+ clientApp.run(port);
+ Thread.sleep(10000);
+ } while (endlessmode);
} catch (Exception e) {
System.err.println("remote call client failed: " + e.getMessage());
e.printStackTrace();
@@ -85,7 +93,7 @@ private void run(int port) throws IOException, ClassNotFoundException {
}
private void traceCallToServer(ObjectOutputStream out, int port) throws IOException {
- OutgoingRemoteCallTracer outgoingRemoteCall = oneAgentSdk.traceOutgoingRemoteCall("myMethod", "myService", "endpoint", ChannelType.IN_PROCESS, "localhost:" + port);
+ OutgoingRemoteCallTracer outgoingRemoteCall = oneAgentSdk.traceOutgoingRemoteCall("myMethod", "myService", "endpoint", ChannelType.TCP_IP, "localhost:" + port);
outgoingRemoteCall.start();
try {
String outgoingTag = outgoingRemoteCall.getDynatraceStringTag();
@@ -93,6 +101,7 @@ private void traceCallToServer(ObjectOutputStream out, int port) throws IOExcept
invokeCallToServer(out, outgoingTag);
} catch (Exception e) {
outgoingRemoteCall.error(e);
+ logger.log(Level.WARNING, "remotecall failed", e);
} finally {
outgoingRemoteCall.end();
}
diff --git a/samples/remotecall/remotecall-server/pom.xml b/samples/remotecall/remotecall-server/pom.xml
index 8db9f88..5b16126 100644
--- a/samples/remotecall/remotecall-server/pom.xml
+++ b/samples/remotecall/remotecall-server/pom.xml
@@ -7,7 +7,7 @@
com.dynatrace.oneagent.sdk.samples.remotingparent
- 1.0.3
+ 1.2.0../parent/pom.xml
@@ -46,7 +46,8 @@
${agent.agentpath}-classpath
- com.dynatrace.oneagent.sdk.samples.remoting.ServerApp
+ com.dynatrace.oneagent.sdk.samples.remoting.ServerApp
+ ${sample.mode}
diff --git a/samples/remotecall/remotecall-server/src/main/java/com/dynatrace/oneagent/sdk/samples/remoting/ServerApp.java b/samples/remotecall/remotecall-server/src/main/java/com/dynatrace/oneagent/sdk/samples/remoting/ServerApp.java
index 45dca3d..57295fd 100644
--- a/samples/remotecall/remotecall-server/src/main/java/com/dynatrace/oneagent/sdk/samples/remoting/ServerApp.java
+++ b/samples/remotecall/remotecall-server/src/main/java/com/dynatrace/oneagent/sdk/samples/remoting/ServerApp.java
@@ -20,6 +20,8 @@
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import com.dynatrace.oneagent.sdk.OneAgentSDKFactory;
import com.dynatrace.oneagent.sdk.api.IncomingRemoteCallTracer;
@@ -32,8 +34,9 @@
*
*/
public class ServerApp {
-
+
private final OneAgentSDK oneAgentSdk;
+ private final Logger logger = Logger.getLogger("ServerApp");
private ServerApp() {
oneAgentSdk = OneAgentSDKFactory.createInstance();
@@ -47,29 +50,34 @@ private ServerApp() {
"SDK is PERMANENT_INACTIVE; Probably no OneAgent injected or OneAgent is incompatible with SDK.");
break;
case TEMPORARILY_INACTIVE:
- System.err.println("SDK is TEMPORARY_INACTIVE; OneAgent has been deactivated - check OneAgent configuration.");
+ System.err.println(
+ "SDK is TEMPORARY_INACTIVE; OneAgent has been deactivated - check OneAgent configuration.");
break;
default:
System.err.println("SDK is in unknown state.");
break;
}
}
-
+
public static void main(String args[]) {
System.out.println("*************************************************************");
System.out.println("** Running remote call server **");
System.out.println("*************************************************************");
int port = 33744; // default port
+ boolean endlessmode = false;
for (String arg : args) {
if (arg.startsWith("port=")) {
port = Integer.parseInt(arg.substring("port=".length()));
+ } else if (arg.startsWith("endlessmode")) {
+ endlessmode = true;
} else {
System.err.println("unknown argument: " + arg);
}
}
try {
- new ServerApp().run(port);
- System.out.println("remote call server stopped. sleeping a while, so OneAgent is able to send data to server ...");
+ new ServerApp().run(port, endlessmode);
+ System.out.println(
+ "remote call server stopped. sleeping a while, so OneAgent is able to send data to server ...");
Thread.sleep(15000); // we have to wait - so OneAgent is able to send data to server.
} catch (Exception e) {
System.err.println("remote call server failed: " + e.getMessage());
@@ -78,31 +86,34 @@ public static void main(String args[]) {
}
}
- private void run(int port) throws IOException, ClassNotFoundException {
+ private void run(int port, boolean endlessmode) throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(port);
try {
- System.out.println("Waiting for clients on port " + serverSocket.getInetAddress().getHostName() + ":"
- + serverSocket.getLocalPort());
- Socket client = serverSocket.accept();
- try {
- System.out.println(
- "Client " + client.getInetAddress().getHostName() + ":" + client.getPort() + " connected");
- ObjectInputStream in = new ObjectInputStream(client.getInputStream());
-
- Object receivedTag = in.readObject();
- String receivedMessage = (String) in.readObject();
- System.out.println("received tag: " + receivedTag.toString());
- traceCallFromClient(receivedTag, receivedMessage);
- } finally {
- client.close();
- }
+ do {
+ System.out.println("Waiting for clients on port " + serverSocket.getInetAddress().getHostName() + ":"
+ + serverSocket.getLocalPort());
+ Socket client = serverSocket.accept();
+ try {
+ System.out.println(
+ "Client " + client.getInetAddress().getHostName() + ":" + client.getPort() + " connected");
+ ObjectInputStream in = new ObjectInputStream(client.getInputStream());
+
+ Object receivedTag = in.readObject();
+ String receivedMessage = (String) in.readObject();
+ System.out.println("received tag: " + receivedTag.toString());
+ traceCallFromClient(receivedTag, receivedMessage);
+ } finally {
+ client.close();
+ }
+ } while (endlessmode);
} finally {
serverSocket.close();
}
}
-
+
private void traceCallFromClient(Object receivedTag, String receivedMessage) {
- IncomingRemoteCallTracer incomingRemoteCall = oneAgentSdk.traceIncomingRemoteCall("myMethod", "myService", "endpoint");
+ IncomingRemoteCallTracer incomingRemoteCall = oneAgentSdk.traceIncomingRemoteCall("myMethod", "myService",
+ "endpoint");
if (receivedTag instanceof String) {
incomingRemoteCall.setDynatraceStringTag((String) receivedTag);
} else if (receivedTag instanceof byte[]) {
@@ -110,21 +121,22 @@ private void traceCallFromClient(Object receivedTag, String receivedMessage) {
} else {
System.err.println("invalid tag received: " + receivedTag.getClass().toString());
}
-
+
incomingRemoteCall.start();
try {
handleCallFromClient(receivedMessage);
} catch (Exception e) {
incomingRemoteCall.error(e);
+ logger.log(Level.WARNING, "handling of remotecall failed", e);
} finally {
incomingRemoteCall.end();
}
-
+
}
private void handleCallFromClient(String receivedMessage) {
// do whatever the server should do ...
System.out.println("Received message from client: " + receivedMessage);
}
-
+
}
\ No newline at end of file
diff --git a/samples/webrequest/.gitignore b/samples/webrequest/.gitignore
new file mode 100644
index 0000000..b83d222
--- /dev/null
+++ b/samples/webrequest/.gitignore
@@ -0,0 +1 @@
+/target/
diff --git a/samples/webrequest/pom.xml b/samples/webrequest/pom.xml
new file mode 100644
index 0000000..64bf7c1
--- /dev/null
+++ b/samples/webrequest/pom.xml
@@ -0,0 +1,84 @@
+
+ 4.0.0
+
+ com.dynatrace.oneagent.sdk.samples.webrequest
+ webrequest-sample
+ 1.4.0
+ jar
+
+
+
+ com.dynatrace.oneagent.sdk.java
+ oneagent-sdk
+ 1.4.0
+ compile
+
+
+
+ https://github.com/Dynatrace/OneAgent-SDK-Java
+ Dynatrace OneAgent SDK Java WebRequest sample
+
+ Dynatrace
+ http://www.dynatrace.com
+
+
+
+ 1.6
+ 1.6
+ UTF-8
+ UTF-8
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.4
+
+
+
+ true
+ com.dynatrace.oneagent.sdk.samples.webrequest.WebRequestApp
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+
+
+ exec
+
+
+
+
+ java
+
+ ${agent.agentpath}
+ -classpath
+
+ com.dynatrace.oneagent.sdk.samples.webrequest.WebRequestApp
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/FakedHttpClient.java b/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/FakedHttpClient.java
new file mode 100644
index 0000000..f760fbc
--- /dev/null
+++ b/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/FakedHttpClient.java
@@ -0,0 +1,93 @@
+package com.dynatrace.oneagent.sdk.samples.webrequest;
+
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.dynatrace.oneagent.sdk.samples.webrequest.FakedWebserver.HttpRequest;
+import com.dynatrace.oneagent.sdk.samples.webrequest.FakedWebserver.HttpResponse;
+
+public class FakedHttpClient implements HttpResponse {
+
+ // REQUEST
+ private URL url;
+ private String method;
+ private Map> requestHeaders = new HashMap>();
+
+ // RESPONSE
+ private int statusCode;
+ private Map> responseHeaders = new HashMap>();
+
+ public FakedHttpClient(String url, String method) throws MalformedURLException {
+ this.method = method;
+ this.url = new URL(url);
+ }
+
+ public void addRequestHeader(String requestHeader, String value) {
+ List values = requestHeaders.get(requestHeader);
+ if (values == null) {
+ values = new ArrayList();
+ requestHeaders.put(requestHeader, values);
+ }
+ values.add(value);
+ }
+
+ public void addResponseHeader(String headerField, String value) {
+ List values = responseHeaders.get(headerField);
+ if (values == null) {
+ values = new ArrayList();
+ responseHeaders.put(headerField, values);
+ }
+ values.add(value);
+ }
+
+ public void executeRequest() {
+ // a normal HTTP client should open plain tcp socket and send the request now ...
+ // ... but we are putting them into non-blocking queue:
+
+ // build the request object, as a standard web container would provide it ...
+ HttpRequest httpRequest;
+ String clientIp;
+ try {
+ clientIp = InetAddress.getLocalHost().getHostAddress();
+ } catch (UnknownHostException e) {
+ clientIp = "192.168.4.5"; // fake IP
+ }
+ httpRequest = new HttpRequest(url.getPath() + "?" + url.getQuery(), method, clientIp, requestHeaders);
+
+ // ... and queue it for processing:
+ WebRequestApp.instance.webServer.enqeueHttpRequestForProcessing(httpRequest, this);
+ }
+
+ public Map> getRequestHeaders() {
+ return requestHeaders;
+ }
+
+ public Map> getResponseHeaders() {
+ return responseHeaders;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setResponseHeaders(Map> responseHeaders) {
+ this.responseHeaders = responseHeaders;
+ }
+
+ @Override
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ @Override
+ public void setContent(byte[] content) {
+ // ignore the content we got from server
+ }
+
+}
diff --git a/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/FakedWebserver.java b/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/FakedWebserver.java
new file mode 100644
index 0000000..8f010eb
--- /dev/null
+++ b/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/FakedWebserver.java
@@ -0,0 +1,144 @@
+package com.dynatrace.oneagent.sdk.samples.webrequest;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+import com.dynatrace.oneagent.sdk.api.IncomingWebRequestTracer;
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+import com.dynatrace.oneagent.sdk.api.infos.WebApplicationInfo;
+
+public class FakedWebserver {
+
+ private final OneAgentSDK oneAgentSDK;
+ private final WebApplicationInfo webAppInfo;
+
+ private final BlockingQueue requestQueue = new ArrayBlockingQueue(10);
+
+ public FakedWebserver(OneAgentSDK oneAgentSDK) {
+ this.oneAgentSDK = oneAgentSDK;
+ webAppInfo = oneAgentSDK.createWebApplicationInfo("servername", "BillingService", "/billing");
+ new RequestProcessor().start();
+ }
+
+ private class RequestProcessor extends Thread {
+ private RequestProcessor() {
+ super("Webserver-Worker");
+ setDaemon(true);
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ Pair incomingRequest;
+ try {
+ incomingRequest = requestQueue.take();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ return;
+ }
+ serve(incomingRequest.httpRequest, incomingRequest.httpResponse);
+ }
+ }
+ }
+
+ private class Pair {
+ public HttpRequest httpRequest;
+ public HttpResponse httpResponse;
+
+ public Pair(HttpRequest httpRequest, HttpResponse httpResponse) {
+ this.httpRequest = httpRequest;
+ this.httpResponse = httpResponse;
+ }
+ }
+
+ public void enqeueHttpRequestForProcessing(HttpRequest httpRequest, HttpResponse httpResponse) {
+ try {
+ requestQueue.put(new Pair(httpRequest,httpResponse));
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static interface HttpResponse {
+
+ public void setStatusCode(int statusCode);
+
+ public void addResponseHeader(String headerField, String value);
+
+ public void setContent(byte[] content);
+ }
+
+ public static class HttpRequest {
+ private final String remoteIpAddress;
+ private final String uri;
+ private final String method;
+ private final Map> requestHeaders;
+
+ public HttpRequest(String uri, String method, String remoteIpAddress, Map> requestHeaders) {
+ this.uri = uri;
+ this.method = method;
+ this.remoteIpAddress = remoteIpAddress;
+ this.requestHeaders = requestHeaders;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public Map> getHeaders() {
+ return requestHeaders;
+ }
+
+ public Map> getParameters() {
+ return new HashMap>();
+ }
+
+ public String getRemoteIpAddress() {
+ return remoteIpAddress;
+ }
+ }
+
+ /** faked http request handling. shows usage of OneAgent SDK's incoming webrequest API */
+ private void serve(HttpRequest request, HttpResponse response) {
+ String url = request.getUri();
+ System.out.println("[Server] serve " + url);
+ IncomingWebRequestTracer incomingWebrequestTracer = oneAgentSDK.traceIncomingWebRequest(webAppInfo, url, request.getMethod());
+
+ // add request header, parameter and remote address before start:
+ for (Entry> headerField : request.getHeaders().entrySet()) {
+ for (String value : headerField.getValue()) {
+ incomingWebrequestTracer.addRequestHeader(headerField.getKey(), value);
+ }
+ }
+ for (Entry> parameter : request.getParameters().entrySet()) {
+ for (String value : parameter.getValue()) {
+ incomingWebrequestTracer.addParameter(parameter.getKey(), value);
+ }
+ }
+ incomingWebrequestTracer.setRemoteAddress(request.getRemoteIpAddress());
+
+ incomingWebrequestTracer.start();
+ try {
+ response.setContent("Hello world!".getBytes());
+ response.setStatusCode(200);
+ incomingWebrequestTracer.setStatusCode(200);
+ } catch (Exception e) {
+ // we assume, container is sending http 500 in case of exception is thrown while serving an request:
+ incomingWebrequestTracer.error(e);
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ } finally {
+ incomingWebrequestTracer.end();
+ }
+ }
+
+
+}
diff --git a/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/StdErrLoggingCallback.java b/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/StdErrLoggingCallback.java
new file mode 100644
index 0000000..032047b
--- /dev/null
+++ b/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/StdErrLoggingCallback.java
@@ -0,0 +1,37 @@
+package com.dynatrace.oneagent.sdk.samples.webrequest;
+
+/*
+ * Copyright 2018 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.dynatrace.oneagent.sdk.api.LoggingCallback;
+
+/**
+ * Implementation of OneAgent Logging Callback. Just printing output messages to
+ * std err.
+ */
+public class StdErrLoggingCallback implements LoggingCallback {
+
+ @Override
+ public void error(String message) {
+ System.err.println("[OneAgent SDK ERROR]: " + message);
+ }
+
+ @Override
+ public void warn(String message) {
+ System.err.println("[OneAgent SDK WARNING]: " + message);
+ }
+
+}
diff --git a/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/WebRequestApp.java b/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/WebRequestApp.java
new file mode 100644
index 0000000..aac1ae9
--- /dev/null
+++ b/samples/webrequest/src/main/java/com/dynatrace/oneagent/sdk/samples/webrequest/WebRequestApp.java
@@ -0,0 +1,92 @@
+package com.dynatrace.oneagent.sdk.samples.webrequest;
+
+import java.util.List;
+import java.util.Map.Entry;
+
+import com.dynatrace.oneagent.sdk.OneAgentSDKFactory;
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+import com.dynatrace.oneagent.sdk.api.OutgoingWebRequestTracer;
+
+/**
+ * Sample application shows how incoming webrequests should be traced.
+ *
+ * @author Alram.Lechner
+ *
+ */
+public class WebRequestApp {
+
+ private final OneAgentSDK oneAgentSdk;
+ final FakedWebserver webServer;
+
+ static WebRequestApp instance;
+
+
+ private WebRequestApp() {
+ oneAgentSdk = OneAgentSDKFactory.createInstance();
+ oneAgentSdk.setLoggingCallback(new StdErrLoggingCallback());
+ switch (oneAgentSdk.getCurrentState()) {
+ case ACTIVE:
+ System.out.println("SDK is active and capturing.");
+ break;
+ case PERMANENTLY_INACTIVE:
+ System.err.println(
+ "SDK is PERMANENT_INACTIVE; Probably no OneAgent injected or OneAgent is incompatible with SDK.");
+ break;
+ case TEMPORARILY_INACTIVE:
+ System.err.println(
+ "SDK is TEMPORARY_INACTIVE; OneAgent has been deactivated - check OneAgent configuration.");
+ break;
+ default:
+ System.err.println("SDK is in unknown state.");
+ break;
+ }
+ webServer = new FakedWebserver(oneAgentSdk);
+ instance = this;
+ }
+
+ public static void main(String args[]) {
+ System.out.println("*************************************************************");
+ System.out.println("** Running webrequest sample **");
+ System.out.println("*************************************************************");
+ try {
+ WebRequestApp app = new WebRequestApp();
+ app.runFakedWebrequest();
+ // app.runIncomingWebrequest();
+ System.out.println("sample application stopped. sleeping a while, so OneAgent is able to send data to server ...");
+ Thread.sleep(15000 * 3); // we have to wait - so OneAgent is able to send data to server
+ } catch (Exception e) {
+ System.err.println("webrequest sample failed: " + e.getMessage());
+ e.printStackTrace();
+ System.exit(-1);
+ }
+ }
+
+ private void runFakedWebrequest() {
+ String url = "http://localhost:80/billing/my/path?param1=value1¶m2=value2";
+ System.out.println("[Client] request " + url);
+ OutgoingWebRequestTracer outgoingWebRequestTracer = oneAgentSdk.traceOutgoingWebRequest(url, "GET");
+ outgoingWebRequestTracer.start();
+ try {
+ FakedHttpClient httpClient = new FakedHttpClient(url, "GET");
+
+ // add link to headers ...
+ httpClient.addRequestHeader(OneAgentSDK.DYNATRACE_HTTP_HEADERNAME, outgoingWebRequestTracer.getDynatraceStringTag());
+
+ httpClient.executeRequest();
+
+ // add response headers to tracer:
+ for (Entry> entry : httpClient.getResponseHeaders().entrySet()) {
+ for (String value : entry.getValue()) {
+ outgoingWebRequestTracer.addResponseHeader(entry.getKey(), value);
+ }
+ }
+
+ outgoingWebRequestTracer.setStatusCode(httpClient.getStatusCode());
+ } catch (Exception e) {
+ outgoingWebRequestTracer.error(e);
+ } finally {
+ outgoingWebRequestTracer.end();
+ }
+ }
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/OneAgentSDKFactory.java b/src/main/java/com/dynatrace/oneagent/sdk/OneAgentSDKFactory.java
new file mode 100644
index 0000000..df67b69
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/OneAgentSDKFactory.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk;
+
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+import com.dynatrace.oneagent.sdk.impl.OneAgentSDKFactoryImpl;
+
+/**
+ * Entry point for customer application.
+ */
+public class OneAgentSDKFactory {
+
+ /**
+ * Provides a {@link OneAgentSDK} instance, that has to be used to create
+ * transactions. It is safe to use returned {@link OneAgentSDK} instance in
+ * multiple threads. Every application should only create one single SDK
+ * instance during its lifetime.
+ *
+ * @return never null. if no OneAgent present, NOOP implementation gets
+ * returned.
+ */
+ public static OneAgentSDK createInstance() {
+ return OneAgentSDKFactoryImpl.createInstance();
+ }
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/CustomServiceTracer.java b/src/main/java/com/dynatrace/oneagent/sdk/api/CustomServiceTracer.java
new file mode 100644
index 0000000..f015bd5
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/CustomServiceTracer.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Interface for tracing custom services.
+ * https://github.com/Dynatrace/OneAgent-SDK#customservice
+ *
+ * @since 1.8.0
+ */
+public interface CustomServiceTracer extends Tracer {
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/DatabaseRequestTracer.java b/src/main/java/com/dynatrace/oneagent/sdk/api/DatabaseRequestTracer.java
new file mode 100644
index 0000000..c3f0f44
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/DatabaseRequestTracer.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Interface for outgoing database tracer.
+ * https://github.com/Dynatrace/OneAgent-SDK#database
+ *
+ * @since 1.7.0
+ */
+public interface DatabaseRequestTracer extends Tracer {
+
+ /**
+ * Adds optional information about retrieved rows of the traced database request.
+ *
+ * @param returnedRowCount number of rows returned by this traced database request. Only positive values are allowed.
+ * @since 1.7.0
+ */
+ public void setReturnedRowCount(int returnedRowCount);
+
+ /**
+ * Adds optional information about round-trip count to database server.
+ *
+ * @param roundTripCount count of round-trips that took place. Only positive values are allowed.
+ * @since 1.7.0
+ */
+ public void setRoundTripCount(int roundTripCount);
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/InProcessLink.java b/src/main/java/com/dynatrace/oneagent/sdk/api/InProcessLink.java
new file mode 100644
index 0000000..efd0d0d
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/InProcessLink.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Represents link used for in-process-tagging. See
+ * {@link OneAgentSDK#createInProcessLink()} and
+ * {@link OneAgentSDK#traceInProcessLink(InProcessLink)} for more details.
+ *
+ * @since 1.1
+ */
+public interface InProcessLink {
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/InProcessLinkTracer.java b/src/main/java/com/dynatrace/oneagent/sdk/api/InProcessLinkTracer.java
new file mode 100644
index 0000000..64c8004
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/InProcessLinkTracer.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Tracer used to trace in-process-linking. See
+ * {@link OneAgentSDK#createInProcessLink()} and
+ * {@link OneAgentSDK#traceInProcessLink(InProcessLink)} for more details.
+ *
+ * @since 1.1
+ */
+public interface InProcessLinkTracer extends Tracer {
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingMessageProcessTracer.java b/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingMessageProcessTracer.java
new file mode 100644
index 0000000..56325e7
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingMessageProcessTracer.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Interface for processing message tracer.
+ * https://github.com/Dynatrace/OneAgent-SDK#messaging
+ *
+ * @since 1.5
+ */
+public interface IncomingMessageProcessTracer extends IncomingTaggable, Tracer {
+
+ /**
+ * Adds optional information about a traced message: message id provided by messaging system.
+ *
+ * @param vendorMessageId the messageId
+ */
+ public void setVendorMessageId(String vendorMessageId);
+
+ /**
+ * Adds optional information about a traced message: correlation id used by messaging system.
+ *
+ * @param correlationId correlationId
+ */
+ public void setCorrelationId(String correlationId);
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingMessageReceiveTracer.java b/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingMessageReceiveTracer.java
new file mode 100644
index 0000000..e49c885
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingMessageReceiveTracer.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Interface for receiving message tracer.
+ * https://github.com/Dynatrace/OneAgent-SDK#messaging
+ *
+ * @since 1.5
+ */
+public interface IncomingMessageReceiveTracer extends Tracer {
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingRemoteCallTracer.java b/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingRemoteCallTracer.java
new file mode 100644
index 0000000..9c37d54
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingRemoteCallTracer.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Represents the server side of a remote call. This Interface extends
+ * {@link Tracer} - it is important to respect the mentioned requirements when
+ * working with {@link IncomingRemoteCallTracer}.
+ *
+ */
+
+public interface IncomingRemoteCallTracer extends Tracer, IncomingTaggable {
+
+ /**
+ * Sets the name of the used remoting protocol.
+ *
+ * @param protocolName
+ * protocol name
+ * @since 1.0
+ */
+ void setProtocolName(String protocolName);
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingTaggable.java b/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingTaggable.java
new file mode 100644
index 0000000..80dd18e
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingTaggable.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Common interface for server-tagging-related methods. Not to be directly used
+ * by SDK user.
+ */
+public interface IncomingTaggable {
+
+ /**
+ * Consumes a tag to continue a pure path. Must be set before a node is being
+ * started.
+ * See {@link OutgoingTaggable} to determine how to create a tag.
+ *
+ * @param tag
+ * the tag in String representation - must not be null.
+ * @since 1.0
+ */
+ void setDynatraceStringTag(String tag);
+
+ /**
+ * Same as {@link #setDynatraceStringTag(String)} but consumes binary
+ * representation of tag.
+ *
+ * @param tag
+ * the tag in binary representation - must not be null.
+ * @since 1.0
+ */
+ void setDynatraceByteTag(byte[] tag);
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingWebRequestTracer.java b/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingWebRequestTracer.java
new file mode 100644
index 0000000..f2d561a
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/IncomingWebRequestTracer.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Interface for incoming webrequest tracer. https://github.com/Dynatrace/OneAgent-SDK#webrequests
+ *
+ * @since 1.3
+ */
+public interface IncomingWebRequestTracer extends Tracer, IncomingTaggable {
+
+ /**
+ * Validates and sets the remote IP address of the incoming web request. This
+ * information is very useful to gain information about Load balancers, Proxies
+ * and ultimately the end user that is sending the request.
+ *
+ * @param remoteAddress
+ * remote IP address
+ */
+ void setRemoteAddress(String remoteAddress);
+
+ /**
+ * All HTTP request headers should be provided to this method. Selective
+ * capturing will be done based on sensor configuration.
+ *
+ * @param name
+ * HTTP request header field name
+ * @param value
+ * HTTP request header field value
+ */
+ void addRequestHeader(String name, String value);
+
+ /**
+ * All HTTP parameters should be provided to this method. Selective capturing
+ * will be done based on sensor configuration.
+ *
+ * @param name
+ * HTTP parameter name
+ * @param value
+ * HTTP parameter value
+ */
+ void addParameter(String name, String value);
+
+ /**
+ * All HTTP response headers should be provided to this method. Selective
+ * capturing will be done based on sensor configuration.
+ *
+ * @param name
+ * HTTP response header field name
+ * @param value
+ * HTTP response header field value
+ */
+ void addResponseHeader(String name, String value);
+
+ /**
+ * Sets the HTTP response status code.
+ *
+ * @param statusCode
+ * HTTP status code returned to client
+ */
+ void setStatusCode(int statusCode);
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/LoggingCallback.java b/src/main/java/com/dynatrace/oneagent/sdk/api/LoggingCallback.java
new file mode 100644
index 0000000..f098d66
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/LoggingCallback.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * LoggingCallback gets called only inside a OneAgentSDK API call when an
+ * error/warning has occurred.
+ * Never call any SDK API inside one of these callback methods.
+ */
+public interface LoggingCallback {
+
+ /**
+ * Just a warning. Something is missing, but OneAgent is working normal.
+ *
+ * @param message
+ * message text. never null.
+ * @since 1.0
+ */
+ void warn(String message);
+
+ /**
+ * Something that should be done can't be done. (e. g. PurePath could not be
+ * started)
+ *
+ * @param message
+ * message text. never null.
+ * @since 1.0
+ */
+ void error(String message);
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/OneAgentSDK.java b/src/main/java/com/dynatrace/oneagent/sdk/api/OneAgentSDK.java
new file mode 100644
index 0000000..8843127
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/OneAgentSDK.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+import com.dynatrace.oneagent.sdk.api.enums.ChannelType;
+import com.dynatrace.oneagent.sdk.api.enums.MessageDestinationType;
+import com.dynatrace.oneagent.sdk.api.enums.SDKState;
+import com.dynatrace.oneagent.sdk.api.infos.DatabaseInfo;
+import com.dynatrace.oneagent.sdk.api.infos.MessagingSystemInfo;
+import com.dynatrace.oneagent.sdk.api.infos.TraceContextInfo;
+import com.dynatrace.oneagent.sdk.api.infos.WebApplicationInfo;
+
+/**
+ * Root interface contains provided Agent SDK API calls. Basically the whole API
+ * is designed according to following rules:
+ *
+ *
API calls never throw any exception
+ *
API calls never return null values. e. g. they returning NOOP Objects in
+ * case of any issue or required parameters are null.
+ *
+ * Single API calls might differ from that rules. Those rules are explicitly
+ * documented.
+ */
+public interface OneAgentSDK {
+
+ /**
+ * Using this headername to transport Dynatrace tag inside an outgoing http
+ * request ensures compatibility to Dynatrace built-in sensors.
+ */
+ public static final String DYNATRACE_HTTP_HEADERNAME = "X-dynaTrace";
+
+ /**
+ * Using this propertyname to transport Dynatrace tag along with the message, ensures compatibility to Dynatrace built-in sensors.
+ */
+ public static final String DYNATRACE_MESSAGE_PROPERTYNAME = "dtdTraceTagInfo";
+
+ // ***** outgoing Database *****
+
+ /**
+ * Initializes a DatabaseInfo instance that is required for tracing database requests.
+ *
+ * @param name name of the database
+ * @param vendor database vendor name (e.g. Oracle, MySQL, ...), can be a user defined name
+ * If possible use a constant defined in {@link com.dynatrace.oneagent.sdk.api.enums.DatabaseVendor}
+ * @param channelType communication protocol used to communicate with the database.
+ * @param channelEndpoint this represents the communication endpoint for the database. This information allows Dynatrace to tie the database requests to a specific process or cloud service. It is optional.
+ * * for TCP/IP: host name/IP of the server-side (can include port in the form of "host:port")
+ * * for UNIX domain sockets: name of domain socket file
+ * * for named pipes: name of pipe
+ * @return {@link DatabaseInfo} instance to work with
+ * @since 1.7.0
+ */
+ DatabaseInfo createDatabaseInfo(String name, String vendor, ChannelType channelType, String channelEndpoint);
+
+ /**
+ * Creates a tracer for tracing outgoing SQL database requests.
+ *
+ * @param databaseInfo information about database
+ * @param statement database SQL statement
+ * @return {@link DatabaseRequestTracer} to work with
+ * @since 1.7.0
+ */
+ DatabaseRequestTracer traceSqlDatabaseRequest(DatabaseInfo databaseInfo, String statement);
+
+ // ***** Web Requests (incoming) *****
+
+ /**
+ * Initializes a WebApplicationInfo instance that is required for tracing
+ * incoming web requests. This information determines the identity and name of
+ * the resulting Web Request service in dynatrace. Also see
+ * https://www.dynatrace.com/support/help/server-side-services/introduction/how-does-dynatrace-detect-and-name-services/#web-request-services
+ * for detail description of the meaning of the parameters.
+ *
+ * @param webServerName
+ * logical name of the web server. In case of a cluster every node in
+ * the cluster must report the same name here. Attention: Make sure
+ * not to use the host header for this parameter. Host headers are
+ * often spoofed and contain things like google or baidoo which do
+ * not reflect your setup.
+ * @param applicationID
+ * application ID of the web application
+ * @param contextRoot
+ * context root of the application. All URLs traced with the returned
+ * WebApplicationInfo, should start with provided context root.
+ * @return {@link WebApplicationInfo} instance to work with
+ * @since 1.3
+ */
+ WebApplicationInfo createWebApplicationInfo(String webServerName, String applicationID, String contextRoot);
+
+ /**
+ * Traces an incoming web request.
+ *
+ * @param webApplicationInfo
+ * information about web application
+ * @param url
+ * (parts of a) URL, which will be parsed into: scheme,
+ * hostname/port, path & query Note: the hostname will be resolved by
+ * the Agent at start() call
+ * @param method
+ * HTTP request method
+ * @return {@link IncomingWebRequestTracer} to work with
+ * @since 1.3
+ */
+ IncomingWebRequestTracer traceIncomingWebRequest(WebApplicationInfo webApplicationInfo, String url, String method);
+
+ /**
+ * Traces an outgoing web request.
+ *
+ * @param url
+ * URL, which will be parsed into: scheme, hostname/port, path &
+ * query Note: the hostname will be resolved by the Agent at start()
+ * call
+ * @param method
+ * HTTP request method
+ * @return {@link OutgoingWebRequestTracer} to work with
+ * @since 1.4
+ */
+ OutgoingWebRequestTracer traceOutgoingWebRequest(String url, String method);
+
+ // ***** Remote Calls (outgoing & incoming) *****
+
+ /**
+ * Traces an incoming remote call.
+ *
+ * @param serviceMethod
+ * name of the called remote method. (required)
+ * @param serviceName
+ * name of the remote service. (required)
+ * @param serviceEndpoint
+ * endpoint on the server side. (required)
+ * @return {@link IncomingRemoteCallTracer} instance to work with
+ * @since 1.0
+ */
+ IncomingRemoteCallTracer traceIncomingRemoteCall(String serviceMethod, String serviceName, String serviceEndpoint);
+
+ /**
+ * Traces an outgoing remote call.
+ *
+ * @param serviceMethod
+ * name of the called remote method. (required)
+ * @param serviceName
+ * name of the remote service. (required)
+ * @param serviceEndpoint
+ * endpoint on the server side. (required)
+ * @param channelType
+ * communication protocol used by remote call. See
+ * {@link ChannelType} for available types. (required)
+ * @param channelEndpoint
+ * optional and depending on channelType:
+ *
+ *
for TCP/IP: host name/IP of the server-side (can include port)
+ *
for UNIX domain sockets: path of domain socket file
+ *
for named pipes: name of pipe
+ *
+ * @return {@link OutgoingRemoteCallTracer} instance to work with
+ * @since 1.0
+ */
+ OutgoingRemoteCallTracer traceOutgoingRemoteCall(String serviceMethod, String serviceName, String serviceEndpoint,
+ ChannelType channelType, String channelEndpoint);
+
+ // ***** in-process-linking *****
+ /**
+ * Creates a link for in-process-linking.
+ *
+ * @return {@link InProcessLink} instance to work with. Use it with
+ * {@link #traceInProcessLink(InProcessLink)}
+ * @since 1.1
+ */
+ InProcessLink createInProcessLink();
+
+ /**
+ * Traces the start of in-process-linking.
+ *
+ * @param inProcessLink
+ * a InProcessLink received via {@link #createInProcessLink()}
+ * @return {@link InProcessLinkTracer} to work with.
+ * @since 1.1
+ */
+ InProcessLinkTracer traceInProcessLink(InProcessLink inProcessLink);
+
+ // ***** Custom request attributes *****
+ /**
+ * Adds a custom request attribute to currently traced service call. Might be
+ * called multiple times, to add more than one attribute. Check via
+ * {@link #setLoggingCallback(LoggingCallback)} if error happened. If two
+ * attributes with same key are set, both attribute-values are captured.
+ *
+ * @param key
+ * key of the attribute. required parameter.
+ * @param value
+ * value of the attribute. required parameter.
+ * @since 1.2
+ */
+ void addCustomRequestAttribute(String key, String value);
+
+ /**
+ * Does exactly the same as {@link #addCustomRequestAttribute(String, String)},
+ * but request-attribute type long.
+ *
+ * @since 1.2
+ */
+ void addCustomRequestAttribute(String key, long value);
+
+ /**
+ * Does exactly the same as {@link #addCustomRequestAttribute(String, String)},
+ * but request-attribute type double.
+ *
+ * @since 1.2
+ */
+ void addCustomRequestAttribute(String key, double value);
+
+ // ***** Messaging (outgoing & incoming) *****
+
+ /**
+ * Initializes a MessagingSystemInfo instance that is required for tracing messages.
+ *
+ * @param vendorName one of {@link com.dynatrace.oneagent.sdk.api.enums.MessageSystemVendor} if well known vendor. Custom provided in any other case.
+ * @param destinationName destination name (e.g. queue name, topic name)
+ * @param destinationType destination type - see {@link MessageDestinationType}.
+ * @param channelType communication protocol used
+ * @param channelEndpoint optional and depending on protocol:
+ * * for TCP/IP: host name/IP of the server-side (can include port)
+ * * for UNIX domain sockets: name of domain socket file
+ * * for named pipes: name of pipe
+ * @return {@link MessagingSystemInfo} instance to work with
+ *
+ * @since 1.5
+ */
+ MessagingSystemInfo createMessagingSystemInfo(String vendorName, String destinationName, MessageDestinationType destinationType, ChannelType channelType, String channelEndpoint);
+
+ /**
+ * Creates a tracer for an outgoing asynchronous message (send).
+ *
+ * @param messagingSystem information about the messaging system (see createMessagingSystemInfo methods).
+ * @return {@link OutgoingMessageTracer} to work with
+ *
+ * @since 1.5
+ */
+ OutgoingMessageTracer traceOutgoingMessage(MessagingSystemInfo messagingSystem);
+
+ /**
+ * Creates a tracer for an incoming asynchronous message (blocking receive).
+ *
+ * @param messagingSystem information about the messaging system (see createMessagingSystemInfo methods).
+ * @return {@link IncomingMessageReceiveTracer} to work with
+ *
+ * @since 1.5
+ */
+ IncomingMessageReceiveTracer traceIncomingMessageReceive(MessagingSystemInfo messagingSystem);
+
+ /**
+ * Creates a tracer for processing (consuming) a received message (onMessage).
+ *
+ * @param messagingSystem information about the messaging system (see createMessagingSystemInfo methods).
+ * @return {@link IncomingMessageProcessTracer} to work with
+ *
+ * @since 1.5
+ */
+ IncomingMessageProcessTracer traceIncomingMessageProcess(MessagingSystemInfo messagingSystem);
+
+ // ***** various *****
+
+ /**
+ * Installs a callback that gets informed, if any SDK action has failed. For
+ * details see {@link LoggingCallback} interface. The provided callback must be
+ * thread-safe, when using this {@link OneAgentSDK} instance in multi-threaded
+ * environments.
+ *
+ * @param loggingCallback
+ * may be null, to remove current callback. provided callback
+ * replaces any previously set callback.
+ * @since 1.0
+ */
+ void setLoggingCallback(LoggingCallback loggingCallback);
+
+ /**
+ * Returns the current SDKState. See {@link SDKState} for details.
+ *
+ * @return current state - never null.
+ * @since 1.0
+ */
+ SDKState getCurrentState();
+
+ /**
+ * Creates a tracer for a custom transaction (Dynatrace calls them Custom service). Used whenever a transaction
+ * should be traced, that does not match any of the specialised transaction types (e. g. DB-request, webrequest, ...).
+ *
+ * @param serviceMethod service method being used for service creation.
+ * @param serviceName service name being used for service creation.
+ *
+ * @return {@link CustomServiceTracer} to work with
+ * @since 1.8
+ */
+ CustomServiceTracer traceCustomService(String serviceMethod, String serviceName);
+
+ /**
+ * Returns the current W3C trace context for log enrichment
+ * (not meant for tagging and context-propagation but for log-enrichment).
+ * See {@link TraceContextInfo} for details.
+ *
+ * @return current trace context at the time of the call - never null (but may contain all-zero ID).
+ * @since 1.9
+ */
+ TraceContextInfo getTraceContextInfo();
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingMessageTracer.java b/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingMessageTracer.java
new file mode 100644
index 0000000..f1a32d1
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingMessageTracer.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Interface for outgoing message tracer.
+ * https://github.com/Dynatrace/OneAgent-SDK#messaging
+ *
+ * @since 1.5
+ */
+public interface OutgoingMessageTracer extends Tracer, OutgoingTaggable {
+
+ /**
+ * Adds optional information about a traced message: message id provided by messaging system.
+ *
+ * @param vendorMessageId the messageId
+ */
+ public void setVendorMessageId(String vendorMessageId);
+
+ /**
+ * Adds optional information about a traced message: correlation id used by messaging system.
+ *
+ * @param correlationId correlationId
+ */
+ public void setCorrelationId(String correlationId);
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingRemoteCallTracer.java b/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingRemoteCallTracer.java
new file mode 100644
index 0000000..4c4d7fc
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingRemoteCallTracer.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Represents the client side of a remote call.
+ *
+ * This Interface extends {@link Tracer} - it is important to respect the
+ * mentioned requirements when working with {@link OutgoingRemoteCallTracer}.
+ *
+ */
+public interface OutgoingRemoteCallTracer extends Tracer, OutgoingTaggable {
+
+ /**
+ * Sets the name of the used remoting protocol. Setting the protocol name is
+ * optional.
+ *
+ * @param protocolName
+ * protocol name. null value is ignored.
+ * @since 1.0
+ */
+ void setProtocolName(String protocolName);
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingTaggable.java b/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingTaggable.java
new file mode 100644
index 0000000..1592d89
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingTaggable.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Common interface for client-tagging-related methods. Not to be directly used
+ * by SDK user.
+ */
+public interface OutgoingTaggable {
+
+ /**
+ * Creates a Dynatrace tag and returns the String representation of it. This tag
+ * has to be transported with the remoting protocol to the destination.
+ * See {@link IncomingTaggable} how to continue a path with provided tag on the
+ * server side.
+ *
+ * @return the tag - never null.
+ * @since 1.0
+ */
+ String getDynatraceStringTag();
+
+ /**
+ * Same as {@link #getDynatraceStringTag()}, but returning the tag as binary
+ * representation.
+ *
+ * @return the tag - never null.
+ * @since 1.0
+ */
+ byte[] getDynatraceByteTag();
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingWebRequestTracer.java b/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingWebRequestTracer.java
new file mode 100644
index 0000000..98c4211
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/OutgoingWebRequestTracer.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Represents client side of an outgoing webrequest.
+ *
+ * @since 1.4
+ *
+ */
+public interface OutgoingWebRequestTracer extends Tracer, OutgoingTaggable {
+
+ /**
+ * All HTTP request headers should be provided to this method. Selective
+ * capturing will be done based on sensor configuration.
+ *
+ * @param name
+ * HTTP request header field name
+ * @param value
+ * HTTP request header field value
+ */
+ void addRequestHeader(String name, String value);
+
+ /**
+ * All HTTP response headers returned by the server should be provided to this
+ * method. Selective capturing will be done based on sensor configuration.
+ *
+ * @param name
+ * HTTP response header field name
+ * @param value
+ * HTTP response header field value
+ */
+ void addResponseHeader(String name, String value);
+
+ /**
+ * Sets the HTTP response status code.
+ *
+ * @param statusCode
+ * HTTP status code retrieved from server
+ */
+ void setStatusCode(int statusCode);
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/Tracer.java b/src/main/java/com/dynatrace/oneagent/sdk/api/Tracer.java
new file mode 100644
index 0000000..b8c8570
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/Tracer.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api;
+
+/**
+ * Common interface for timing-related methods. Not to be directly used by SDK
+ * user.
+ */
+public interface Tracer {
+
+ /**
+ * starts timing of a node. Every node that has been started, must be ended with
+ * {@link #end()} method. Consider using the following pattern:
+ *
+ *
+ *
+ * {@link #start()}, {@link #end()}, {@link #error(String)},
+ * {@link #error(Throwable)} are not thread-safe. They must be called from the
+ * same thread where {@link #start()} has been invoked.
+ *
+ * @since 1.0
+ */
+ void start();
+
+ /**
+ * Ends timing of a node. Typically this method is called via finally block.
+ *
+ * {@link #start()}, {@link #end()}, {@link #error(String)},
+ * {@link #error(Throwable)} are not thread-safe. They must be called from the
+ * same thread where {@link #start()} has been invoked.
+ *
+ * @since 1.0
+ */
+ void end();
+
+ /**
+ * Marks the node as 'exited by exception'. An additional error message can be
+ * provided as String.
+ * {@link #start()}, {@link #end()}, {@link #error(String)},
+ * {@link #error(Throwable)} are not thread-safe. They must be called from the
+ * same thread where {@link #start()} has been invoked.
+ *
+ * @param message
+ * error message with details about occurred error (eg. return code).
+ * must not be null.
+ * @since 1.0
+ */
+ void error(String message);
+
+ /**
+ * Marks the node as 'exited by exception'.Additional information can be
+ * provided as Throwable.
+ * {@link #start()}, {@link #end()}, {@link #error(String)},
+ * {@link #error(Throwable)} are not thread-safe. They must be called from the
+ * same thread where {@link #start()} has been invoked.
+ *
+ * @param throwable
+ * exception, that occurred. must not null.
+ * @since 1.0
+ */
+ void error(Throwable throwable);
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/enums/ChannelType.java b/src/main/java/com/dynatrace/oneagent/sdk/api/enums/ChannelType.java
new file mode 100644
index 0000000..2f44299
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/enums/ChannelType.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api.enums;
+
+/**
+ * Defines the type of communication channel being used.
+ *
+ * @author Alram.Lechner
+ *
+ */
+public enum ChannelType {
+
+ OTHER(0), TCP_IP(1), UNIX_DOMAIN_SOCKET(2), NAMED_PIPE(3), IN_PROCESS(4);
+
+ /** constant is being used in API call to OneAgent. don't change it! */
+ private final int sdkConstant;
+
+ private ChannelType(int sdkConstant) {
+ this.sdkConstant = sdkConstant;
+ }
+
+ public int getSDKConstant() {
+ return sdkConstant;
+ }
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/enums/DatabaseVendor.java b/src/main/java/com/dynatrace/oneagent/sdk/api/enums/DatabaseVendor.java
new file mode 100644
index 0000000..c140f90
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/enums/DatabaseVendor.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api.enums;
+
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+
+/**
+ * Enumerates all well-known database vendors. See {@link OneAgentSDK#createDatabaseInfo(String, String, ChannelType, String)}.
+ * Using these constants ensures that services captured by OneAgentSDK are handled the same way as traced via built-in sensors.
+ * @since 1.7.0
+ */
+public enum DatabaseVendor {
+
+ APACHE_HIVE("ApacheHive"),
+ CLOUDSCAPE("Cloudscape"),
+ HSQLDB("HSQLDB"),
+ PROGRESS("Progress"),
+ MAXDB("MaxDB"),
+ HANADB("HanaDB"),
+ INGRES("Ingres"),
+ FIRST_SQL("FirstSQL"),
+ ENTERPRISE_DB("EnterpriseDB"),
+ CACHE("Cache"),
+ ADABAS("Adabas"),
+ FIREBIRD("Firebird"),
+ DB2("DB2"),
+ DERBY_CLIENT("Derby Client"),
+ DERBY_EMBEDDED("Derby Embedded"),
+ FILEMAKER("Filemaker"),
+ INFORMIX("Informix"),
+ INSTANT_DB("InstantDb"),
+ INTERBASE("Interbase"),
+ MYSQL("MySQL"),
+ MARIADB("MariaDB"),
+ NETEZZA("Netezza"),
+ ORACLE("Oracle"),
+ PERVASIVE("Pervasive"),
+ POINTBASE("Pointbase"),
+ POSTGRESQL("PostgreSQL"),
+ SQLSERVER("SQL Server"),
+ SQLITE("sqlite"),
+ SYBASE("Sybase"),
+ TERADATA("Teradata"),
+ VERTICA("Vertica"),
+ CASSANDRA("Cassandra"),
+ H2("H2"),
+ COLDFUSION_IMQ("ColdFusion IMQ"),
+ REDSHIFT("Amazon Redshift"),
+ COUCHBASE("Couchbase");
+
+ private final String vendorName;
+
+ private DatabaseVendor(String vendorName) {
+ this.vendorName = vendorName;
+ }
+
+ public String getVendorName() {
+ return vendorName;
+ }
+
+ @Override
+ public String toString() {
+ return vendorName;
+ }
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/enums/MessageDestinationType.java b/src/main/java/com/dynatrace/oneagent/sdk/api/enums/MessageDestinationType.java
new file mode 100644
index 0000000..ef9ab54
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/enums/MessageDestinationType.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api.enums;
+
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+
+/**
+ * Enumerates all well-known messaging destination types. See
+ * {@link OneAgentSDK#createMessagingSystemInfo(String, String, MessageDestinationType, ChannelType, String)}
+ *
+ * @since 1.5
+ */
+public enum MessageDestinationType {
+
+ QUEUE("Queue"),
+ TOPIC("Topic");
+
+ private final String name;
+
+ private MessageDestinationType(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/enums/MessageSystemVendor.java b/src/main/java/com/dynatrace/oneagent/sdk/api/enums/MessageSystemVendor.java
new file mode 100644
index 0000000..4387e0e
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/enums/MessageSystemVendor.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api.enums;
+
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+
+/**
+ * Enumerates all well-known messaging systems. See {@link OneAgentSDK#createMessagingSystemInfo(String, String, MessageDestinationType, ChannelType, String)}.
+ * Using these constants ensures that services captured by OneAgentSDK are handled the same way as traced via built-in sensors.
+ *
+ * @since 1.5
+ */
+public enum MessageSystemVendor {
+
+ HORNETQ("HornetQ"),
+ ACTIVE_MQ("ActiveMQ"),
+ RABBIT_MQ("RabbitMQ"),
+ ARTEMIS("Artemis"),
+ WEBSPHERE("WebSphere"),
+ MQSERIES_JMS("MQSeries JMS"),
+ MQSERIES("MQSeries"),
+ TIBCO("Tibco");
+
+ private final String vendorName;
+
+ private MessageSystemVendor(String vendorName) {
+ this.vendorName = vendorName;
+ }
+
+ public String getVendorName() {
+ return vendorName;
+ }
+
+ @Override
+ public String toString() {
+ return vendorName;
+ }
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/enums/SDKState.java b/src/main/java/com/dynatrace/oneagent/sdk/api/enums/SDKState.java
new file mode 100644
index 0000000..3c63ee1
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/enums/SDKState.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api.enums;
+
+/**
+ * Defines the possible states of the SDK.
+ */
+public enum SDKState {
+
+ /**
+ * SDK is connected to OneAgent and capturing data.
+ *
+ * @since 1.0
+ */
+ ACTIVE,
+
+ /**
+ * SDK is connected to OneAgent, but capturing is disabled.It is good practice
+ * to skip creating SDK transactions to save resources. The SDK state should be
+ * checked regularly as it may change at every point in time.
+ *
+ * @since 1.0
+ */
+ TEMPORARILY_INACTIVE,
+
+ /**
+ * SDK isn't connected to OneAgent, so it will never capture data. This SDK
+ * state will never change during the lifetime of a JVM. It is good practice to
+ * never call any SDK API to save resources.
+ *
+ * @since 1.0
+ */
+ PERMANENTLY_INACTIVE;
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/infos/DatabaseInfo.java b/src/main/java/com/dynatrace/oneagent/sdk/api/infos/DatabaseInfo.java
new file mode 100644
index 0000000..4aa3a04
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/infos/DatabaseInfo.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api.infos;
+
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+
+/**
+ * Type returned by {@link OneAgentSDK#createDatabaseInfo(String, String, com.dynatrace.oneagent.sdk.api.enums.ChannelType, String)}
+ * @since 1.7.0
+ */
+public interface DatabaseInfo {
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/infos/MessagingSystemInfo.java b/src/main/java/com/dynatrace/oneagent/sdk/api/infos/MessagingSystemInfo.java
new file mode 100644
index 0000000..0399199
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/infos/MessagingSystemInfo.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api.infos;
+
+import com.dynatrace.oneagent.sdk.api.OneAgentSDK;
+
+/**
+ * Type returned by {@link OneAgentSDK#createMessagingSystemInfo(String, String, com.dynatrace.oneagent.sdk.api.enums.MessageDestinationType, com.dynatrace.oneagent.sdk.api.enums.ChannelType, String)}
+ *
+ * @since 1.5
+ */
+public interface MessagingSystemInfo {
+
+}
diff --git a/src/main/java/com/dynatrace/oneagent/sdk/api/infos/TraceContextInfo.java b/src/main/java/com/dynatrace/oneagent/sdk/api/infos/TraceContextInfo.java
new file mode 100644
index 0000000..0e4d408
--- /dev/null
+++ b/src/main/java/com/dynatrace/oneagent/sdk/api/infos/TraceContextInfo.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2023 Dynatrace LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.dynatrace.oneagent.sdk.api.infos;
+
+/**
+ * Provides information about a PurePath node using the TraceContext (Trace-Id, Span-Id) model as defined in
+ * These are a few common reasons for why you may be unable to get a valid trace context: