Exemple d'auto-instrumentation
Cette page montre comment utiliser l’auto-instrumentation Python dans
OpenTelemetry. L’exemple est basé sur un exemple OpenTracing. Vous pouvez
télécharger ou voir les fichiers sources utilisés dans cette page depuis le
dépôt opentelemetry-python
.
Cet exemple utilise trois scripts différents. La principale différence entre eux est la manière dont ils sont instrumentés :
server_manual.py
est instrumenté manuellement.server_automatic.py
est instrumenté automatiquement.server_programmatic.py
est instrumenté programmatiquement.
L’instrumentation programmatique est un type d’instrumentation qui nécessite un minimum de code d’instrumentation à ajouter à l’application. Seules quelques bibliothèques d’instrumentation offrent des capacités supplémentaires qui vous donnent un plus grand contrôle sur le processus d’instrumentation lorsqu’elles sont utilisées programmatiquement.
Exécutez le premier script sans l’agent d’instrumentation automatique et le second avec l’agent. Ils devraient tous deux produire les mêmes résultats, démontrant que l’agent d’instrumentation automatique fait exactement la même chose que l’instrumentation manuelle.
L’instrumentation automatique utilise le monkey-patching pour réécrire dynamiquement les méthodes et les classes à l’exécution via des bibliothèques d’instrumentation. Cela réduit la quantité de travail nécessaire pour intégrer OpenTelemetry dans le code de votre application. Ci-dessous, vous verrez la différence entre une route Flask instrumentée manuellement, automatiquement et programmatiquement.
Serveur instrumenté manuellement
server_manual.py
@app.route("/server_request")
def server_request():
with tracer.start_as_current_span(
"server_request",
context=extract(request.headers),
kind=trace.SpanKind.SERVER,
attributes=collect_request_attributes(request.environ),
):
print(request.args.get("param"))
return "served"
Serveur instrumenté automatiquement
server_automatic.py
@app.route("/server_request")
def server_request():
print(request.args.get("param"))
return "served"
Serveur instrumenté programmatiquement
server_programmatic.py
instrumentor = FlaskInstrumentor()
app = Flask(__name__)
instrumentor.instrument_app(app)
# instrumentor.instrument_app(app, excluded_urls="/server_request") {#instrumentorinstrument_appapp-excluded_urlsserver_request}
@app.route("/server_request")
def server_request():
print(request.args.get("param"))
return "served"
Préparation
Exécutez l’exemple suivant dans un environnement virtuel séparé. Exécutez les commandes suivantes pour préparer l’auto-instrumentation :
mkdir auto_instrumentation
cd auto_instrumentation
python -m venv venv
source ./venv/bin/activate
Installation
Exécutez les commandes suivantes pour installer les paquets appropriés. Le
paquet opentelemetry-distro
dépend de quelques autres, comme
opentelemetry-sdk
pour l’instrumentation personnalisée de votre propre code et
opentelemetry-instrumentation
qui fournit plusieurs commandes qui aident à
instrumenter automatiquement un programme.
pip install opentelemetry-distro
pip install flask requests
Exécutez la commande opentelemetry-bootstrap
:
opentelemetry-bootstrap -a install
Les exemples qui suivent envoient les résultats de l’instrumentation à la console. Apprenez-en plus sur l’installation et la configuration de la Distribution OpenTelemetry pour envoyer la télémétrie à d’autres destinations, comme un Collecteur OpenTelemetry.
Note: Pour utiliser l’instrumentation automatique via
opentelemetry-instrument
, vous devez la configurer via des variables d’environnement ou la ligne de commande. L’agent crée un pipeline de télémétrie qui ne peut être modifié que par ces moyens. Si vous avez besoin de plus de personnalisation pour vos pipelines de télémétrie, alors vous devez renoncer à l’agent et importer le SDK OpenTelemetry et les bibliothèques d’instrumentation dans votre code et les configurer dans votre code. Vous pouvez également étendre l’instrumentation automatique en important l’API OpenTelemetry. Pour plus de détails, voir la référence de l’API.
Exécution
Cette section vous guide à travers le processus manuel d’instrumentation d’un serveur ainsi que le processus d’exécution d’un serveur instrumenté automatiquement.
Exécuter le serveur instrumenté manuellement
Exécutez le serveur dans deux consoles séparées, une pour chacun des scripts à exécuter qui composent cet exemple :
source ./venv/bin/activate
python server_manual.py
source ./venv/bin/activate
python client.py testing
La console exécutant server_manual.py
affichera les spans générés par
l’instrumentation au format JSON. Les spans devraient ressembler à l’exemple
suivant :
{
"name": "server_request",
"context": {
"trace_id": "0xfa002aad260b5f7110db674a9ddfcd23",
"span_id": "0x8b8bbaf3ca9c5131",
"trace_state": "{}"
},
"kind": "SpanKind.SERVER",
"parent_id": null,
"start_time": "2020-04-30T17:28:57.886397Z",
"end_time": "2020-04-30T17:28:57.886490Z",
"status": {
"status_code": "OK"
},
"attributes": {
"http.method": "GET",
"http.server_name": "127.0.0.1",
"http.scheme": "http",
"host.port": 8082,
"http.host": "localhost:8082",
"http.target": "/server_request?param=testing",
"net.peer.ip": "127.0.0.1",
"net.peer.port": 52872,
"http.flavor": "1.1"
},
"events": [],
"links": [],
"resource": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "0.16b1"
}
}
Exécuter le serveur instrumenté automatiquement
Arrêtez l’exécution de server_manual.py
en appuyant sur Control+C
et exécutez la commande suivante à la place :
opentelemetry-instrument --traces_exporter console --metrics_exporter none --logs_exporter none python server_automatic.py
Dans la console où vous avez précédemment exécuté client.py
, exécutez à
nouveau la commande suivante :
python client.py testing
La console exécutant server_automatic.py
affichera les spans générés par
l’instrumentation au format JSON. Les spans devraient ressembler à l’exemple
suivant :
{
"name": "server_request",
"context": {
"trace_id": "0x9f528e0b76189f539d9c21b1a7a2fc24",
"span_id": "0xd79760685cd4c269",
"trace_state": "{}"
},
"kind": "SpanKind.SERVER",
"parent_id": "0xb4fb7eee22ef78e4",
"start_time": "2020-04-30T17:10:02.400604Z",
"end_time": "2020-04-30T17:10:02.401858Z",
"status": {
"status_code": "OK"
},
"attributes": {
"http.method": "GET",
"http.server_name": "127.0.0.1",
"http.scheme": "http",
"host.port": 8082,
"http.host": "localhost:8082",
"http.target": "/server_request?param=testing",
"net.peer.ip": "127.0.0.1",
"net.peer.port": 48240,
"http.flavor": "1.1",
"http.route": "/server_request",
"http.status_text": "OK",
"http.status_code": 200
},
"events": [],
"links": [],
"resource": {
"telemetry.sdk.language": "python",
"telemetry.sdk.name": "opentelemetry",
"telemetry.sdk.version": "0.16b1",
"service.name": ""
}
}
Vous pouvez voir que les deux sorties sont les mêmes car l’instrumentation automatique fait exactement ce que fait l’instrumentation manuelle.
Exécuter le serveur instrumenté programmatiquement
Il est également possible d’utiliser les bibliothèques d’instrumentation (telles
que opentelemetry-instrumentation-flask
) par elles-mêmes, ce qui peut avoir
l’avantage de personnaliser les options. Cependant, en choisissant de le faire,
vous renoncez à utiliser l’auto-instrumentation en démarrant votre application
avec opentelemetry-instrument
car elles sont mutuellement exclusives.
Exécutez le serveur comme vous le feriez pour l’instrumentation manuelle, dans deux consoles séparées, une pour exécuter chacun des scripts qui composent cet exemple :
source ./venv/bin/activate
python server_programmatic.py
source ./venv/bin/activate
python client.py testing
Les résultats devraient être les mêmes que lors de l’exécution avec l’instrumentation manuelle.
Utilisation des fonctionnalités d’instrumentation programmatique
Certaines bibliothèques d’instrumentation incluent des fonctionnalités qui permettent un contrôle plus précis lors de l’instrumentation programmatique, la bibliothèque d’instrumentation pour Flask en est une.
Cet exemple a une ligne commentée, changez-la comme ceci :
# instrumentor.instrument_app(app) {#instrumentorinstrument_appapp}
instrumentor.instrument_app(app, excluded_urls="/server_request")
Après avoir réexécuté l’exemple, aucune instrumentation ne devrait apparaître
côté serveur. Ceci est dû à l’option excluded_urls
passée à instrument_app
qui empêche effectivement la fonction server_request
d’être instrumentée car
son URL correspond à l’expression régulière passée à excluded_urls
.
Instrumentation pendant le débogage
Le mode de débogage peut être activé dans l’application Flask comme ceci :
if __name__ == "__main__":
app.run(port=8082, debug=True)
Le mode de débogage peut interrompre l’instrumentation car il active un
rechargeur. Pour exécuter l’instrumentation lorsque le mode de débogage est
activé, définissez l’option use_reloader
sur False
:
if __name__ == "__main__":
app.run(port=8082, debug=True, use_reloader=False)
Configuration
L’auto-instrumentation peut consommer la configuration à partir des variables d’environnement.
Capturer les en-têtes de requête et de réponse HTTP
Vous pouvez capturer les en-têtes HTTP prédéfinis en tant qu’attributs de span, conformément à la convention sémantique.
Pour définir les en-têtes HTTP que vous souhaitez capturer, fournissez une liste
de noms d’en-têtes HTTP séparés par des virgules via les variables
d’environnement OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST
et
OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE
, par exemple :
export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_REQUEST="Accept-Encoding,User-Agent,Referer"
export OTEL_INSTRUMENTATION_HTTP_CAPTURE_HEADERS_SERVER_RESPONSE="Last-Modified,Content-Type"
opentelemetry-instrument --traces_exporter console --metrics_exporter none --logs_exporter none python app.py
Ces options de configuration sont prises en charge par les instrumentations HTTP suivantes :
- Django
- Falcon
- FastAPI
- Pyramid
- Starlette
- Tornado
- WSGI
Si ces en-têtes sont disponibles, ils seront inclus dans votre span :
{
"attributes": {
"http.request.header.user-agent": [
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)"
],
"http.request.header.accept_encoding": ["gzip, deflate, br"],
"http.response.header.last_modified": ["2022-04-20 17:07:13.075765"],
"http.response.header.content_type": ["text/html; charset=utf-8"]
}
}
Feedback
Cette page est-elle utile?
Thank you. Your feedback is appreciated!
Please let us know how we can improve this page. Your feedback is appreciated!