Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ For historical analysis documents from development sessions, see [`docs/archive/
* [DataDog](docs/framework-datadog_javaagent.md) ([Configuration](docs/framework-datadog_javaagent.md#configuration)
* [Debug](docs/framework-debug.md) ([Configuration](docs/framework-debug.md#configuration))
* [Elastic APM Agent](docs/framework-elastic_apm_agent.md) ([Configuration](docs/framework-elastic_apm_agent.md#configuration))
* [Elastic OTel Java Agent](docs/framework-elastic_otel_java_agent.md) ([Configuration](docs/framework-elastic_otel_java_agent.md#configuration))
* [Dynatrace SaaS/Managed OneAgent](docs/framework-dynatrace_one_agent.md) ([Configuration](docs/framework-dynatrace_one_agent.md#configuration))
* [Google Stackdriver Profiler](docs/framework-google_stackdriver_profiler.md) ([Configuration](docs/framework-google_stackdriver_profiler.md#configuration))
* [Introscope Agent](docs/framework-introscope_agent.md) ([Configuration](docs/framework-introscope_agent.md#configuration))
Expand Down
75 changes: 75 additions & 0 deletions docs/framework-elastic_otel_java_agent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Elastic OTel Java Agent Framework

The Elastic OTel Java Agent Framework causes an application to be automatically configured to work with the [Elastic Distribution of OpenTelemetry Java][].

<table>
<tr>
<td><strong>Detection Criterion</strong></td>
<td>Existence of a bound Elastic OTel service. The service must have a name, label, or tag containing <code>elastic-otel</code> and must provide an OTLP endpoint plus authentication credentials. The framework can also be enabled explicitly with <code>ELASTIC_OTEL_AGENT</code>.</td>
</tr>
<tr>
<td><strong>Tags</strong></td>
<td><tt>elastic-otel-javaagent=&lt;version&gt;</tt></td>
</tr>
</table>

Tags are printed to standard output by the buildpack detect script.

## User-Provided Service

Users can provide their own Elastic OTel service. A user-provided service must have a name or tag with `elastic-otel` in it so that the framework configures the application with the Elastic Otel Java agent.

The credential payload can contain the following entries.

| Name | Description |
| ---- | ----------- |
| `otel.exporter.otlp.endpoint` | The OTLP endpoint for your Elastic deployment or EDOT Collector. Aliases: `otlp_endpoint`, `otlpEndpoint`, `endpoint`. |
| `otel.exporter.otlp.headers` | Explicit OTLP headers, for example `Authorization=ApiKey <key>`. If present, this takes precedence over derived authentication headers. |
| `api_key` | Elastic API key. Converted to `otel.exporter.otlp.headers=Authorization=ApiKey <key>`. |
| `secret_token` | Bearer token. Converted to `otel.exporter.otlp.headers=Authorization=Bearer <token>`. |
| `otel.*` | Any additional OpenTelemetry configuration applied as JVM system properties. |
| `elastic.otel.*` | Any additional Elastic OTel configuration applied as JVM system properties. |

### Creating an Elastic OTel User-Provided Service

Example minimal configuration:

```
cf cups my-elastic-otel-service -p '{"otel.exporter.otlp.endpoint":"https://my-deployment.ingest.us-west1.gcp.cloud.es.io","api_key":"my-api-key"}'
```

Example configuration with explicit OTLP headers and resource attributes:

```
cf cups my-elastic-otel-service -p '{"otel.exporter.otlp.endpoint":"https://my-deployment.ingest.us-west1.gcp.cloud.es.io","otel.exporter.otlp.headers":"Authorization=ApiKey my-api-key","otel.resource.attributes":"deployment.environment.name=production"}'
```

Bind your application to the service using:

`cf bind-service my-app-name my-elastic-otel-service`

or use the `services` block in the application manifest file.

## Configuration

For general information on configuring the buildpack, including how to specify configuration values through environment variables, refer to [Configuration and Extension][].

The framework uses the dependency version configured in `manifest.yml`.

| Name | Description |
| ---- | ----------- |
| `version` | The version of Elastic OTel Java agent to use. The current buildpack manifest uses the `elastic-otel-javaagent` dependency. |

The framework sets `otel.service.name` from `VCAP_APPLICATION.application_name` if it is not configured in service credentials or `OTEL_SERVICE_NAME`. It also sets `deployment.environment.name` from `VCAP_APPLICATION.space_name` when `otel.resource.attributes` is not configured.

> **Warning**
> Do not bind this framework alongside the Elastic APM Agent, OpenTelemetry Javaagent, Splunk OTel Java Agent, or another Java agent framework for the same application. Running multiple Java agents in the same JVM can cause duplicate telemetry or conflicting instrumentation.

## Migration From Elastic APM Agent

The Elastic OTel Java agent uses OTLP configuration. It does not use Elastic APM agent settings such as `server_url` or `secret_token` with the `elastic.apm.*` prefix.

When migrating, create a new service binding named or tagged for Elastic OTel and provide an OTLP endpoint plus `otel.exporter.otlp.headers` or `api_key`.

[Configuration and Extension]: ../README.md#configuration-and-extension
[Elastic Distribution of OpenTelemetry Java]: https://www.elastic.co/docs/reference/opentelemetry/edot-sdks/java
3 changes: 2 additions & 1 deletion docs/framework-ordering.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ Line | Framework Name | Priority | Notes
75 | SpringAutoReconfiguration | 41 | Spring framework
76 | SplunkOtelJavaAgent | 42 | Observability agent
77 | SpringInsight | 43 | Spring monitoring
78 | SkyWalkingAgent | 44 | APM agent
78 | SkyWalkingAgent | 41 | APM agent
78a | ElasticOtelJavaAgent | 44 | Observability agent
79 | YourKitProfiler | 45 | Profiler
80 | JavaSecurity | 47 | Security configuration
81 | JavaOpts | 99 | ⚠️ USER-DEFINED OPTS (ALWAYS LAST)
Expand Down
16 changes: 16 additions & 0 deletions manifest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ packaging_profiles:
exclude:
- datadog-javaagent
- elastic-apm-agent
- elastic-otel-javaagent
- azure-application-insights
- skywalking-agent
- splunk-otel-javaagent
Expand All @@ -44,6 +45,7 @@ packaging_profiles:
exclude:
- datadog-javaagent
- elastic-apm-agent
- elastic-otel-javaagent
- azure-application-insights
- skywalking-agent
- splunk-otel-javaagent
Expand Down Expand Up @@ -94,6 +96,8 @@ default_versions:
version: 1.x
- name: elastic-apm-agent
version: 1.x
- name: elastic-otel-javaagent
version: 1.x
- name: azure-application-insights
version: 3.x
- name: skywalking-agent
Expand Down Expand Up @@ -182,6 +186,9 @@ url_to_dependency_map:
- match: elastic-apm-agent-(\d+\.\d+\.\d+)
name: elastic-apm-agent
version: "$1"
- match: elastic-otel-javaagent[-_](\d+\.\d+\.\d+)
name: elastic-otel-javaagent
version: "$1"
- match: applicationinsights-agent-(\d+\.\d+\.\d+)
name: azure-application-insights
version: "$1"
Expand Down Expand Up @@ -321,6 +328,15 @@ dependencies:
- cflinuxfs5
source: https://repo1.maven.org/maven2/co/elastic/apm/elastic-apm-agent/1.56.0/elastic-apm-agent-1.56.0.jar
source_sha256: ''
- name: elastic-otel-javaagent
version: 1.11.0
uri: https://repo1.maven.org/maven2/co/elastic/otel/elastic-otel-javaagent/1.11.0/elastic-otel-javaagent-1.11.0.jar
sha256: 61c0aae98e165ddfa3096d5d8ed16c159992b8ae284bf6296800839008cdb707
cf_stacks:
- cflinuxfs4
- cflinuxfs5
source: https://repo1.maven.org/maven2/co/elastic/otel/elastic-otel-javaagent/1.11.0/elastic-otel-javaagent-1.11.0.jar
source_sha256: 61c0aae98e165ddfa3096d5d8ed16c159992b8ae284bf6296800839008cdb707
- name: google-stackdriver-profiler
version: 0.4.0
uri: https://storage.googleapis.com/cloud-profiler/java/latest/profiler_java_agent.tar.gz
Expand Down
39 changes: 39 additions & 0 deletions src/integration/frameworks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,45 @@ func testFrameworks(platform switchblade.Platform, fixtures string) func(*testin
})
})

context("with Elastic OTel service binding", func() {
it("detects and installs Elastic OTel Java agent", func() {
deployment, logs, err := platform.Deploy.
WithServices(map[string]switchblade.Service{
"elastic-otel": {
"otel.exporter.otlp.endpoint": "https://elastic-otel.example.com:443",
"api_key": "test-api-key",
},
}).
WithEnv(map[string]string{
"BP_JAVA_VERSION": "17",
}).
Execute(name, filepath.Join(fixtures, "apps", "integration_valid"))
Expect(err).NotTo(HaveOccurred(), logs.String)

Expect(logs.String()).To(ContainSubstring("Elastic OTel"))
Eventually(deployment).Should(matchers.Serve(ContainSubstring("")))
})

it("configures Elastic OTel with explicit OTLP headers", func() {
deployment, logs, err := platform.Deploy.
WithServices(map[string]switchblade.Service{
"my-elastic-otel": {
"otel.exporter.otlp.endpoint": "https://elastic-otel.production.example.com:443",
"otel.exporter.otlp.headers": "Authorization=ApiKey explicit-key",
"otel.service.name": "my-java-app",
},
}).
WithEnv(map[string]string{
"BP_JAVA_VERSION": "17",
}).
Execute(name, filepath.Join(fixtures, "containers", "spring_boot_staged"))
Expect(err).NotTo(HaveOccurred(), logs.String)

Expect(logs.String()).To(ContainSubstring("Elastic OTel"))
Eventually(deployment).Should(matchers.Serve(ContainSubstring("")))
})
})

context("with OpenTelemetry service binding", func() {
it("detects and installs OpenTelemetry Javaagent", func() {
deployment, logs, err := platform.Deploy.
Expand Down
Loading