Skip to content

Commit c5b07c3

Browse files
authored
Merge pull request #88 from geoadmin/develop
New Release v4.4.0 - #minor
2 parents ac9f103 + ff0fa02 commit c5b07c3

12 files changed

Lines changed: 719 additions & 982 deletions

.env.default

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,11 @@ ALLOWED_DOMAINS=localhost,.*\.geo\.admin\.ch,.*\.bgdi\.ch
77
STAGING=local
88

99
# OTEL
10-
OTEL_SDK_DISABLED=true
10+
OTEL_SDK_DISABLED=false
11+
OTEL_ENABLE_BOTO=true
12+
OTEL_ENABLE_FLASK=true
13+
OTEL_ENABLE_LOGGING=true
14+
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
15+
OTEL_EXPORTER_OTLP_INSECURE=true
16+
OTEL_RESOURCE_ATTRIBUTES=service.name=service-shortlink
17+
OTEL_PYTHON_EXCLUDED_URLS="checker"

.pylintrc

Lines changed: 0 additions & 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

Makefile

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ YAPF_CMD := $(PIPENV_RUN) yapf
2828
ISORT_CMD := $(PIPENV_RUN) isort
2929
NOSE_CMD := $(PIPENV_RUN) nose2
3030
PYLINT_CMD := $(PIPENV_RUN) pylint
31+
EDOT_BOOTSTRAP_CMD := $(PIPENV_RUN) edot-bootstrap
3132

3233
# AWS variables
3334
AWS_DEFAULT_REGION = eu-central-1
@@ -70,7 +71,6 @@ help:
7071
@echo "- dockerpush Build and push the project localy (with tag := $(DOCKER_IMG_LOCAL_TAG))"
7172
@echo "- dockerrun Run the project using the gunicorn WSGI server inside a container. (Exposed_port: $(HTTP_PORT)"
7273
@echo "- shutdown Stop the aforementioned container"
73-
@echo "- otelrequirements Get a list of available otel instrumentation libraries to add to the pipfile of this project"
7474
@echo -e " \033[1mCLEANING TARGETS\033[0m "
7575
@echo "- clean Clean genereated files"
7676
@echo "- clean_venv Clean python venv"
@@ -125,7 +125,7 @@ serve: clean_logs $(LOGS_DIR)
125125

126126
.PHONY: gunicornserve
127127
gunicornserve: clean_logs $(LOGS_DIR)
128-
OTEL_SDK_DISABLED=true ENV_FILE=.env.default LOGS_DIR=$(LOGS_DIR) ${PYTHON_CMD} wsgi.py
128+
ENV_FILE=.env.default LOGS_DIR=$(LOGS_DIR) ${PYTHON_CMD} wsgi.py
129129

130130
# Docker related functions.
131131
.PHONY: dockerlogin
@@ -179,9 +179,5 @@ clean: clean_venv clean_logs
179179

180180
# Actual builds targets with dependencies
181181

182-
.PHONY: otelrequirements
183-
otelrequirements:
184-
edot-bootstrap --action=requirements
185-
186182
$(LOGS_DIR):
187183
mkdir -p -m=777 $(LOGS_DIR)

Pipfile

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ name = "pypi"
55

66
[packages]
77
boto3 = "~=1.40"
8-
logging-utilities = "~=5.1"
8+
logging-utilities = "~=5.3"
99
Flask = "~=3.1"
1010
gevent = "~=25.8"
1111
gunicorn = "~=23.0"
@@ -18,18 +18,17 @@ opentelemetry-exporter-otlp = "~=1.37"
1818
opentelemetry-instrumentation = "*"
1919

2020
# Specific OpenTelemetry instrumentation libraries used to instrument this app
21-
# Full list or a subset of libraries listed by 'make otelrequirements'
21+
# Full list or a subset of libraries listed by 'edot-bootstrap --action=requirements'
2222
opentelemetry-instrumentation-botocore = "*"
2323
opentelemetry-instrumentation-flask = "*"
24-
opentelemetry-instrumentation-requests = "*"
24+
opentelemetry-instrumentation-logging = "*"
2525

2626
[dev-packages]
2727
yapf = "~=0.43"
2828
moto = "~=5.1"
2929
nose2 = "*"
3030
pylint = "*"
3131
pylint-flask = "*"
32-
elastic-opentelemetry = "*"
3332

3433
[requires]
3534
python_version = "3.13"

Pipfile.lock

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

README.md

Lines changed: 47 additions & 37 deletions
Large diffs are not rendered by default.

app/helpers/otel.py

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,56 @@
1-
import os
1+
from os import getenv
22

33
from opentelemetry import trace
44
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import \
55
OTLPSpanExporter
6+
from opentelemetry.instrumentation.botocore import BotocoreInstrumentor
7+
from opentelemetry.instrumentation.flask import FlaskInstrumentor
8+
from opentelemetry.instrumentation.logging import LoggingInstrumentor
69
from opentelemetry.sdk.resources import Resource
710
from opentelemetry.sdk.trace import TracerProvider
811
from opentelemetry.sdk.trace.export import BatchSpanProcessor
912

10-
from app.helpers.utils import strtobool
1113

14+
def strtobool(value) -> bool:
15+
"""Convert a string representation of truth to true (1) or false (0).
16+
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
17+
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
18+
'val' is anything else.
19+
"""
20+
value = value.lower()
21+
if value in ('y', 'yes', 't', 'true', 'on', '1'):
22+
return True
23+
if value in ('n', 'no', 'f', 'false', 'off', '0'):
24+
return False
25+
raise ValueError(f"invalid truth value \'{value}\'")
1226

13-
def setup_trace_provider(worker_pid):
14-
trace.set_tracer_provider(TracerProvider(resource=Resource.create()))
1527

16-
# Since we created a new tracer, the default span processor is gone. We need to
17-
# create a new one using the default OTEL env variables and ad it to the tracer.
18-
span_processor = BatchSpanProcessor(
19-
OTLPSpanExporter(
20-
endpoint=os.getenv('OTEL_EXPORTER_OTLP_ENDPOINT', "http://localhost:4317"),
21-
headers=os.getenv('OTEL_EXPORTER_OTLP_HEADERS'),
22-
insecure=strtobool(os.getenv('OTEL_EXPORTER_OTLP_INSECURE', "false"))
28+
def initialize() -> None:
29+
if not strtobool(getenv("OTEL_SDK_DISABLED", "false")):
30+
if strtobool(getenv("OTEL_ENABLE_BOTO", "false")):
31+
BotocoreInstrumentor().instrument()
32+
if strtobool(getenv("OTEL_ENABLE_LOGGING", "false")):
33+
LoggingInstrumentor().instrument()
34+
35+
36+
def initialize_flask(app):
37+
if not strtobool(getenv("OTEL_SDK_DISABLED", "false")):
38+
if strtobool(getenv("OTEL_ENABLE_FLASK", "false")):
39+
FlaskInstrumentor().instrument_app(app)
40+
41+
42+
def setup_trace_provider():
43+
if not strtobool(getenv("OTEL_SDK_DISABLED", "false")):
44+
# Since we created a new tracer, the default span processor is gone. We need to
45+
# create a new one using the default OTEL env variables and ad it to the tracer.
46+
span_processor = BatchSpanProcessor(
47+
OTLPSpanExporter(
48+
endpoint=getenv('OTEL_EXPORTER_OTLP_ENDPOINT', "http://localhost:4317"),
49+
headers=getenv('OTEL_EXPORTER_OTLP_HEADERS'),
50+
insecure=strtobool(getenv('OTEL_EXPORTER_OTLP_INSECURE', "false"))
51+
)
2352
)
24-
)
25-
trace.get_tracer_provider().add_span_processor(span_processor)
53+
54+
provider = TracerProvider(resource=Resource.create())
55+
provider.add_span_processor(span_processor)
56+
trace.set_tracer_provider(provider)

app/helpers/utils.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from flask import make_response
1616
from flask import request
1717

18+
from app.helpers.otel import strtobool
1819
from app.settings import ALLOWED_DOMAINS_PATTERN
1920
from app.settings import SHORT_ID_ALPHABET
2021
from app.settings import SHORT_ID_SIZE
@@ -124,20 +125,6 @@ def get_url():
124125
return url
125126

126127

127-
def strtobool(value) -> bool:
128-
"""Convert a string representation of truth to true (1) or false (0).
129-
True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
130-
are 'n', 'no', 'f', 'false', 'off', and '0'. Raises ValueError if
131-
'val' is anything else.
132-
"""
133-
value = value.lower()
134-
if value in ('y', 'yes', 't', 'true', 'on', '1'):
135-
return True
136-
if value in ('n', 'no', 'f', 'false', 'off', '0'):
137-
return False
138-
raise ValueError(f"invalid truth value \'{value}\'")
139-
140-
141128
def is_domain_allowed(url):
142129
"""Check if the url contain a domain that is allowed
143130
"""

docker-compose.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,16 @@ services:
7070
- AWS_ACCESS_KEY_ID=dummy123
7171
- AWS_SECRET_ACCESS_KEY=dummy123
7272
- AWS_DEFAULT_REGION=wonderland
73+
74+
otel-collector:
75+
image: otel/opentelemetry-collector-contrib:latest
76+
command: --config otel-local-config.yaml
77+
volumes:
78+
- ./otel-local-config.yaml:/otel-local-config.yaml
79+
ports:
80+
- "4317:4317"
81+
82+
zipkin:
83+
image: openzipkin/zipkin:latest
84+
ports:
85+
- "9411:9411"

logging-cfg-local.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ formatters:
8888
duration: "%(duration)s"
8989
payload: "%(response.json).128s"
9090
message: message
91+
otelSpanID: otelSpanID
92+
otelTraceID: otelTraceID
93+
otelTraceSampled: otelTraceSampled
9194

9295
handlers:
9396
console:

0 commit comments

Comments
 (0)