diff --git a/.gitignore b/.gitignore index 485dee6..f18e914 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .idea +venv/ diff --git a/README.md b/README.md index 8b6b9cc..26c9486 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ The Docker image is available on Docker hub: https://hub.docker.com/r/grafana/ot ## Run the Docker image ```sh -docker run -p 3000:3000 -p 4317:4317 -p 4318:4318 --rm -ti grafana/otel-lgtm +./run-lgtm.sh ``` ## Send OpenTelemetry Data @@ -72,4 +72,5 @@ Each example uses a different application port (to be able to run all applicatio |---------|---------------------------------------| | Java | `curl http://localhost:8080/rolldice` | | Go | `curl http://localhost:8081/rolldice` | +| Python | `curl http://localhost:8082/rolldice` | diff --git a/examples/go/Dockerfile b/examples/go/Dockerfile index 13549c1..6fb0951 100644 --- a/examples/go/Dockerfile +++ b/examples/go/Dockerfile @@ -1,26 +1,15 @@ -# syntax=docker/dockerfile:1 - FROM golang:1.21 -# Set destination for COPY WORKDIR /app -# Download Go modules COPY go.mod go.sum ./ RUN go mod download -# Copy the source code. Note the slash at the end, as explained in -# https://docs.docker.com/engine/reference/builder/#copy COPY *.go ./ # Build RUN CGO_ENABLED=0 GOOS=linux go build -o /rolldice -# Optional: -# To bind to a TCP port, runtime parameters must be supplied to the docker command. -# But we can document in the Dockerfile what ports -# the application is going to listen on by default. -# https://docs.docker.com/engine/reference/builder/#expose EXPOSE 8081 # Run diff --git a/examples/go/run.sh b/examples/go/run.sh index cad262f..f192e3c 100755 --- a/examples/go/run.sh +++ b/examples/go/run.sh @@ -4,5 +4,5 @@ set -euo pipefail export OTEL_EXPORTER_OTLP_INSECURE="true" # needed because of https://github.com/open-telemetry/opentelemetry-go/issues/4834 export OTEL_METRIC_EXPORT_INTERVAL="5000" # so we don't have to wait 60s for metrics -export OTEL_RESOURCE_ATTRIBUTES="service.name=example-app,service.instance.id=localhost:8081" +export OTEL_RESOURCE_ATTRIBUTES="service.name=rolldice,service.instance.id=localhost:8081" go run . diff --git a/examples/java/pom.xml b/examples/java/pom.xml index ec27aa1..20ac1af 100644 --- a/examples/java/pom.xml +++ b/examples/java/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.grafana.example - example-app + rolldice 1.0.0-SNAPSHOT Hello World REST Service diff --git a/examples/java/run.sh b/examples/java/run.sh index 89b9b45..77caf57 100755 --- a/examples/java/run.sh +++ b/examples/java/run.sh @@ -2,7 +2,7 @@ set -euo pipefail -if [[ ! -f ./target/example-app.jar ]] ; then +if [[ ! -f ./target/rolldice.jar ]] ; then ./mvnw clean package fi version=v2.0.0 @@ -10,5 +10,5 @@ jar=opentelemetry-javaagent-${version}.jar if [[ ! -f ./${jar} ]] ; then curl -sL https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/v2.0.0/opentelemetry-javaagent.jar -o ${jar} fi -export OTEL_RESOURCE_ATTRIBUTES="service.name=example-app,service.instance.id=localhost:8080" -java -Dotel.metric.export.interval=500 -Dotel.bsp.schedule.delay=500 -javaagent:${jar} -jar ./target/example-app.jar +export OTEL_RESOURCE_ATTRIBUTES="service.name=rolldice,service.instance.id=localhost:8080" +java -Dotel.metric.export.interval=500 -Dotel.bsp.schedule.delay=500 -javaagent:${jar} -jar ./target/rolldice.jar diff --git a/examples/python/Dockerfile b/examples/python/Dockerfile new file mode 100644 index 0000000..2bb29f3 --- /dev/null +++ b/examples/python/Dockerfile @@ -0,0 +1,25 @@ +FROM python:alpine3.19 + +WORKDIR /app + +COPY requirements.txt . + +# How to get the requirements.txt file? +# 1. Follow https://opentelemetry.io/docs/languages/python/getting-started/ +# 2. Run `pip freeze > requirements.txt` in the same directory as your app.py file +RUN pip install -r requirements.txt + +RUN pip install opentelemetry-distro[otlp] +RUN opentelemetry-bootstrap -a install + +COPY app.py . + +# Logging support is still in alpha, so we need to enable it explicitly +ENV OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true + +EXPOSE 8082 + +CMD ["opentelemetry-instrument", "flask", "run", "--host", "0.0.0.0", "--port", "8082"] + + + diff --git a/examples/python/app.py b/examples/python/app.py new file mode 100644 index 0000000..b3897ef --- /dev/null +++ b/examples/python/app.py @@ -0,0 +1,22 @@ +from random import randint +from flask import Flask, request +import logging + +app = Flask(__name__) +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + +@app.route("/rolldice") +def roll_dice(): + player = request.args.get('player', default=None, type=str) + result = str(roll()) + if player: + logger.warning("%s is rolling the dice: %s", player, result) + else: + logger.warning("Anonymous player is rolling the dice: %s", result) + return result + + +def roll(): + return randint(1, 6) diff --git a/examples/python/docker-compose.oats.yml b/examples/python/docker-compose.oats.yml new file mode 100644 index 0000000..9a57965 --- /dev/null +++ b/examples/python/docker-compose.oats.yml @@ -0,0 +1,13 @@ +# OATS is an acceptance testing framework for OpenTelemetry - https://github.com/grafana/oats/tree/main/yaml +version: '3.4' + +services: + go: + build: + context: . + dockerfile: Dockerfile + environment: + OTEL_EXPORTER_OTLP_ENDPOINT: http://collector:4317 + OTEL_METRIC_EXPORT_INTERVAL: "5000" # so we don't have to wait 60s for metrics + ports: + - "8080:8082" diff --git a/examples/python/oats.yaml b/examples/python/oats.yaml new file mode 100644 index 0000000..5ee168b --- /dev/null +++ b/examples/python/oats.yaml @@ -0,0 +1,17 @@ +# OATS is an acceptance testing framework for OpenTelemetry - https://github.com/grafana/oats/tree/main/yaml +docker-compose: + generator: lgtm + files: + - ./docker-compose.oats.yml +input: + - path: /rolldice +expected: + traces: + - traceql: '{ span.http.route = "/rolldice" }' + spans: + - name: '/rolldice' # should be "GET /rolldice" + attributes: + otel.library.name: opentelemetry.instrumentation.flask + metrics: + - promql: 'http_server_active_requests{http_method="GET"}' + value: ">= 0" diff --git a/examples/python/requirements.txt b/examples/python/requirements.txt new file mode 100644 index 0000000..5a3a34a --- /dev/null +++ b/examples/python/requirements.txt @@ -0,0 +1,7 @@ +blinker==1.7.0 +click==8.1.7 +Flask==2.3.3 +itsdangerous==2.1.2 +Jinja2==3.1.3 +MarkupSafe==2.1.5 +Werkzeug==2.3.8 diff --git a/examples/python/run.sh b/examples/python/run.sh new file mode 100755 index 0000000..3ea99db --- /dev/null +++ b/examples/python/run.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -euo pipefail + +export OTEL_METRIC_EXPORT_INTERVAL="5000" # so we don't have to wait 60s for metrics +export OTEL_RESOURCE_ATTRIBUTES="service.name=rolldice,service.instance.id=localhost:8082" +export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true + +python3 -m venv venv +source ./venv/bin/activate + +# How to get the requirements.txt file? +# 1. Follow https://opentelemetry.io/docs/languages/python/getting-started/ +# 2. Run `pip freeze > requirements.txt` in the same directory as your app.py file +pip install -r requirements.txt + +pip install opentelemetry-distro[otlp] +opentelemetry-bootstrap -a install + +opentelemetry-instrument flask run -p 8082 diff --git a/generate-traffic.sh b/generate-traffic.sh index c4c8fad..16dd646 100755 --- a/generate-traffic.sh +++ b/generate-traffic.sh @@ -1,3 +1,3 @@ #!/bin/bash -watch 'curl -s http://localhost:8080/rolldice; curl -s http://localhost:8081/rolldice' +watch 'curl -s http://localhost:8080/rolldice; curl -s http://localhost:8081/rolldice; curl -s http://localhost:8082/rolldice' diff --git a/run-lgtm.sh b/run-lgtm.sh new file mode 100755 index 0000000..176d67b --- /dev/null +++ b/run-lgtm.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +docker run -p 3000:3000 -p 4317:4317 -p 4318:4318 --rm -ti grafana/otel-lgtm