-
Notifications
You must be signed in to change notification settings - Fork 128
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
add example for OTLP logging via stdout and k8s #547
base: main
Are you sure you want to change the base?
Changes from all commits
884cb52
e9a828d
53e0989
fbbe529
53822c7
51cc285
d47be0a
a9b7786
6042466
b5b44a7
49d61b7
eb70bb2
a186517
d44bcd3
899c6d0
ed68f72
291fb3f
f78cdbc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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. maybe rename to |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#!/usr/bin/env bash | ||
|
||
set -euo pipefail | ||
|
||
pushd logging-k8s-stdout-otlp-json | ||
../gradlew assemble | ||
popd | ||
|
||
wget -q -O - https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash | ||
|
||
cd oats/yaml | ||
go install github.com/onsi/ginkgo/v2/ginkgo@latest | ||
export TESTCASE_TIMEOUT=5m | ||
export TESTCASE_BASE_PATH=../.. | ||
ginkgo -r |
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,48 @@ | ||||||||
name: Acceptance Tests | ||||||||
|
||||||||
on: | ||||||||
pull_request: | ||||||||
branches: | ||||||||
- main | ||||||||
paths: | ||||||||
- .github/workflows/acceptance-tests.yml | ||||||||
- 'logging-k8s-stdout-otlp-json/**' | ||||||||
workflow_dispatch: | ||||||||
|
||||||||
jobs: | ||||||||
acceptance-tests: | ||||||||
runs-on: ubuntu-24.04 | ||||||||
steps: | ||||||||
- name: Check out | ||||||||
uses: actions/checkout@v4 | ||||||||
|
||||||||
- name: Set up JDK for running Gradle | ||||||||
uses: actions/setup-java@v4 | ||||||||
with: | ||||||||
distribution: temurin | ||||||||
java-version: 17 | ||||||||
|
||||||||
- name: Set up gradle | ||||||||
uses: gradle/actions/setup-gradle@v4 | ||||||||
with: | ||||||||
cache-read-only: ${{ github.event_name == 'pull_request' }} | ||||||||
|
||||||||
- name: Check out oats | ||||||||
uses: actions/checkout@v4 | ||||||||
with: | ||||||||
repository: grafana/oats | ||||||||
ref: bc2f08c5e55114234cece216290f1580a75a6032 | ||||||||
path: oats | ||||||||
- name: Set up Go | ||||||||
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. (sorry, just a nitpicky preference I have)
Suggested change
|
||||||||
uses: actions/setup-go@v5 | ||||||||
with: | ||||||||
go-version: '1.23' | ||||||||
cache-dependency-path: oats/go.sum | ||||||||
- name: Run acceptance tests | ||||||||
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.
Suggested change
|
||||||||
run: .github/scripts/run-acceptance-tests.sh | ||||||||
- name: upload log file | ||||||||
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.
Suggested change
|
||||||||
uses: actions/upload-artifact@v4 | ||||||||
if: failure() | ||||||||
with: | ||||||||
name: OATS logs | ||||||||
path: oats/yaml/build/**/*.log |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
FROM eclipse-temurin:21-jre | ||
|
||
WORKDIR /usr/src/app/ | ||
|
||
# renovate: datasource=github-releases depName=opentelemetry-java-instrumentation packageName=open-telemetry/opentelemetry-java-instrumentation | ||
ENV OPENTELEMETRY_JAVA_INSTRUMENTATION_VERSION=v2.10.0 | ||
|
||
ADD build/libs/*SNAPSHOT.jar ./app.jar | ||
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. what do you think about adding the |
||
ADD --chmod=644 https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/$OPENTELEMETRY_JAVA_INSTRUMENTATION_VERSION/opentelemetry-javaagent.jar ./opentelemetry-javaagent.jar | ||
ENV JAVA_TOOL_OPTIONS=-javaagent:./opentelemetry-javaagent.jar | ||
|
||
EXPOSE 8080 | ||
ENTRYPOINT [ "java", "-jar", "./app.jar" ] |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,43 @@ | ||||||||||||||
# Exporting Application logs using JSON logging in Kubernetes | ||||||||||||||
|
||||||||||||||
If you want to get logs from your Java application ingested into an | ||||||||||||||
OpenTelemetry-compatible logs backend, the easiest and recommended way is using | ||||||||||||||
an OpenTelemetry protocol (OTLP) exporter, | ||||||||||||||
which is explained in the [logging](../logging) example. | ||||||||||||||
|
||||||||||||||
However, some scenarios require logs | ||||||||||||||
to be output to files or stdout due to organizational or reliability needs. | ||||||||||||||
Refer to [Collecting OpenTelemetry-compliant Java logs from files](https://opentelemetry.io/blog/2024/collecting-otel-compliant-java-logs-from-files/) for more details. | ||||||||||||||
|
||||||||||||||
This example contains | ||||||||||||||
|
||||||||||||||
- a Java application that uses the experimental | ||||||||||||||
[experimental-otlp/stdout](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/configuration/sdk-environment-variables.md#in-development-exporter-selection) logs exporter | ||||||||||||||
- a OTel collector configuration that uses the | ||||||||||||||
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.
Suggested change
|
||||||||||||||
[OTLP/JSON connector](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/connector/otlpjsonconnector) to turn Pod logs into `OTLP` | ||||||||||||||
|
||||||||||||||
## Architecture | ||||||||||||||
|
||||||||||||||
![OTLP/JSON Architecture](otlpjson-architecture.png) | ||||||||||||||
|
||||||||||||||
The OTel Collector pipeline: | ||||||||||||||
|
||||||||||||||
![OTel Collector Pipeline](otel-collector-otlpjson-pipeline.png) | ||||||||||||||
Comment on lines
+23
to
+25
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.
Suggested change
|
||||||||||||||
|
||||||||||||||
## Getting Started | ||||||||||||||
|
||||||||||||||
The k8s directory contains the Kubernetes manifests to deploy the application and the collector. | ||||||||||||||
|
||||||||||||||
Ignore the `lgtm.yaml` file, which is only used for running locally with | ||||||||||||||
[LGTM](https://github.com/grafana/docker-otel-lgtm/) | ||||||||||||||
and automated testing using [OATs](https://github.com/grafana/oats). | ||||||||||||||
|
||||||||||||||
## Running locally | ||||||||||||||
|
||||||||||||||
You can run the application locally using the following steps: | ||||||||||||||
|
||||||||||||||
1. Run [k3d.sh](./k3d.sh) to start a local Kubernetes cluster with all the necessary components. | ||||||||||||||
2. Generate traffic using [generate-traffic.sh](./generate-traffic.sh) | ||||||||||||||
3. Log in to [http://localhost:3000](http://localhost:3000) | ||||||||||||||
4. Go to "Explore" | ||||||||||||||
5. Select "Loki" as data source to view the logs |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import org.springframework.boot.gradle.plugin.SpringBootPlugin | ||
import org.springframework.boot.gradle.tasks.bundling.BootJar | ||
|
||
plugins { | ||
id("java") | ||
id("org.springframework.boot") version "3.4.0" | ||
} | ||
|
||
description = "OpenTelemetry Example for Java Agent with Stdout logging" | ||
val moduleName by extra { "io.opentelemetry.examples.javagent.logging-k8s-stdout-otlp-json" } | ||
|
||
java { | ||
toolchain { | ||
languageVersion.set(JavaLanguageVersion.of(17)) | ||
} | ||
} | ||
|
||
dependencies { | ||
implementation(platform(SpringBootPlugin.BOM_COORDINATES)) | ||
|
||
implementation("org.springframework.boot:spring-boot-starter-web") | ||
implementation("org.springframework.boot:spring-boot-starter-actuator") | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#!/bin/bash | ||
|
||
set -euo pipefail | ||
|
||
docker build -f Dockerfile -t "dice:1.1-SNAPSHOT" . |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/bash | ||
|
||
watch 'curl -s http://localhost:8080/rolldice' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#!/bin/bash | ||
|
||
set -euo pipefail | ||
|
||
./build.sh | ||
k3d cluster create jsonlogging || k3d cluster start jsonlogging | ||
k3d image import -c jsonlogging dice:1.1-SNAPSHOT | ||
Comment on lines
+5
to
+7
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. since this file already has a dependency on the dice image, does it make sense to just inline the one line here? |
||
|
||
kubectl apply -f k8s/ | ||
|
||
kubectl wait --for=condition=ready pod -l app=dice | ||
kubectl wait --for=condition=ready --timeout=5m pod -l app=lgtm | ||
|
||
kubectl port-forward service/dice 8080:8080 & | ||
kubectl port-forward service/lgtm 3000:3000 & |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
apiVersion: v1 | ||
kind: ConfigMap | ||
metadata: | ||
name: otel-collector-config | ||
data: | ||
otel-collector-config.yaml: |- | ||
receivers: | ||
otlp: | ||
protocols: | ||
grpc: | ||
endpoint: 0.0.0.0:4317 | ||
http: | ||
endpoint: 0.0.0.0:4318 | ||
prometheus/collector: # needed if you use the docker-lgtm image | ||
zeitlinger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
config: | ||
scrape_configs: | ||
- job_name: 'opentelemetry-collector' | ||
static_configs: | ||
- targets: [ 'localhost:8888' ] | ||
filelog/otlp-json-logs: | ||
include: | ||
- /var/log/pods/*/*/*.log | ||
include_file_path: true | ||
operators: | ||
- id: container-parser | ||
type: container | ||
|
||
processors: | ||
zeitlinger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
batch: | ||
resourcedetection: | ||
detectors: [ "env", "system" ] | ||
override: false | ||
|
||
zeitlinger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
k8sattributes: | ||
# Config details in | ||
# https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/processor/k8sattributesprocessor | ||
connectors: | ||
otlpjson: | ||
|
||
exporters: | ||
otlphttp/metrics: | ||
endpoint: http://localhost:9090/api/v1/otlp | ||
otlphttp/traces: | ||
endpoint: http://localhost:4418 | ||
otlphttp/logs: | ||
endpoint: http://localhost:3100/otlp | ||
debug/metrics: | ||
verbosity: detailed | ||
debug/traces: | ||
verbosity: detailed | ||
debug/logs: | ||
verbosity: detailed | ||
nop: | ||
|
||
service: | ||
pipelines: | ||
traces: | ||
receivers: [ otlp ] | ||
processors: [ k8sattributes, resourcedetection, batch ] | ||
exporters: [ otlphttp/traces ] | ||
metrics: | ||
receivers: [ otlp, prometheus/collector ] | ||
zeitlinger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
processors: [ k8sattributes, resourcedetection, batch ] | ||
exporters: [ otlphttp/metrics ] | ||
logs/raw_otlpjson: | ||
receivers: [ filelog/otlp-json-logs ] | ||
# (i) no need for processors before the otlpjson connector | ||
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. what does (i) mean? |
||
# Declare processors in the shared "logs" pipeline below | ||
processors: [ ] | ||
exporters: [ otlpjson ] | ||
logs/otlp: | ||
receivers: [ otlp, otlpjson ] | ||
processors: [ k8sattributes, resourcedetection, batch ] | ||
exporters: [ otlphttp/logs ] | ||
# exporters: [ otlphttp/logs, debug/logs ] # Uncomment this line to enable debug logging |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
apiVersion: v1 | ||
kind: Service | ||
metadata: | ||
name: dice | ||
spec: | ||
selector: | ||
app: dice | ||
ports: | ||
- protocol: TCP | ||
port: 8080 | ||
targetPort: 8080 | ||
--- | ||
apiVersion: apps/v1 | ||
kind: Deployment | ||
metadata: | ||
name: dice | ||
spec: | ||
replicas: 1 | ||
selector: | ||
matchLabels: | ||
app: dice | ||
template: | ||
metadata: | ||
labels: | ||
app: dice | ||
spec: | ||
containers: | ||
- name: dice | ||
image: dice:1.1-SNAPSHOT | ||
imagePullPolicy: Never | ||
ports: | ||
- containerPort: 8080 | ||
env: | ||
- name: OTEL_EXPORTER_OTLP_ENDPOINT | ||
value: "http://lgtm:4318" | ||
- name: OTEL_LOGS_EXPORTER | ||
value: "experimental-otlp/stdout" | ||
- name: OTEL_RESOURCE_ATTRIBUTES | ||
value: service.name=dice,service.namespace=shop,service.version=1.1,deployment.environment=staging | ||
- name: OTEL_INSTRUMENTATION_LOGBACK_APPENDER_EXPERIMENTAL_LOG_ATTRIBUTES | ||
value: "true" | ||
- name: OTEL_INSTRUMENTATION_LOGBACK_APPENDER_EXPERIMENTAL_CAPTURE_KEY_VALUE_PAIR_ATTRIBUTES | ||
value: "true" | ||
- name: OTEL_INSTRUMENTATION_LOGBACK_APPENDER_EXPERIMENTAL_CAPTURE_MDC_ATTRIBUTES | ||
value: "true" | ||
- name: SERVICE_NAME | ||
value: dice | ||
|
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.
interesting 👍