Skip to content

Commit 1834c34

Browse files
Merge pull request #16 from mohamad-liyaghi/tracing
Tracing
2 parents 88072ec + b88a4ce commit 1834c34

12 files changed

+106
-1
lines changed

README.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- [Monitoring](#monitoring)
77
- [Node Exporter](#node-exporter)
88
- [Loki](#loki)
9+
- [OpenTelemetry](#opentelemetry)
910
- [Application](#application)
1011
- [User](#user)
1112
- [Active Session](#active-session)
@@ -37,12 +38,14 @@ Vendors can easily register their restaurants, manage their menus, and add produ
3738
<img style="height:30px;" alt="prometheus" src="https://img.shields.io/badge/Prometheus-E6522C.svg?style=flat&logo=prometheus&logoColor=white">
3839
<img style="height:30px;" alt="loki" src="https://img.shields.io/badge/Loki-3B2E5A.svg?style=flat&logo=loki&logoColor=white">
3940
<img style="height:30px;" alt="pytest" src="https://img.shields.io/badge/Pytest-0A9EDC.svg?style=flat&logo=pytest&logoColor=white">
41+
<img style="height:30px;" alt="jaeger" src="https://img.shields.io/badge/Jaeger-FF6F00.svg?style=flat&logo=jaeger&logoColor=white">
42+
<img style="height:30px;" alt="opentelemetry" src="https://img.shields.io/badge/OpenTelemetry-FF6F00.svg?style=flat&logo=opentelemetry&logoColor=white">
4043
</div>
4144
<br>
4245

4346
This project uses <a href="https://docs.djangoproject.com/">Django</a> as the backend framework, with <a href="https://www.postgresql.org/">PostgreSQL</a> and <a href="https://postgis.net/">PostGIS</a> for database management and geographic data handling. The application is containerized using <a href="https://www.docker.com/">Docker</a> and orchestrated with <a href="https://kubernetes.io/">Kubernetes</a>.
4447

45-
For background task processing, <a href="https://docs.celeryq.dev/en/stable/">Celery</a> is used, with <a href="https://redis.io/">Redis</a> serving as both the caching layer and the message broker. Monitoring and logging are handled with <a href="https://grafana.com/">Grafana</a>, <a href="https://prometheus.io/docs/guides/node-exporter/">Node Exporter</a>, <a href="https://grafana.com/docs/loki/latest/getting-started/promtail/">Promtail</a>, and <a href="https://grafana.com/docs/loki/latest/">Loki</a>.
48+
For background task processing, <a href="https://docs.celeryq.dev/en/stable/">Celery</a> is used, with <a href="https://redis.io/">Redis</a> serving as both the caching layer and the message broker. Monitoring and logging are handled with <a href="https://grafana.com/">Grafana</a>, <a href="https://prometheus.io/docs/guides/node-exporter/">Node Exporter</a>, <a href="https://grafana.com/docs/loki/latest/getting-started/promtail/">Promtail</a>, and <a href="https://grafana.com/docs/loki/latest/">Loki</a>, Also <a href="https://www.jaegertracing.io/">Jaeger</a> is used for distributed tracing.
4649

4750
Testing is managed with <a href="https://docs.pytest.org/en/stable/">pytest</a> to ensure code quality and reliability.
4851

@@ -62,6 +65,16 @@ Loki is a log aggregation system that is used to store and query logs from the a
6265
Here is an example of the Loki dashboard in Grafana:
6366
<img src="./images/loki.png" alt="Loki"/>
6467

68+
### OpenTelemetry
69+
This Project uses OpenTelemetry as its distributed tracing system. Jaeger is used to collect, store, and visualize traces from the application. It provides insights into the performance of the application and helps identify bottlenecks and issues.
70+
71+
Here is an example of the Jaeger dashboard:
72+
<img src="./images/jaeger.png" alt="Jaeger"/>
73+
74+
Here is an example of the metrics in grafana:
75+
<img src="./images/opentelemetry_metrics.png" alt="Open Telemetry"/>
76+
77+
6578
## Application
6679
To make the application easier to understand, we have divided it into several components. Each component is responsible for a specific part of the application. The components are as follows:
6780

config/settings/core.py

+4
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@
109109
"format": "{levelname} {message}",
110110
"style": "{",
111111
},
112+
"trace_formatter": {
113+
"format": "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s] [%(funcName)s] %(message)s", # noqa
114+
"datefmt": "%Y-%m-%d %H:%M:%S",
115+
},
112116
},
113117
"handlers": {
114118
"file_info": {

docker-compose.base.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,16 @@ services:
145145
volumes:
146146
- food_anywhere_grafana_data:/var/lib/grafana
147147

148+
jaeger:
149+
image: jaegertracing/all-in-one:1.32
150+
container_name: food-anywhere-jaeger
151+
ports:
152+
- 16686:16686
153+
networks:
154+
- main
155+
volumes:
156+
- food_anywhere_jaeger_data:/var/lib/jaeger
157+
148158

149159
networks:
150160
main:

docker-compose.prod.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ services:
6060
extends:
6161
service: prometheus
6262
file: docker-compose.base.yaml
63+
jaeger:
64+
extends:
65+
service: jaeger
66+
file: docker-compose.base.yaml
6367

6468
networks:
6569
main:
@@ -69,3 +73,4 @@ volumes:
6973
food_anywhere_grafana_data:
7074
food_anywhere_node_exporter_data:
7175
food_anywhere_prometheus_data:
76+
food_anywhere_jaeger_data:

docker-compose.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ services:
7070
extends:
7171
service: prometheus
7272
file: docker-compose.base.yaml
73+
jaeger:
74+
extends:
75+
service: jaeger
76+
file: docker-compose.base.yaml
7377

7478
networks:
7579
main:
@@ -79,3 +83,4 @@ volumes:
7983
food_anywhere_grafana_data:
8084
food_anywhere_node_exporter_data:
8185
food_anywhere_prometheus_data:
86+
food_anywhere_jaeger_data:

envs/.env.local

+4
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,9 @@ EMAIL_FROM='[email protected]'
2323
CELERY_BROKER_URL=redis://redis:6379/1
2424
CELERY_RESULT_BACKEND=redis://redis:6379/1
2525

26+
# Jaeger
27+
TRACING_HOST="jaeger"
28+
TRACING_PORT=6831
29+
2630
# Cache Keys
2731
CART_CACHE_KEY='cart:{user_id}:{product_id}'

envs/.env.prod

+4
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,9 @@ EMAIL_FROM='[email protected]'
2323
CELERY_BROKER_URL=redis://redis:6379/1
2424
CELERY_RESULT_BACKEND=redis://redis:6379/1
2525

26+
# Jaeger
27+
TRACING_HOST="jaeger"
28+
TRACING_PORT=6831
29+
2630
# Cache Keys
2731
CART_CACHE_KEY='cart:{user_id}:{product_id}'

images/jaeger.png

63.2 KB
Loading

images/opentelemetry_metrics.png

222 KB
Loading

kubernetes/jaeger.yaml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: food-anywhere-jaeger-dp
5+
labels:
6+
app: food-anywhere-jaeger
7+
spec:
8+
replicas: 1
9+
selector:
10+
matchLabels:
11+
app: food-anywhere-jaeger
12+
template:
13+
metadata:
14+
labels:
15+
app: food-anywhere-jaeger
16+
spec:
17+
containers:
18+
- name: jaeger
19+
image: jaegertracing/all-in-one:1.32
20+
ports:
21+
- containerPort: 16686
22+
---
23+
apiVersion: v1
24+
kind: Service
25+
metadata:
26+
name: jaeger
27+
spec:
28+
selector:
29+
app: food-anywhere-jaeger
30+
ports:
31+
- protocol: TCP
32+
port: 16686
33+
targetPort: 16686

manage.py

+19
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,30 @@
22
"""Django's command-line utility for administrative tasks."""
33
import os
44
import sys
5+
from opentelemetry.exporter.jaeger.thrift import JaegerExporter
6+
from opentelemetry.instrumentation.django import DjangoInstrumentor
7+
from opentelemetry.instrumentation.logging import LoggingInstrumentor
8+
from opentelemetry.sdk.trace import TracerProvider
9+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
10+
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
11+
from opentelemetry import trace
512

613

714
def main():
815
"""Run administrative tasks."""
916
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
17+
18+
DjangoInstrumentor().instrument()
19+
LoggingInstrumentor().instrument()
20+
21+
jaeger_exporter = JaegerExporter(
22+
agent_host_name=os.getenv("TRACING_HOST"),
23+
agent_port=int(os.getenv("TRACING_PORT")),
24+
)
25+
trace.set_tracer_provider(TracerProvider(resource=Resource.create({SERVICE_NAME: "food-anywhere-backend"})))
26+
span_processor = BatchSpanProcessor(jaeger_exporter)
27+
trace.get_tracer_provider().add_span_processor(span_processor)
28+
1029
try:
1130
from django.core.management import execute_from_command_line
1231
except ImportError as exc:

requirements.txt

+8
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ jsonschema-specifications==2023.12.1
3131
kombu==5.3.7
3232
mypy-extensions==1.0.0
3333
nodeenv==1.9.1
34+
opentelemetry-api==1.10.0
35+
opentelemetry-exporter-jaeger==1.10.0
36+
opentelemetry-instrumentation==0.29b0
37+
opentelemetry-instrumentation-django==0.29b0
38+
opentelemetry-instrumentation-logging==0.29b0
39+
opentelemetry-instrumentation-requests==0.29b0
40+
opentelemetry-sdk==1.10.0
3441
packaging==24.1
3542
pathspec==0.12.1
3643
platformdirs==4.2.2
@@ -48,6 +55,7 @@ python-decouple==3.8
4855
PyYAML==6.0.1
4956
redis==5.0.8
5057
referencing==0.35.1
58+
requests==2.32.3
5159
rpds-py==0.19.1
5260
six==1.16.0
5361
sqlparse==0.5.1

0 commit comments

Comments
 (0)