165 lines
4.6 KiB
YAML
165 lines
4.6 KiB
YAML
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: my-python-app
|
|
namespace: meta
|
|
data:
|
|
main.py: |
|
|
import time
|
|
import random
|
|
from flask import Flask
|
|
from opentelemetry import trace
|
|
from opentelemetry.sdk.trace import TracerProvider
|
|
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
|
from opentelemetry.instrumentation.flask import FlaskInstrumentor
|
|
from opentelemetry.sdk.resources import Resource
|
|
import logging
|
|
from opentelemetry.trace import get_current_span
|
|
SERVICE_NAME = "my-flask-app" # match your OTEL resource name
|
|
|
|
|
|
|
|
trace.set_tracer_provider(
|
|
TracerProvider(resource=Resource.create({"service.name": "my-flask-app"}))
|
|
)
|
|
tracer = trace.get_tracer(__name__)
|
|
span_processor = BatchSpanProcessor(OTLPSpanExporter())
|
|
trace.get_tracer_provider().add_span_processor(span_processor)
|
|
|
|
|
|
|
|
class TraceIdFilter(logging.Filter):
|
|
def filter(self, record):
|
|
span = trace.get_current_span()
|
|
ctx = span.get_span_context()
|
|
if ctx.trace_id != 0:
|
|
record.trace_id = format(ctx.trace_id, "032x")
|
|
record.span_id = format(ctx.span_id, "016x")
|
|
record.service_name = SERVICE_NAME
|
|
else:
|
|
record.trace_id = None
|
|
record.span_id = None
|
|
return True
|
|
|
|
|
|
formatter = logging.Formatter(
|
|
'{"message": "%(message)s", "trace_id": "%(trace_id)s", "span_id": "%(span_id)s", "service_name": "my-flask-app"}'
|
|
)
|
|
handler = logging.StreamHandler()
|
|
handler.setFormatter(formatter)
|
|
handler.addFilter(TraceIdFilter())
|
|
|
|
logger = logging.getLogger("myapp")
|
|
logger.setLevel(logging.INFO)
|
|
logger.addHandler(handler)
|
|
|
|
|
|
resource = Resource(
|
|
attributes={
|
|
"service.name": "python-otel-demo-app", # 👈 choose any name you like
|
|
}
|
|
)
|
|
trace.set_tracer_provider(TracerProvider(resource=resource))
|
|
tracer = trace.get_tracer(__name__)
|
|
|
|
|
|
otlp_exporter = OTLPSpanExporter(
|
|
endpoint="http://otel-collector.meta.svc:4318/v1/traces",
|
|
# insecure=True,
|
|
)
|
|
span_processor = BatchSpanProcessor(otlp_exporter)
|
|
trace.get_tracer_provider().add_span_processor(span_processor)
|
|
|
|
|
|
app = Flask(__name__)
|
|
FlaskInstrumentor().instrument_app(app)
|
|
|
|
|
|
def get_trace_id():
|
|
span = get_current_span()
|
|
if span:
|
|
return span.get_span_context().trace_id
|
|
return None
|
|
|
|
|
|
@app.route("/")
|
|
def root():
|
|
with tracer.start_as_current_span("handle_homepage"):
|
|
logger.info("handling request", extra={"trace_id": get_trace_id()})
|
|
time.sleep(random.random() * 0.05) # simulate request parsing
|
|
fetch_user()
|
|
calculate_recommendations()
|
|
return "Hello from / with traces!"
|
|
|
|
|
|
def fetch_user():
|
|
with tracer.start_as_current_span("fetch_user"):
|
|
time.sleep(random.random() * 0.1) # simulate DB query
|
|
|
|
|
|
def calculate_recommendations():
|
|
with tracer.start_as_current_span("calculate_recommendations"):
|
|
for i in range(2):
|
|
with tracer.start_as_current_span(f"score_item_{i}"):
|
|
time.sleep(random.random())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app.run(host="0.0.0.0", port=5000)
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: python-otel
|
|
namespace: meta
|
|
labels:
|
|
app: python-otel
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: python-otel
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: python-otel
|
|
spec:
|
|
containers:
|
|
- name: python
|
|
image: python
|
|
command: ["/bin/sh", "-c"]
|
|
args:
|
|
- |
|
|
python -m venv .venv && \
|
|
.venv/bin/python -m pip install --upgrade pip && \
|
|
.venv/bin/python -m pip install \
|
|
opentelemetry-sdk \
|
|
opentelemetry-exporter-otlp \
|
|
opentelemetry-instrumentation-flask \
|
|
flask && \
|
|
.venv/bin/python /app/main.py
|
|
volumeMounts:
|
|
- name: app-code
|
|
mountPath: /app
|
|
env:
|
|
- name: OTEL_EXPORTER_OTLP_ENDPOINT
|
|
value: http://otel-collector.meta.svc:4318
|
|
- name: OTEL_EXPORTER_OTLP_INSECURE
|
|
value: "true"
|
|
volumes:
|
|
- name: app-code
|
|
configMap:
|
|
name: my-python-app
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: python-otel
|
|
namespace: meta
|
|
spec:
|
|
selector:
|
|
app: python-otel
|
|
ports:
|
|
- port: 80
|
|
targetPort: 5000
|