This article is available in French.
1. Le modèle de données #
Un log enrichi de contexte.
LogRecord #
OpenTelemetry ne crée pas un nouveau framework de logs : il définit un modèle de données commun et des ponts vers les bibliothèques existantes. Un enregistrement de log contient :
| Champ | Contenu |
|---|---|
| Timestamp / ObservedTimestamp | moment de l'événement / moment de sa collecte |
| SeverityNumber / SeverityText | 1-24 normalisé (9 = INFO, 13 = WARN, 17 = ERROR) / texte d'origine |
| Body | le message (texte ou structure) |
| Attributes | contexte (semconv : code.function.name, exception.type…) |
| TraceId / SpanId / TraceFlags | la trace et le span actifs au moment du log |
| Resource | le service émetteur, identique à ses traces et métriques |
| EventName | nom d'un événement structuré (logs « événements ») |
Pourquoi c'est utile #
- Un format unique, quel que soit le langage ou la bibliothèque de logs.
- La corrélation automatique : chaque log porte l'identifiant de la trace en cours.
- La même ressource que les autres signaux : filtrer logs, traces et métriques d'un même pod en un clic.
- Le même transport (OTLP) et le même Collector que les autres signaux.
2. Depuis l'application #
Appenders et Logs Bridge API.
Le principe #
La Logs Bridge API n'est pas destinée à être appelée par votre code : elle sert aux auteurs d'appenders (ou handlers) qui branchent Logback, Log4j, java.util.logging, le module logging de Python, Serilog ou Winston sur le SDK. Vous continuez à écrire logger.info(...).
Exemples #
# Python : avec l'auto-instrumentation
export OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
export OTEL_LOGS_EXPORTER=otlp
opentelemetry-instrument python app.py
# Java : l'agent capture Logback et Log4j par défaut
java -javaagent:opentelemetry-javaagent.jar -Dotel.logs.exporter=otlp -jar app.jar# Python : configuration manuelle du handler
import logging
from opentelemetry._logs import set_logger_provider
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
provider = LoggerProvider(resource=resource)
provider.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter()))
set_logger_provider(provider)
logging.getLogger().addHandler(LoggingHandler(level=logging.INFO, logger_provider=provider))Bonne Pratique : Même sans exporter les logs en OTLP, ajouteztrace_idetspan_idà vos logs JSON : la corrélation fonctionnera aussi avec une collecte par fichier.
3. Depuis les fichiers #
Le receiver filelog du Collector.
Parser des logs JSON #
receivers:
filelog:
include: [/var/log/app/*.log]
start_at: end
storage: file_storage # reprendre là où on s'était arrêté
operators:
- type: json_parser
timestamp: { parse_from: attributes.time, layout: "%Y-%m-%dT%H:%M:%S%z" }
severity: { parse_from: attributes.level }
- type: trace_parser
trace_id: { parse_from: attributes.trace_id }
span_id: { parse_from: attributes.span_id }
- type: move
from: attributes.message
to: bodyLogs Kubernetes #
Sur Kubernetes, un Collector en DaemonSet lit /var/log/pods/*/*/*.log, utilise l'opérateur container pour décoder le format du runtime, puis le processeur k8sattributes pour ajouter pod, namespace, déploiement et labels. Le chart Helm officiel l'active avec le préréglage logsCollection.
Erreur Courante : Ne collectez pas deux fois les mêmes logs (appender OTLP et fichier) : volume doublé et doublons dans le backend. Choisissez une voie par application.
4. Traiter et interroger #
Réduire, masquer, retrouver.
Dans le Collector #
processors:
filter/debug:
logs:
log_record: ['severity_number < SEVERITY_NUMBER_INFO'] # supprimer DEBUG et TRACE
transform/pii:
log_statements:
- context: log
statements:
- replace_pattern(body, "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+", "***@***")Dans Loki #
{service_name="checkout"} | severity_text="ERROR"
{service_name="checkout"} | trace_id="4bf92f3577b34da6a3ce929d0e0e4736"
sum by (service_name) (count_over_time({deployment_environment_name="production"} | severity_text="ERROR" [5m]))My progress
Sign in to track your progress and take notes. Sign in
Recommended Articles
Understanding the concept of score
The concept of score allows Elasticsearch to rank your documents by relevance during a search.
Understanding the Elastic Common Schema (ECS)
As always in our consulting engagements, we recommend that companies harmonise and standardise: k...
License consumption types
Understand the evolution of billing in Dynatrace: the difference between the old licensing model ...
Grafana Alloy: The importance of Self-Monitoring
Discover why and how to configure Grafana Alloy so that it monitors itself, collecting its own lo...
Grafana Alloy: Understanding and exploiting the User Interface (UI)
Discover how to enable, secure, and use Grafana Alloy's built-in web interface to visualize your ...
Grafana Alloy: Introduction and Architecture
Discover the fundamental concepts of Grafana Alloy, the transition from the static Agent to Alloy...
Grafana Alloy: Syntax and Configuration (Alloy Language: River)
As part of a Grafana training or observability training, master the declarative syntax of Grafana...
Grafana Alloy: Metrics Collection (Prometheus & Ecosystem)
Learn how to configure Grafana Alloy to collect, transform, and forward metrics using the Prometh...
Grafana Alloy: Log Management with Loki
Discover how to configure Grafana Alloy to read log files, journald, or network streams, process ...