Skip to content

Commit fcd3a5f

Browse files
authored
Merge pull request #70 from geoadmin/PB-1954-add-otel-instrumentation
PB-1954: implement otel instrumentation
2 parents b1a33c8 + 82a4f08 commit fcd3a5f

File tree

12 files changed

+927
-316
lines changed

12 files changed

+927
-316
lines changed

.env.local

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,10 @@
11
ALLOWED_DOMAINS=.*localhost,.*\.admin\.ch,.*\.bgdi\.ch
2+
3+
# OTEL
4+
OTEL_SDK_DISABLED=false
5+
OTEL_ENABLE_FLASK=true
6+
OTEL_ENABLE_LOGGING=true
7+
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
8+
OTEL_EXPORTER_OTLP_INSECURE=true
9+
OTEL_RESOURCE_ATTRIBUTES=service.name=service-qrcode
10+
OTEL_PYTHON_EXCLUDED_URLS="checker"

.env.test

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,10 @@
1-
ALLOWED_DOMAINS=some_random_domain,.*\.geo\.admin\.ch,http://localhost
1+
ALLOWED_DOMAINS=some_random_domain,.*\.geo\.admin\.ch,http://localhost
2+
3+
# OTEL
4+
OTEL_SDK_DISABLED=false
5+
OTEL_ENABLE_FLASK=true
6+
OTEL_ENABLE_LOGGING=true
7+
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
8+
OTEL_EXPORTER_OTLP_INSECURE=true
9+
OTEL_RESOURCE_ATTRIBUTES=service.name=service-qrcode
10+
OTEL_PYTHON_EXCLUDED_URLS="checker"

.pylintrc

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ load-plugins=pylint_flask
3636
# Pickle collected data for later comparisons.
3737
persistent=yes
3838

39-
# When enabled, pylint would attempt to guess common misconfiguration and emit
40-
# user-friendly hints instead of false-positive error messages.
41-
suggestion-mode=yes
42-
4339
# Allow loading of arbitrary C extensions. Extensions are imported into the
4440
# active Python interpreter and may run arbitrary code.
4541
unsafe-load-any-extension=no
@@ -62,6 +58,7 @@ confidence=
6258
# --disable=W".
6359
disable=missing-docstring,
6460
missing-module-docstring,
61+
unused-argument,
6562
useless-object-inheritance,
6663

6764

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
FROM python:3.12-slim-bullseye
2-
ENV HTTP_PORT 8080
2+
ENV HTTP_PORT=8080
33
RUN groupadd -r geoadmin && useradd -r -s /bin/false -g geoadmin geoadmin
44

55

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ help:
6767
@echo -e " \033[1mSetup TARGETS\033[0m "
6868
@echo "- setup Create the python virtual environment with developper tools and activate it"
6969
@echo "- ci Create the python virtual environment and install requirements based on the Pipfile.lock"
70+
@echo "- otelrequirements Get a list of available otel instrumentation libraries to add to the pipfile of this project"
7071
@echo -e " \033[1mFORMATING, LINTING AND TESTING TOOLS TARGETS\033[0m "
7172
@echo "- format Format the python source code"
7273
@echo "- lint Lint the python source code"
@@ -99,6 +100,9 @@ ci: $(REQUIREMENTS)
99100
# Create virtual env with all packages for development using the Pipfile.lock
100101
pipenv sync --dev
101102

103+
.PHONY: otelrequirements
104+
otelrequirements:
105+
edot-bootstrap --action=requirements
102106

103107
# linting target, calls upon yapf to make sure your code is easier to read and respects some conventions.
104108

Pipfile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,15 @@ gunicorn = "~=23.0.0"
1010
Flask = "~=3.0.3"
1111
Pillow = "~=10.4.0"
1212
qrcode = "~=7.4"
13-
logging-utilities = "~=4.4.1"
13+
logging-utilities = "~=5.3.0"
1414
python-dotenv = "~=1.0.1"
1515

16+
# OpenTelemetry packages
17+
opentelemetry-sdk = "*"
18+
opentelemetry-exporter-otlp = "*"
19+
opentelemetry-instrumentation-flask = "*"
20+
opentelemetry-instrumentation-logging = "*"
21+
1622
[dev-packages]
1723
yapf = "*"
1824
nose2 = "*"

Pipfile.lock

Lines changed: 763 additions & 306 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/helpers/otel.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from os import getenv
2+
3+
from opentelemetry import trace
4+
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import \
5+
OTLPSpanExporter
6+
from opentelemetry.instrumentation.flask import FlaskInstrumentor
7+
from opentelemetry.instrumentation.logging import LoggingInstrumentor
8+
from opentelemetry.sdk.resources import Resource
9+
from opentelemetry.sdk.trace import TracerProvider
10+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
11+
12+
from app.helpers.utils import strtobool
13+
14+
15+
def initialize() -> None:
16+
if not strtobool(getenv("OTEL_SDK_DISABLED", "false")):
17+
if strtobool(getenv("OTEL_ENABLE_LOGGING", "false")):
18+
LoggingInstrumentor().instrument()
19+
20+
21+
def initialize_flask(app):
22+
if not strtobool(getenv("OTEL_SDK_DISABLED", "false")):
23+
if strtobool(getenv("OTEL_ENABLE_FLASK", "false")):
24+
FlaskInstrumentor().instrument_app(app)
25+
26+
27+
def setup_trace_provider():
28+
if not strtobool(getenv("OTEL_SDK_DISABLED", "false")):
29+
# Since we created a new tracer, the default span processor is gone. We need to
30+
# create a new one using the default OTEL env variables and ad it to the tracer.
31+
span_processor = BatchSpanProcessor(
32+
OTLPSpanExporter(
33+
endpoint=getenv('OTEL_EXPORTER_OTLP_ENDPOINT', "http://localhost:4317"),
34+
headers=getenv('OTEL_EXPORTER_OTLP_HEADERS'),
35+
insecure=strtobool(getenv('OTEL_EXPORTER_OTLP_INSECURE', "false"))
36+
)
37+
)
38+
39+
provider = TracerProvider(resource=Resource.create())
40+
provider.add_span_processor(span_processor)
41+
trace.set_tracer_provider(provider)

app/helpers/utils.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,18 @@ def get_logging_cfg():
3030
def init_logging():
3131
config = get_logging_cfg()
3232
logging.config.dictConfig(config)
33+
34+
35+
def strtobool(val):
36+
"""Convert a string representation of truth to True or False.
37+
38+
True values are 'y', 'yes', 't', 'true', 'on', and '1';
39+
False values are 'n', 'no', 'f', 'false', 'off', and '0'.
40+
Raises ValueError if 'val' is anything else.
41+
"""
42+
val = val.lower()
43+
if val in ('y', 'yes', 't', 'true', 'on', '1'):
44+
return True
45+
if val in ('n', 'no', 'f', 'false', 'off', '0'):
46+
return False
47+
raise ValueError(f"invalid truth value: {val}")

docker-compose-otel.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
version: "2"
2+
services:
3+
otel-collector:
4+
image: otel/opentelemetry-collector-contrib:latest
5+
command: --config otel-local-config.yaml
6+
volumes:
7+
- ./otel-local-config.yaml:/otel-local-config.yaml
8+
ports:
9+
- "4317:4317"
10+
11+
zipkin:
12+
image: openzipkin/zipkin:latest
13+
ports:
14+
- "9411:9411"

0 commit comments

Comments
 (0)