This article describes how to export observability data from a Java application to Cloud Database ClickHouse Enterprise Edition and analyze it using the one-stop observability service. This helps developers and operations teams monitor application performance in real time and resolve issues faster.
Prerequisites
You have enabled the one-stop observability service for your ApsaraDB for ClickHouse Enterprise Edition instance.
Procedure
In this tutorial, the business service and the Otel Collector are deployed on the same ECS instance. For production environments, we recommend deploying the business service and the Otel Collector on separate instances.
Step 1: Deploy the Otel Collector
-
Configure an ECS instance.
-
Purchase an ECS instance. We recommend assigning a public IP when you purchase the instance for public network access.
-
Add the IP address of the ECS instance to the allowlist of your ApsaraDB for ClickHouse instance.
-
Private IP: If an ECS instance and an ApsaraDB for ClickHouse Enterprise Edition instance are in the same VPC, you can add the private IP address of the ECS instance to the allowlist. In the following operations, use the VPC address as the endpoint for the ApsaraDB for ClickHouse instance.
-
Public IP: If an ECS instance cannot connect to an ApsaraDB for ClickHouse Enterprise Edition instance over a private network, you can add the public IP address of the ECS instance to the allowlist. In the following operations, use the public address for the endpoint of the ApsaraDB for ClickHouse instance.
Connect to the ECS instance and run the following command to test the connection to your ApsaraDB for ClickHouse instance. A response of
Ok.indicates a successful connection.curl http://cc-xxxxxxx-clickhouse.clickhouseserver.pre.rds.aliyuncs.com:8123 -
-
-
Connect to the ECS instance and run the following commands to install otelcol-contrib.
mkdir llm-demo cd llm-demo wget -O otelcol-contrib.rpm https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v0.136.0/otelcol-contrib_0.136.0_linux_amd64.rpm yum install otelcol-contrib.rpm -
Configure the Otel Collector to receive observability data over gRPC and HTTP, and to export it to your ApsaraDB for ClickHouse instance over HTTP.
Copy the following configuration and modify it as needed:
-
In the
receiverssection: We recommend replacing theendpointof the OTLP receiver with the endpoint of your Otel Collector service. -
In the
exporterssection:-
Configure the connection details for your ApsaraDB for ClickHouse instance, including
endpoint,username, andpassword. -
Configure the database and table names for storing observability data in your ApsaraDB for ClickHouse instance, including
database,traces_table_name,logs_table_name, andmetrics_tables.
-
cat > /etc/otelcol-contrib/config.yaml << EOF receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: timeout: 5s send_batch_size: 5000 exporters: clickhouse: endpoint: http://cc-xxxxxx-clickhouse.clickhouseserver.pre.rds.aliyuncs.com:8123?dial_timeout=10s&compress=lz4&async_insert=1 username: test password: password # ttl: 72h traces_table_name: otel_traces logs_table_name: otel_logs metrics_tables: gauge: name: otel_metrics_gauge sum: name: otel_metrics_sum summary: name: otel_metrics_summary histogram: name: otel_metrics_histogram exponential_histogram: name: otel_metrics_exp_histogram create_schema: false timeout: 5s database: clickobserve_service sending_queue: queue_size: 1000 retry_on_failure: enabled: true initial_interval: 5s max_interval: 30s max_elapsed_time: 300s service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [clickhouse] metrics: receivers: [otlp] processors: [batch] exporters: [clickhouse] logs: receivers: [otlp] processors: [batch] exporters: [clickhouse] EOF -
-
Start the Otel Collector.
service otelcol-contrib restart
Step 2: Create a Java application
This section demonstrates how to create the application, using a simple Spring Boot dice-rolling service as an example.
-
Configure the Java environment.
-
Deploy a Java environment. We recommend installing Java 17 or later.
-
Download and install Gradle. We recommend installing Gradle 8 or later.
-
-
In this example, the directory is named
java-simple. After initialization, the directory structure is as follows:java-simple ├── app │ ├── build.gradle.kts │ └── src │ ├── main │ │ ├── java │ │ │ └── org │ │ │ └── example │ │ │ └── App.java │ │ └── resources │ └── test │ ├── java │ │ └── org │ │ └── example │ │ └── AppTest.java │ └── resources ├── gradle │ ├── libs.versions.toml │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle.kts -
In the
java-simpledirectory, modify or create the following files:build.gradle.kts
plugins { id("java") id("org.springframework.boot") version "3.0.6" id("io.spring.dependency-management") version "1.1.0" } sourceSets { main { java.setSrcDirs(setOf(".")) } } repositories { mavenCentral() } dependencies { implementation("org.springframework.boot:spring-boot-starter-web") }App.java
package org.example; import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication app = new SpringApplication(App.class); app.setBannerMode(Banner.Mode.OFF); app.run(args); } }RollController.java
package org.example; import java.util.Optional; import java.util.concurrent.ThreadLocalRandom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class RollController { private static final Logger logger = LoggerFactory.getLogger(RollController.class); @GetMapping("/rolldice") public String index(@RequestParam("player") Optional<String> player) { int result = this.getRandomNumber(1, 6); if (player.isPresent()) { logger.info("{} is rolling the dice: {}", player.get(), result); } else { logger.info("Anonymous player is rolling the dice: {}", result); } return Integer.toString(result); } public int getRandomNumber(int min, int max) { return ThreadLocalRandom.current().nextInt(min, max + 1); } }
Step 3: Configure the OpenTelemetry Java Agent
-
Download the OpenTelemetry Java Agent.
curl -L -O https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar -
Configure the environment variables.
export JAVA_TOOL_OPTIONS="-javaagent:/../opentelemetry-javaagent.jar" \ OTEL_TRACES_EXPORTER=otlp \ OTEL_METRICS_EXPORTER=otlp \ OTEL_LOGS_EXPORTER=otlp \ OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf \ OTEL_EXPORTER_OTLP_ENDPOINT=http://<IP_ADDRESS>:4318 \ OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://<IP_ADDRESS>:4318/v1/traces \ OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://<IP_ADDRESS>:4318/v1/metrics \ OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://<IP_ADDRESS>:4318/v1/logs \ OTEL_METRIC_EXPORT_INTERVAL=15000-
JAVA_TOOL_OPTIONS: Set this to the actual path of theopentelemetry-javaagent.jarfile. -
Endpoint configurations: In
http://<IP_ADDRESS>:4318, replace<IP_ADDRESS>with the IP address of the Otel Collector service endpoint accessible from your Java application. -
For information about other parameters, see properties-exporters.
-
Step 4: Start and access the Java application
-
In the project's application directory, run the following commands to start the application.
In this example, the project's application directory is
../java-simple/app.gradle assemble java -jar ./build/libs/app.jar -
In your browser, access
http://<IP_ADDRESS>:8080/rolldice. Replace<IP_ADDRESS>with the IP address of the server running the Java application.After a successful request, the page returns a random number, as shown in the following example:
5
Step 5: Query and analyze the observability data
-
In the left navigation pane of the Cloud Database ClickHouse instance details page, click All-in-one Observe Suite and follow the on-screen instructions to open the service portal.
-
On the main page, query and analyze the observability data from your Java application.
On the Search page in HyperDX, set the data source to otel_traces. Enter the SQL query
SELECT Timestamp, ServiceName as service, StatusCode as level, round(Duration / 1e6) as duration, SpanName, and set the sort order to Timestamp DESC. In the left Filters panel, filter by SpanName (for example,GET /rolldiceorPUBLISH) and ServiceName (for example,apporlanggenius/dify). The results table, which includes columns such as Timestamp, service, level, duration, and SpanName, allows you to review latency details for spans across services.