Pour suivre la santé de votre application il est primordiale de suivre les métriques les plus importantes. J'ai du implémenter ce mécanisme le mois dernier et je vais vous faire un retour sur son intégration dans Datadog puis Signoz.
Je vais utiliser un Application Performance Monitoring (APM) qui permet d'obtenir les erreurs HTTP, temps de réponse ou encore la consommation de ressource. On remonte les traces sur cet APM.
J'utiliserais également la remonté des logs qui est une autre fonctionnalité de Datadog et Signoz
Il y a 2 manières de configurer l'export des données :
- via la modification du code de votre application (mode manuel ou code base)
- via un outil qui wrappe le démarrage de l'application, sans modifier le code de prod (mode automatique ou no code)
On peut également choisir d'utiliser un middleware entre l'application et le serveur APM. Ce collecteur permet d'affiner un peu plus ce qui va être remonté dans l'outil, il portera la configuration ici au lieu dans l'application.
Après la lecture de cet article il vous restera à choisir l'observabilité qui vous convient le mieux.
Datadog
C'est le leader du marché pour mettre en place de l'observabilité, une solution performante mais aussi assez onéreuse. Une fois la période de 15 jours terminée, l'accès à l'APM et le log explorer n'est plus possible sans payer.
Datadog recommande de passer par leur agent (un service qui tourne à côté de votre application) qui est un intermédiaire entre l'application et le serveur datadog : je suis parti sur cette solution que je vais vous présenter.
L'avantage de cette solution est de passer par une seule librairie
ddtrace
Il suffit d'aller préfixer l'exécution de votre serveur comme ceci
ddtrace-run uvicorn "src.main:app" --host=0.0.0.0 --port=8000
Comme nous passons par l'agent de Datadog il faut le lancer dans un container hérité de
gcr.io/datadoghq/agent:latest
Pour ma part j'utilise un sidecar sous GCP mais vous êtes libre de le faire autrement comme via un service docker-compose. Il faut penser à appliquer ces variables d'env
DD_SERVICE="myapp"
DD_ENV="PROD"
DD_SERVERLESS_LOG_PATH="/datadog/app.log"
DD_SITE="datadoghq.eu"
DD_API_KEY=<YOUR_DATADOG_API_KEY>
Vous avez surement remarqué que j'indique à Datadog où se situe les log puisque pour la rémonté des logs il faut mettre en place une écriture des logs dans un fichier qui sera configuré dans un handler de la librarie
logging
Copier le code
1 2 3 4 5 6 7 "file": { "level": self.verbose_level, "class": "logging.handlers.RotatingFileHandler", "filename": "/datadog/app.log", "maxBytes": 50 * 1024 * 1024, "backupCount": 3, }
Il reste à configurer ce volume /datadog (ou un autre nom à votre convenance) qui sera partagé entre votre applicaton et l'agent Datadog.
Voici un exemple complet de configuration de mon agent sous GCP
Copier le code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 - name: datadog-agent image: gcr.io/datadoghq/agent:latest command: ["/bin/sh", "-c"] args: - >- for i in $(seq 1 150); do wget -q -O- http://127.0.0.1:8000/ >/dev/null 2>&1 && break; sleep 2; done; exec agent run env: - name: DD_SERVICE value: "myapp" - name: DD_ENV value: "PROD" - name: DD_SERVERLESS_LOG_PATH value: "/datadog/app.log" - name: DD_SITE value: "datadoghq.eu" - name: DD_API_KEY value: ${DATADOG_API_KEY} volumeMounts: - name: datadog mountPath: /datadog volumes: - name: datadog emptyDir: { }

Signoz
C'est une alternative open source à Datadog que j'avais envie de tester. En effet comme vu aupravant Datadog sur sa version free ne permet pas de tester son APM (après avoir terminé la version d'essai).
Pour simplifier ma configuration je suis parti sur un accès direct à l'exporter de signoz sans passer par l'exporter OTLP proposé par open telemetry (la solution évoquée avec Datadog juste avant reposait sur un exporter OTLP que Datadog nomme agent).

L'approche no code
On va commencer par installer la librairie
opentelemetry-distro
Il suffit d'aller préfixer l'exécution de votre serveur comme ceci
opentelemetry-instrument uvicorn "src.main:app" --host=0.0.0.0 --port=8000
Dans mon
Dockerfile
RUN opentelemetry-bootstrap --action=install
La seconde librairie
opentelemetry-exporter-otlp
OTEL_EXPORTER_OTLP_PROTOCOL=grpc
OTEL_EXPORTER_OTLP_ENDPOINT=ngest.eu.signoz.cloud:443
OTEL_EXPORTER_OTLP_HEADERS=signoz-access-token=${SIGNOZ_TOKEN}
OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED="true
OTEL_RESOURCE_ATTRIBUTES="deployment.environment=prod,service.version=${CI_COMMIT_SHA}"
OTEL_SERVICE_NAME=myapp

Un point qui n'est pas précisé dans la documentation de signoz c'est que la collecte des logs nécessite un handler particulier. Contrairement au trace qui utilise le monkey patching, pour les logs avec la librairie
logging
Vous devrez ajouter ce handler dans votre configuration d'application
Copier le code
1 2 3 4 "otel": { "class": "opentelemetry.sdk._logs.LoggingHandler", "level": "INFO", },

L'approche code base
Si vous vous êtes intéressé à mettre en place de l'observabilité dans FastApi vous êtes surement tombé sur cette librairie
opentelemetry-instrumentation-fastapi
C'est un outil qui récolte les informations (trace) dans les profondeurs du framework. Il se comporte comme un middleware et doit être appelé après l'initialisation du framework.
Copier le code
1 2 app = FastAPI() FastAPIInstrumentor.instrument_app(app)
Comme vous le remarquez il est nécessaire de modifier son code de production.
Avec cette librairie on a mis en place la collecte des informations mais cela n'est pas suffisant. Il faut également mettre en place :
- la collecte des logs avec
opentelemetry-instrumentation-logging
- la mécanique de l'observabilité avec
opentelemetry-sdk
- l'exporteur de données (trace + log) avec
opentelemetry-exporter-otlp
Je ne vais pas rentrer dans le détail de son implémentation car cela est fastidieux. Il faut refaire la mécanique de
opentelemetry-distro
Conclusion
La simplicité de datadog, qui ne nécessite pas autant de paramètres que signoz, le rend plus vite configurable.
Le choix entre une instrumentation manuelle (modification du code de prod) ou automatique (via un wrapper de lib) dépend de votre contexte. Le mode automatique est idéal, si vous n'avez pas la main sur la gestion du serveur d'application ou si vous ne voulez pas que votre instrumentation "pollue" le code métier par exemple.
Le mode manuel est privilégié si vous voulez garder la main sur ce que vous voulez remonté et maitriser la mécanique de récolte d'information plus finement.
Et voila 2 techiques pour mettre en place une observabilité sur votre application python.