├── o11y-backend
├── grafana-bootstrap.ini
├── prometheus.yaml
├── tempo-overrides.yaml
├── grafana-datasources.yaml
└── tempo-config.yaml
├── .gitignore
├── images
└── youtube.png
├── src
└── main
│ ├── resources
│ ├── application.properties
│ └── logback.xml
│ └── java
│ └── tutorial
│ └── buildon
│ └── aws
│ └── o11y
│ ├── HelloApp.java
│ ├── Constants.java
│ └── HelloAppController.java
├── CODE_OF_CONDUCT.md
├── Dockerfile
├── collector-config-aws.yaml
├── collector-config-local.yaml
├── run-microservice.sh
├── LICENSE
├── docker-compose-aws.yaml
├── CONTRIBUTING.md
├── docker-compose.yaml
├── pom.xml
└── README.md
/o11y-backend/grafana-bootstrap.ini:
--------------------------------------------------------------------------------
1 | [feature_toggles]
2 | enable = tempoSearch tempoBackendSearch
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | tempo-data
3 | .vscode
4 | opentelemetry-javaagent-all.jar
5 | hello-app.log
6 |
--------------------------------------------------------------------------------
/images/youtube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/build-on-aws/instrumenting-java-apps-using-opentelemetry/HEAD/images/youtube.png
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.config.import=optional:dependencies.properties
2 | spring.application.name=hello-app
3 | server.port=8888
4 |
--------------------------------------------------------------------------------
/o11y-backend/prometheus.yaml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 15s
3 | evaluation_interval: 15s
4 |
5 | scrape_configs:
6 | - job_name: 'collector'
7 | scrape_interval: 5s
8 | static_configs:
9 | - targets: [ 'collector:6666' ]
10 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
4 | opensource-codeofconduct@amazon.com with any additional questions or comments.
5 |
--------------------------------------------------------------------------------
/src/main/java/tutorial/buildon/aws/o11y/HelloApp.java:
--------------------------------------------------------------------------------
1 | package tutorial.buildon.aws.o11y;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class HelloApp {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(HelloApp.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM maven:3.8.1-openjdk-17-slim
2 |
3 | VOLUME /tmp
4 | ADD . /usr/src/app
5 | WORKDIR /usr/src/app
6 |
7 | RUN mvn clean package -DskipTests
8 | RUN curl -L https://github.com/aws-observability/aws-otel-java-instrumentation/releases/download/v1.28.1/aws-opentelemetry-agent.jar --output opentelemetry-javaagent-all.jar
9 | ENTRYPOINT [ "java", "-javaagent:opentelemetry-javaagent-all.jar", "-jar", "target/hello-app-1.0.jar" ]
10 |
--------------------------------------------------------------------------------
/o11y-backend/tempo-overrides.yaml:
--------------------------------------------------------------------------------
1 | overrides:
2 | "single-tenant":
3 | search_tags_allow_list:
4 | - "instance"
5 | ingestion_rate_strategy: "local"
6 | ingestion_rate_limit_bytes: 15000000
7 | ingestion_burst_size_bytes: 20000000
8 | max_traces_per_user: 10000
9 | max_global_traces_per_user: 0
10 | max_bytes_per_trace: 50000
11 | max_search_bytes_per_trace: 0
12 | max_bytes_per_tag_values_query: 5000000
13 | block_retention: 0s
--------------------------------------------------------------------------------
/o11y-backend/grafana-datasources.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: 1
2 |
3 | datasources:
4 | - name: Prometheus
5 | type: prometheus
6 | access: proxy
7 | orgId: 1
8 | url: http://prometheus:9090
9 | basicAuth: false
10 | isDefault: false
11 | version: 1
12 | editable: false
13 | - name: Tempo
14 | type: tempo
15 | access: proxy
16 | orgId: 1
17 | url: http://tempo:3200
18 | basicAuth: false
19 | isDefault: true
20 | version: 1
21 | editable: false
22 | apiVersion: 1
23 | uid: tempo
24 |
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/main/java/tutorial/buildon/aws/o11y/Constants.java:
--------------------------------------------------------------------------------
1 | package tutorial.buildon.aws.o11y;
2 |
3 | public interface Constants {
4 |
5 | public static final String METRIC_PREFIX = "custom.metric.";
6 |
7 | public static final String NUMBER_OF_EXEC_NAME = METRIC_PREFIX + "number.of.exec";
8 | public static final String NUMBER_OF_EXEC_DESCRIPTION = "Count the number of executions.";
9 |
10 | public static final String HEAP_MEMORY_NAME = METRIC_PREFIX + "heap.memory";
11 | public static final String HEAP_MEMORY_DESCRIPTION = "Reports heap memory utilization.";
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/collector-config-aws.yaml:
--------------------------------------------------------------------------------
1 | receivers:
2 | otlp:
3 | protocols:
4 | grpc:
5 | endpoint: 0.0.0.0:5555
6 |
7 | processors:
8 | batch:
9 | timeout: 5s
10 | send_batch_size: 1024
11 |
12 | exporters:
13 | awsemf:
14 | region: 'us-east-1'
15 | log_group_name: '/metrics/otel'
16 | log_stream_name: 'otel-using-java'
17 | awsxray:
18 | region: 'us-east-1'
19 |
20 | service:
21 | pipelines:
22 | metrics:
23 | receivers: [otlp]
24 | processors: [batch]
25 | exporters: [awsemf]
26 | traces:
27 | receivers: [otlp]
28 | processors: [batch]
29 | exporters: [awsxray]
30 |
--------------------------------------------------------------------------------
/collector-config-local.yaml:
--------------------------------------------------------------------------------
1 | receivers:
2 | otlp:
3 | protocols:
4 | grpc:
5 | endpoint: 0.0.0.0:5555
6 |
7 | processors:
8 | batch:
9 | timeout: 1s
10 | send_batch_size: 1024
11 |
12 | exporters:
13 | prometheus:
14 | endpoint: collector:6666
15 | namespace: default
16 | otlp:
17 | endpoint: tempo:4317
18 | tls:
19 | insecure: true
20 |
21 | service:
22 | pipelines:
23 | metrics:
24 | receivers: [otlp]
25 | processors: [batch]
26 | exporters: [prometheus]
27 | traces:
28 | receivers: [otlp]
29 | processors: [batch]
30 | exporters: [otlp]
31 | telemetry:
32 | logs:
33 | level: debug
34 |
--------------------------------------------------------------------------------
/run-microservice.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | mvn clean package -Dmaven.test.skip=true
4 |
5 | AGENT_FILE=opentelemetry-javaagent-all.jar
6 | if [ ! -f "${AGENT_FILE}" ]; then
7 | curl -L https://github.com/aws-observability/aws-otel-java-instrumentation/releases/download/v1.28.1/aws-opentelemetry-agent.jar --output ${AGENT_FILE}
8 | fi
9 |
10 | export OTEL_TRACES_EXPORTER=otlp
11 | export OTEL_METRICS_EXPORTER=otlp
12 | export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:5555
13 |
14 | export OTEL_RESOURCE_ATTRIBUTES=service.name=hello-app,service.version=1.0
15 | export OTEL_TRACES_SAMPLER=always_on
16 | export OTEL_IMR_EXPORT_INTERVAL=1000
17 | export OTEL_METRIC_EXPORT_INTERVAL=1000
18 |
19 | java -javaagent:./${AGENT_FILE} -jar target/hello-app-1.0.jar
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of
4 | this software and associated documentation files (the "Software"), to deal in
5 | the Software without restriction, including without limitation the rights to
6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7 | the Software, and to permit persons to whom the Software is furnished to do so.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15 |
16 |
--------------------------------------------------------------------------------
/o11y-backend/tempo-config.yaml:
--------------------------------------------------------------------------------
1 | server:
2 | http_listen_port: 3200
3 |
4 | distributor:
5 | search_tags_deny_list:
6 | - "instance"
7 | - "version"
8 | receivers:
9 | jaeger:
10 | protocols:
11 | thrift_http:
12 | grpc:
13 | thrift_binary:
14 | thrift_compact:
15 | zipkin:
16 | otlp:
17 | protocols:
18 | http:
19 | grpc:
20 | opencensus:
21 |
22 | ingester:
23 | trace_idle_period: 10s
24 | max_block_bytes: 1_000_000
25 | max_block_duration: 5m
26 |
27 | compactor:
28 | compaction:
29 | compaction_window: 1h
30 | max_block_bytes: 100_000_000
31 | block_retention: 1h
32 | compacted_block_retention: 10m
33 |
34 | storage:
35 | trace:
36 | backend: local
37 | block:
38 | bloom_filter_false_positive: .05
39 | index_downsample_bytes: 1000
40 | encoding: zstd
41 | wal:
42 | path: /tmp/tempo/wal
43 | encoding: snappy
44 | local:
45 | path: /tmp/tempo/blocks
46 | pool:
47 | max_workers: 100
48 | queue_depth: 10000
49 |
50 | overrides:
51 | per_tenant_override_config: /etc/overrides.yaml
--------------------------------------------------------------------------------
/docker-compose-aws.yaml:
--------------------------------------------------------------------------------
1 | version: '3.0'
2 |
3 | services:
4 |
5 | hello-app:
6 | build: .
7 | image: hello-app:latest
8 | container_name: hello-app
9 | hostname: hello-app
10 | depends_on:
11 | - collector
12 | ports:
13 | - "8888:8888"
14 | environment:
15 | - OTEL_TRACES_EXPORTER=otlp
16 | - OTEL_METRICS_EXPORTER=otlp
17 | - OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:5555
18 | - OTEL_TRACES_SAMPLER=always_on
19 | - OTEL_IMR_EXPORT_INTERVAL=5000
20 | - OTEL_METRIC_EXPORT_INTERVAL=5000
21 | - OTEL_RESOURCE_ATTRIBUTES=service.name=hello-app,service.version=1.0,deployment.environment=production
22 | healthcheck:
23 | interval: 5s
24 | retries: 10
25 | test: curl --write-out 'HTTP %{http_code}' --fail --silent --output /dev/null http://localhost:8888/hello
26 |
27 | collector:
28 | image: public.ecr.aws/aws-observability/aws-otel-collector:latest
29 | container_name: collector
30 | hostname: collector
31 | command: ["--config=/etc/collector-config.yaml"]
32 | environment:
33 | - AWS_PROFILE=default
34 | volumes:
35 | - ./collector-config-aws.yaml:/etc/collector-config.yaml
36 | - ~/.aws:/root/.aws
37 | ports:
38 | - "5555:5555"
39 |
40 | networks:
41 | default:
42 | name: inst-java-apps-using-otel
43 |
--------------------------------------------------------------------------------
/src/main/java/tutorial/buildon/aws/o11y/HelloAppController.java:
--------------------------------------------------------------------------------
1 | package tutorial.buildon.aws.o11y;
2 |
3 | import java.util.Objects;
4 | import javax.annotation.PostConstruct;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import org.springframework.beans.factory.annotation.Value;
10 | import org.springframework.web.bind.annotation.*;
11 |
12 | import io.opentelemetry.api.GlobalOpenTelemetry;
13 | import io.opentelemetry.api.metrics.LongCounter;
14 | import io.opentelemetry.api.metrics.Meter;
15 | import io.opentelemetry.api.trace.Span;
16 | import io.opentelemetry.api.trace.Tracer;
17 | import io.opentelemetry.context.Scope;
18 | import io.opentelemetry.instrumentation.annotations.WithSpan;
19 |
20 | import static tutorial.buildon.aws.o11y.Constants.*;
21 | import static java.lang.Runtime.*;
22 |
23 | @RestController
24 | public class HelloAppController {
25 |
26 | private static final Logger log =
27 | LoggerFactory.getLogger(HelloAppController.class);
28 |
29 | @Value("otel.traces.api.version")
30 | private String tracesApiVersion;
31 |
32 | @Value("otel.metrics.api.version")
33 | private String metricsApiVersion;
34 |
35 | private final Tracer tracer =
36 | GlobalOpenTelemetry.getTracer("io.opentelemetry.traces.hello",
37 | tracesApiVersion);
38 |
39 | private final Meter meter =
40 | GlobalOpenTelemetry.meterBuilder("io.opentelemetry.metrics.hello")
41 | .setInstrumentationVersion(metricsApiVersion)
42 | .build();
43 |
44 | private LongCounter numberOfExecutions;
45 |
46 | @PostConstruct
47 | public void createMetrics() {
48 |
49 | numberOfExecutions =
50 | meter
51 | .counterBuilder(NUMBER_OF_EXEC_NAME)
52 | .setDescription(NUMBER_OF_EXEC_DESCRIPTION)
53 | .setUnit("int")
54 | .build();
55 |
56 | meter
57 | .gaugeBuilder(HEAP_MEMORY_NAME)
58 | .setDescription(HEAP_MEMORY_DESCRIPTION)
59 | .setUnit("byte")
60 | .buildWithCallback(
61 | r -> {
62 | r.record(getRuntime().totalMemory() - getRuntime().freeMemory());
63 | });
64 |
65 | }
66 |
67 | @RequestMapping(method= RequestMethod.GET, value="/hello")
68 | public Response hello() {
69 | Response response = buildResponse();
70 | // Creating a custom span
71 | Span span = tracer.spanBuilder("mySpan").startSpan();
72 | try (Scope scope = span.makeCurrent()) {
73 | if (response.isValid()) {
74 | log.info("The response is valid.");
75 | }
76 | // Update the synchronous metric
77 | numberOfExecutions.add(1);
78 | } finally {
79 | span.end();
80 | }
81 | return response;
82 | }
83 |
84 | @WithSpan
85 | private Response buildResponse() {
86 | return new Response("Hello World");
87 | }
88 |
89 | private record Response (String message) {
90 | private Response {
91 | Objects.requireNonNull(message);
92 | }
93 | private boolean isValid() {
94 | return true;
95 | }
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing Guidelines
2 |
3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4 | documentation, we greatly value feedback and contributions from our community.
5 |
6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7 | information to effectively respond to your bug report or contribution.
8 |
9 |
10 | ## Reporting Bugs/Feature Requests
11 |
12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features.
13 |
14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already
15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
16 |
17 | * A reproducible test case or series of steps
18 | * The version of our code being used
19 | * Any modifications you've made relevant to the bug
20 | * Anything unusual about your environment or deployment
21 |
22 |
23 | ## Contributing via Pull Requests
24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
25 |
26 | 1. You are working against the latest source on the *main* branch.
27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
29 |
30 | To send us a pull request, please:
31 |
32 | 1. Fork the repository.
33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
34 | 3. Ensure local tests pass.
35 | 4. Commit to your fork using clear commit messages.
36 | 5. Send us a pull request, answering any default questions in the pull request interface.
37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
38 |
39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
41 |
42 |
43 | ## Finding contributions to work on
44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
45 |
46 |
47 | ## Code of Conduct
48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
50 | opensource-codeofconduct@amazon.com with any additional questions or comments.
51 |
52 |
53 | ## Security issue notifications
54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
55 |
56 |
57 | ## Licensing
58 |
59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
60 |
--------------------------------------------------------------------------------
/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '3.0'
2 |
3 | services:
4 |
5 | hello-app:
6 | build: .
7 | image: hello-app:latest
8 | container_name: hello-app
9 | hostname: hello-app
10 | depends_on:
11 | - collector
12 | ports:
13 | - "8888:8888"
14 | environment:
15 | - OTEL_TRACES_EXPORTER=otlp
16 | - OTEL_METRICS_EXPORTER=otlp
17 | - OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:5555
18 | - OTEL_TRACES_SAMPLER=always_on
19 | - OTEL_IMR_EXPORT_INTERVAL=5000
20 | - OTEL_METRIC_EXPORT_INTERVAL=5000
21 | - OTEL_RESOURCE_ATTRIBUTES=service.name=hello-app,service.version=1.0,deployment.environment=development
22 | healthcheck:
23 | interval: 5s
24 | retries: 10
25 | test: curl --write-out 'HTTP %{http_code}' --fail --silent --output /dev/null http://localhost:8888/hello
26 |
27 | collector:
28 | image: otel/opentelemetry-collector:latest
29 | container_name: collector
30 | hostname: collector
31 | depends_on:
32 | tempo:
33 | condition: service_healthy
34 | prometheus:
35 | condition: service_healthy
36 | command: ["--config=/etc/collector-config.yaml"]
37 | volumes:
38 | - ./collector-config-local.yaml:/etc/collector-config.yaml
39 | ports:
40 | - "5555:5555"
41 | - "6666:6666"
42 |
43 | tempo:
44 | image: grafana/tempo:1.5.0
45 | command: [ "-search.enabled=true", "-config.file=/etc/tempo.yaml" ]
46 | container_name: tempo
47 | hostname: tempo
48 | volumes:
49 | - ./o11y-backend/tempo-config.yaml:/etc/tempo.yaml
50 | - ./o11y-backend/tempo-overrides.yaml:/etc/overrides.yaml
51 | - ./tempo-data:/tmp/tempo
52 | ports:
53 | - "3200:3200"
54 | - "4317:4317"
55 | healthcheck:
56 | interval: 5s
57 | retries: 10
58 | test: wget --no-verbose --tries=1 --spider http://localhost:3200/status || exit 1
59 |
60 | prometheus:
61 | image: prom/prometheus:v2.39.2
62 | container_name: prometheus
63 | hostname: prometheus
64 | command:
65 | - --config.file=/etc/prometheus.yaml
66 | - --web.enable-remote-write-receiver
67 | - --enable-feature=exemplar-storage
68 | volumes:
69 | - ./o11y-backend/prometheus.yaml:/etc/prometheus.yaml
70 | ports:
71 | - "9090:9090"
72 | healthcheck:
73 | interval: 5s
74 | retries: 10
75 | test: wget --no-verbose --tries=1 --spider http://localhost:9090/status || exit 1
76 |
77 | grafana:
78 | image: grafana/grafana:9.2.2
79 | container_name: grafana
80 | hostname: grafana
81 | depends_on:
82 | tempo:
83 | condition: service_healthy
84 | prometheus:
85 | condition: service_healthy
86 | volumes:
87 | - ./o11y-backend/grafana-bootstrap.ini:/etc/grafana/grafana.ini
88 | - ./o11y-backend/grafana-datasources.yaml:/etc/grafana/provisioning/datasources/datasources.yaml
89 | environment:
90 | - GF_AUTH_ANONYMOUS_ENABLED=true
91 | - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
92 | - GF_AUTH_DISABLE_LOGIN_FORM=true
93 | ports:
94 | - "3000:3000"
95 | healthcheck:
96 | interval: 5s
97 | retries: 10
98 | test: wget --no-verbose --tries=1 --spider http://localhost:3000 || exit 1
99 |
100 | networks:
101 | default:
102 | name: inst-java-apps-using-otel
103 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | tutorial.buildon.aws.o11y
7 | hello-app
8 | 1.0
9 |
10 |
11 | org.springframework.boot
12 | spring-boot-starter-parent
13 | 3.1.2
14 |
15 |
16 |
17 |
18 | 17
19 | 0.13.1
20 | 1.10.0-alpha-rc.1
21 |
22 |
23 |
24 |
25 | org.springframework.boot
26 | spring-boot-starter-web
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter-actuator
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-devtools
35 | runtime
36 |
37 |
38 | org.springframework.boot
39 | spring-boot-starter-test
40 | test
41 |
42 |
43 | junit
44 | junit
45 | 4.13.2
46 | compile
47 |
48 |
49 | javax.annotation
50 | javax.annotation-api
51 | 1.3.2
52 |
53 |
54 | io.opentelemetry
55 | opentelemetry-api
56 | 1.28.0
57 |
58 |
59 | io.opentelemetry.instrumentation
60 | opentelemetry-instrumentation-annotations
61 | 1.28.0
62 |
63 |
64 | io.opentelemetry
65 | opentelemetry-api-trace
66 | ${otel.traces.api.version}
67 |
68 |
69 | io.opentelemetry
70 | opentelemetry-api-metrics
71 | ${otel.metrics.api.version}
72 |
73 |
74 |
75 |
76 |
77 | org.apache.maven.plugins
78 | maven-compiler-plugin
79 | 3.11.0
80 |
81 | 17
82 |
83 |
84 |
85 | org.springframework.boot
86 | spring-boot-maven-plugin
87 |
88 |
89 | org.codehaus.mojo
90 | properties-maven-plugin
91 | 1.2.0
92 |
93 |
94 | package
95 |
96 | write-project-properties
97 |
98 |
99 | ${project.build.outputDirectory}/dependencies.properties
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Instrumenting Java Applications using OpenTelemetry
2 |
3 | This project provides an example of microservice written in Java that produces telemetry data for traces and metrics using [OpenTelemetry](https://opentelemetry.io). It also shows how to de-couple the application from the observability backend using the [OpenTelemetry Collector](https://opentelemetry.io/docs/collector) and the [OTLP protocol](https://opentelemetry.io/docs/reference/specification/protocol), so you can be easily switch the observability backend for another without code changes.
4 |
5 | 💡 If you want to learn how to build this code with a hands-on tutorial, you can watch the YouTube series below.
6 |
7 | [](https://www.youtube.com/watch?v=XvmicNH_4lc&list=PLDqi6CuDzubz5viRapQ049TjJMOCCu9MJ&index=1)
8 |
9 | Alternatively, you can also read the blog post: https://www.buildon.aws/posts/instrumenting-java-apps-using-opentelemetry
10 |
11 | ### Requirements
12 |
13 | * [Java 17+](https://openjdk.org/install)
14 | * [Maven 3.8.6+](https://maven.apache.org/download.cgi)
15 | * [Docker](https://www.docker.com/get-started)
16 |
17 | ## 🏢 Running the microservice with Grafana, Grafana Tempo, and Prometheus as observability backend.
18 |
19 | You can have the microservice sending telemetry data to a local observability backend. Traces will be sent to [Grafana Tempo](https://grafana.com/traces) and the metrics to [Prometheus](https://prometheus.io). Then you can use [Grafana](https://grafana.com/grafana) to visualize the the generated telemetry data.
20 |
21 | 1. Start the containers using Docker Compose.
22 |
23 | ```bash
24 | docker compose -f docker-compose.yaml up -d
25 | ```
26 |
27 | 2. Access the Grafana UI: http://localhost:3000
28 |
29 | ## 🌩 Running the microservice with AWS X-Ray and Amazon CloudWatch as observability backend.
30 |
31 | You can have the microservice sending telemetry data to AWS as observability backend. Traces will be sent to [AWS X-Ray](https://aws.amazon.com/xray) and the metrics to [Amazon CloudWatch](https://aws.amazon.com/cloudwatch). This is possible thanks to the [AWS Distro for OpenTelemetry](https://aws.amazon.com/otel) that provides out-of-the-box integration with AWS services. Before running the code; make sure to [configure your AWS credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html) in your machine, as the code will use them to connect with the target services.
32 |
33 | 1. Start the containers using Docker Compose.
34 |
35 | ```bash
36 | docker compose -f docker-compose-aws.yaml up -d
37 | ```
38 |
39 | 2. Access the AWS Console: https://console.aws.amazon.com
40 |
41 | ## ⚡️ Invoke the Microservice API manually
42 |
43 | The microservice expose an API over the port 8888 using HTTP.
44 |
45 | 1. Invoke this API for testing purposes.
46 |
47 | ```bash
48 | curl -X GET http://localhost:8888/hello
49 | ```
50 |
51 | ## Security
52 |
53 | See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
54 |
55 | ## Disclaimers
56 |
57 | ```text
58 | This package requires and may incorporate or retrieve a number of third-party
59 | software packages (such as open source packages) at install-time or build-time
60 | or run-time ("External Dependencies"). The External Dependencies are subject to
61 | license terms that you must accept in order to use this package. If you do not
62 | accept all of the applicable license terms, you should not use this package. We
63 | recommend that you consult your company's open source approval policy before
64 | proceeding.
65 |
66 | Provided below is a list of External Dependencies and the applicable license
67 | identification as indicated by the documentation associated with the External
68 | Dependencies as of Amazon's most recent review.
69 |
70 | THIS INFORMATION IS PROVIDED FOR CONVENIENCE ONLY. AMAZON DOES NOT PROMISE THAT
71 | THE LIST OR THE APPLICABLE TERMS AND CONDITIONS ARE COMPLETE, ACCURATE, OR
72 | UP-TO-DATE, AND AMAZON WILL HAVE NO LIABILITY FOR ANY INACCURACIES. YOU SHOULD
73 | CONSULT THE DOWNLOAD SITES FOR THE EXTERNAL DEPENDENCIES FOR THE MOST COMPLETE
74 | AND UP-TO-DATE LICENSING INFORMATION.
75 |
76 | YOUR USE OF THE EXTERNAL DEPENDENCIES IS AT YOUR SOLE RISK. IN NO EVENT WILL
77 | AMAZON BE LIABLE FOR ANY DAMAGES, INCLUDING WITHOUT LIMITATION ANY DIRECT,
78 | INDIRECT, CONSEQUENTIAL, SPECIAL, INCIDENTAL, OR PUNITIVE DAMAGES (INCLUDING
79 | FOR ANY LOSS OF GOODWILL, BUSINESS INTERRUPTION, LOST PROFITS OR DATA, OR
80 | COMPUTER FAILURE OR MALFUNCTION) ARISING FROM OR RELATING TO THE EXTERNAL
81 | DEPENDENCIES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, EVEN
82 | IF AMAZON HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
83 | AND DISCLAIMERS APPLY EXCEPT TO THE EXTENT PROHIBITED BY APPLICABLE LAW.
84 |
85 | Grafana (https://grafana.com) – Affero General Public License 3.0
86 | ```
87 |
88 | ## License
89 |
90 | This library is licensed under the MIT-0 License. See the [LICENSE](./LICENSE) file.
91 |
--------------------------------------------------------------------------------