-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce Cloud Logging Exporter #169
Merged
KarstenSchnitter
merged 6 commits into
SAP:main
from
KarstenSchnitter:otel-cloud-logging
Jan 12, 2024
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
4fed8c3
Add OpenTelemetry Signal Exporters for Cloud Logging
KarstenSchnitter 1be2057
Add Unit Tests and Refactor Prod Code
KarstenSchnitter dac86a0
Improve CF resource attributes
KarstenSchnitter 9ded83d
Refactor Service Binding Detection
KarstenSchnitter e99fb8a
Adjust Documentation for Cloud-Logging
KarstenSchnitter edf8762
Remove Security Test Artifacts
KarstenSchnitter File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,15 @@ | ||
# OpenTelemetry Java Agent Extension for SAP Cloud Logging | ||
|
||
This module provides an extension for the [OpenTelemetry Java Agent](https://opentelemetry.io/docs/instrumentation/java/automatic/). | ||
The extension scans the service bindings of an application for SAP Cloud Logging. | ||
The extension scans the service bindings of an application for [SAP Cloud Logging](https://discovery-center.cloud.sap/serviceCatalog/cloud-logging). | ||
If such a binding is found, the OpenTelemetry Java Agent is configured to ship observability data to that service. | ||
Thus, this extension provides a convenient auto-instrumentation for Java applications running on SAP BTP. | ||
|
||
The extension provides two main features: | ||
The extension provides the following main features: | ||
|
||
* auto-configuration of the OpenTelemetry connection to SAP Cloud Logging | ||
* adding resource attributes to describe the CF application | ||
* additional exporters for logs, metrics and traces for [SAP Cloud Logging](https://discovery-center.cloud.sap/serviceCatalog/cloud-logging) | ||
* auto-configuration of the generic OpenTelemetry connection to [SAP Cloud Logging](https://discovery-center.cloud.sap/serviceCatalog/cloud-logging) | ||
* adding resource attributes describing the CF application | ||
|
||
See the section on [configuration](#configuration) for further details. | ||
|
||
|
@@ -18,7 +19,7 @@ Any Java application can be instrumented with the OpenTelemetry Java Agent and t | |
|
||
```sh | ||
java -javaagent:/path/to/opentelemetry-javaagent-<version>.jar \ | ||
-Dotel.javaagent-extensions=/path/to/cf-java-logging-support-opentelemetry-agent-extension-<versions>.jar \ | ||
-Dotel.javaagent-extensions=/path/to/cf-java-logging-support-opentelemetry-agent-extension-<version>.jar \ | ||
# your Java application command | ||
``` | ||
|
||
|
@@ -37,27 +38,76 @@ java -javaagent:BOOT-INF/lib/opentelemetry-javaagent-<version>.jar \ | |
|
||
See the [example manifest](../sample-spring-boot/manifest-otel-javaagent.yml), how this translates into a deployment description. | ||
|
||
For the instrumentation to send observability data to SAP Cloud Logging, the application needs to be bound to a corresponding service instance. | ||
The service instance can be either managed or [user-provided](#using-user-provided-service-instances). | ||
Once the agent is attached to the JVM with the ectension in place, there are two ways, which can be used to send data to [SAP Cloud Logging](https://discovery-center.cloud.sap/serviceCatalog/cloud-logging): | ||
|
||
1. Use the `cloud-logging` exporters explicitly as provided by the extension. | ||
This can be achieved via system properties or environment variables: | ||
```sh | ||
-Dotel.logs.exporter=cloud-logging \ | ||
-Dotel.metrics.exporter=cloud-logging \ | ||
-Dotel.traces.exporter=cloud-logging | ||
|
||
#or | ||
|
||
export OTEL_LOGS_EXPORTER=cloud-logging | ||
export OTEL_METRICS_EXPORTER=cloud-logging | ||
export OTEL_TRACES_EXPORTER=cloud-logging | ||
java #... | ||
``` | ||
|
||
2. Use the default `otlp` exporter with the provided default configuration from the extension: | ||
|
||
```sh | ||
-Dotel.logs.exporter=otlp \ | ||
-Dotel.metrics.exporter=otlp # default value \ | ||
-Dotel.traces.exporter=otlp # default value | ||
|
||
#or | ||
|
||
Note, that the OpenTelemetry Java Agent currently only sends traces and metrics by default. | ||
To enable logs, the additional property `-Dotel.logs.exporter=otlp` is required. | ||
export OTEL_LOGS_EXPORTER=otlp | ||
export OTEL_METRICS_EXPORTER=otlp # default value | ||
export OTEL_TRACES_EXPORTER=otlp # default value | ||
java #... | ||
``` | ||
|
||
Note, that the OpenTelemetry Java Agent currently sends traces and metrics by default using the `otlp` exporter. | ||
That means, without any configuration the agent with the extension will forward metrics and traces to [SAP Cloud Logging](https://discovery-center.cloud.sap/serviceCatalog/cloud-logging). | ||
See TODO for the difference between `cloud-logging` and `otlp` exporters. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. leftover TODO |
||
The benefit of the `cloud-logging` exporter is, that it can be combined with a different configuration of the `otlp` exporter. | ||
|
||
For the instrumentation to send observability data to [SAP Cloud Logging](https://discovery-center.cloud.sap/serviceCatalog/cloud-logging), the application needs to be bound to a corresponding service instance. | ||
The service instance can be either managed or [user-provided](#using-user-provided-service-instances). | ||
|
||
## Configuration | ||
|
||
The OpenTelemetry Java Agent supports a wide variety of [configuration options](https://opentelemetry.io/docs/instrumentation/java/automatic/agent-config/). | ||
As the extension provides configuration via SPI, all its configuration takes lower precedence than other configuration options for OpenTelemetry. | ||
Users can easily overwrite any setting using environment variables or system properties. | ||
|
||
### Using the Extension | ||
|
||
The extension needs to be started with the OpenTelemetry Java Agent as outlined in the [Quick Start Guide](#quickstart-guide). | ||
You need to enable shipping data either by using the `cloud-logging` exporters or relying on the `otlp` exporters for each signal type. | ||
Multiple different exporters can be configured with comma separation. | ||
Using the custom `cloud-logging` exporter will enable you, to use the default `otlp` exporter for different services. | ||
The extension will configure a default endpoint and credentials for the `otlp` endpoints, so no further configuration is required. | ||
|
||
Note, that the `cloud-logging` exporter is just a facade for the `otlp` exporter to allow configuration of multiple data sinks. | ||
There is no custom network client provided by this extension. | ||
|
||
### Configuring the Extension | ||
|
||
The extension itself can be configured by specifying the following system properties: | ||
|
||
| Property | Default Value | Comment | | ||
|----------|---------------|---------| | ||
| `com.sap.otel.extension.cloud-logging.label` | `cloud-logging` | The label of the managed service binding to bind to. | | ||
| `com.sap.otel.extension.cloud-logging.tag` | `Cloud Logging` | The tag of any service binding (managed or user-provided) to bind to. | | ||
| `otel.javaagent.extension.sap.cf.resource.enabled` or `env(OTEL_JAVAAGENT_EXTENSION_SAP_CF_RESOURCE_ENABLED)` | `true` | Whether to add CF resource attributes to all events. | | ||
| `otel.javaagent.extension.sap.cf.binding.cloud-logging.label` or `com.sap.otel.extension.cloud-logging.label` | `cloud-logging` | The label of the managed service binding to bind to. | | ||
| `otel.javaagent.extension.sap.cf.binding.cloud-logging.tag` or `com.sap.otel.extension.cloud-logging.tag` | `Cloud Logging` | The tag of any service binding (managed or user-provided) to bind to. | | ||
| `otel.javaagent.extension.sap.cf.binding.user-provided.label` | `user-provided` | The label of a user-provided service binding to bind to. Note, this label is defined by the Cloud Foundry instance. | | ||
| `otel.javaagent.extension.sap.cf.resource.enabled` | `true` | Whether to add CF resource attributes to all events. | | ||
|
||
> The `otel.javaagent.extension.sap.*` properties are preferred over the `com.sap.otel.extension.*` properties, which are kept for compatibility. | ||
Each `otel.javaagent.extension.sap.*` property can also be provided as environment variable `OTEL_JAVAAGENT_EXTENSION_SAP_*`. | ||
|
||
The extension will scan the environment variable `VCAP_SERVICES` for CF service bindings. | ||
User-provided bindings will take precedence over managed bindings of the configured label ("cloud-logging" by default). | ||
|
@@ -90,7 +140,7 @@ The [OpenTelemetry Java Instrumentation project](https://github.com/open-telemet | |
|
||
## Using User-Provided Service Instances | ||
|
||
The extension provides support not only for managed service instance of SAP Cloud Logging but also for user-provided service instances. | ||
The extension provides support not only for managed service instance of [SAP Cloud Logging](https://discovery-center.cloud.sap/serviceCatalog/cloud-logging) but also for user-provided service instances. | ||
This helps to fine-tune the configuration, e.g. leave out or reconfigure the syslog drain. | ||
Furthermore, this helps on sharing service instances across CF orgs or landscapes. | ||
|
||
|
@@ -103,7 +153,7 @@ The extension requires four fields in the user-provided service credentials and | |
| `ingest-otlp-cert`| The mTLS client certificate in PEM format matching the client key. Line breaks as `\n`. | | ||
| `server-ca` | The trusted mTLS server certificate in PEM format. Line breaks as `\n`. | | ||
|
||
If you have a SAP Cloud Logging service key, you can generate the required JSON file with jq: | ||
If you have a [SAP Cloud Logging](https://discovery-center.cloud.sap/serviceCatalog/cloud-logging) service key, you can generate the required JSON file with jq: | ||
|
||
```bash | ||
cf service-key cls test \ | ||
|
@@ -119,5 +169,17 @@ Using this file, you can create the required user-provided service: | |
``` | ||
|
||
Note, that you can easily feed arbitrary credentials to the extension. | ||
It does not need to be SAP Cloud Logging. | ||
It does not need to be [SAP Cloud Logging](https://discovery-center.cloud.sap/serviceCatalog/cloud-logging). | ||
You can even change the tag using the configuration parameters of the extension. | ||
|
||
## Implementation Differences between Cloud-Logging and OTLP Exporter | ||
|
||
The `cloud-logging` exporter provided by this extension is a facade for the `OtlpGrpcExporter` provided by the OpenTelemetry Java Agent, just like the `otlp` exporter. | ||
The difference is just during the bootstrapping phase. | ||
The main differences are: | ||
|
||
* The `cloud-logging` exporter will send data to all found bindings to SAP Cloud Logging. | ||
The auto-instrumentation of the `otlp` exporter will just configure the first binding it finds priotizing user-provided services. | ||
* The `otlp` configuration will write the required certificates and keys to temporary files, which are deleted when the JVM is shut down. The `cloud-logging` exporter will keep the secrets in memory. | ||
* Since the `otlp` exporter is the default for traces and metrics, just attaching the extension and binding to Cloud Logging will result in metrics and traces being forwarded. | ||
The `cloud-logging` exporter needs to be configured explictly as does the `otlp` exporter for logs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
.../com/sap/hcf/cf/logging/opentelemetry/agent/ext/binding/CloudLoggingServicesProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.sap.hcf.cf.logging.opentelemetry.agent.ext.binding; | ||
|
||
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties; | ||
import io.pivotal.cfenv.core.CfEnv; | ||
import io.pivotal.cfenv.core.CfService; | ||
|
||
import java.util.List; | ||
import java.util.function.Supplier; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
public class CloudLoggingServicesProvider implements Supplier<Stream<CfService>> { | ||
|
||
private static final String DEFAULT_USER_PROVIDED_LABEL = "user-provided"; | ||
private static final String DEFAULT_CLOUD_LOGGING_LABEL = "cloud-logging"; | ||
private static final String DEFAULT_CLOUD_LOGGING_TAG = "Cloud Logging"; | ||
|
||
private final List<CfService> services; | ||
|
||
public CloudLoggingServicesProvider(ConfigProperties config, CfEnv cfEnv) { | ||
String userProvidedLabel = getUserProvidedLabel(config); | ||
String cloudLoggingLabel = getCloudLoggingLabel(config); | ||
String cloudLoggingTag = getCloudLoggingTag(config); | ||
List<CfService> userProvided = cfEnv.findServicesByLabel(userProvidedLabel); | ||
List<CfService> managed = cfEnv.findServicesByLabel(cloudLoggingLabel); | ||
this.services = Stream.concat(userProvided.stream(), managed.stream()) | ||
.filter(svc -> svc.existsByTagIgnoreCase(cloudLoggingTag)) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private String getUserProvidedLabel(ConfigProperties config) { | ||
return config.getString("otel.javaagent.extension.sap.cf.binding.user-provided.label", DEFAULT_USER_PROVIDED_LABEL); | ||
} | ||
|
||
private String getCloudLoggingLabel(ConfigProperties config) { | ||
String fromOwnProperties = System.getProperty("com.sap.otel.extension.cloud-logging.label", DEFAULT_CLOUD_LOGGING_LABEL); | ||
return config.getString("otel.javaagent.extension.sap.cf.binding.cloud-logging.label", fromOwnProperties); | ||
} | ||
|
||
private String getCloudLoggingTag(ConfigProperties config) { | ||
String fromOwnProperties = System.getProperty("com.sap.otel.extension.cloud-logging.tag", DEFAULT_CLOUD_LOGGING_TAG); | ||
return config.getString("otel.javaagent.extension.sap.cf.binding.cloud-logging.tag", fromOwnProperties); | ||
} | ||
|
||
@Override | ||
public Stream<CfService> get() { | ||
return services.stream(); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.