Ao depurar sistemas distribuídos, é comum iniciar a investigação por um trace e precisar localizar as entradas de log correspondentes, ou vice-versa. Ao injetar trace IDs e span IDs do OpenTelemetry nos logs da aplicação, você navega diretamente de um span de trace para as linhas exatas de log geradas durante aquela operação. Isso acelera o diagnóstico de falhas e a análise de desempenho.
Este tópico aborda a correlação entre traces e logs para Java, Go e Python. Java e Python permitem injeção automática por meio da auto-instrumentação do OpenTelemetry. Em Go, injete os valores manualmente.
Pré-requisitos
Antes de começar, verifique se você possui:
Aplicação monitorada pelo ARMS com rastreamento OpenTelemetry ativado
Agente Java, SDK do Go ou SDK do Python do OpenTelemetry instalado, conforme a linguagem utilizada
Como funciona
O OpenTelemetry utiliza o Mapped Diagnostic Context (MDC) para injetar trace_id e span_id em cada entrada de log produzida dentro de um span ativo. Com a auto-instrumentação (Java, Python), o agente realiza essa injeção automaticamente, sem necessidade de alterações no código. Sem a auto-instrumentação (Go), extraia esses valores do contexto do span e anexe-os aos campos de log manualmente.
Depois que o contexto de trace aparecer nos logs, pesquise pelo trace ID no Simple Log Service para localizar todas as entradas de log associadas a uma solicitação específica.
Java
Frameworks de log compatíveis
|
Framework de log |
Suporte à auto-instrumentação |
Dependência para instrumentação manual |
|
Log4j 1 |
1,2+ |
N/A |
|
Log4j 2 |
2,7+ |
|
|
Logback |
1,0+ |
Para mais detalhes sobre o funcionamento da auto-instrumentação de MDC, consulte Auto-instrumentação de Logger MDC.
Configure o Log4j 2
-
Adicione a dependência do OpenTelemetry Log4j 2 ao arquivo
pom.xml. SubstituaOPENTELEMETRY_VERSIONpela versão mais recente.<dependencies> <dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-log4j-context-data-2.17-autoconfigure</artifactId> <version>OPENTELEMETRY_VERSION</version> <scope>runtime</scope> </dependency> </dependencies> -
Inclua
%X{trace_id}e%X{span_id}no padrão definido emlog4j2.xml. A sintaxe%X{key}lê valores do MDC, preenchidos automaticamente pelo agente OpenTelemetry quando há um span ativo.<?xml version="1.0" encoding="UTF-8"?> <Configuration> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} trace_id=%X{trace_id} span_id=%X{span_id} trace_flags=%X{trace_flags} - %msg%n"/> </Console> </Appenders> <Loggers> <Root> <AppenderRef ref="Console" level="All"/> </Root> </Loggers> </Configuration>
Configure o Logback
-
Adicione a dependência do OpenTelemetry Logback ao arquivo
pom.xml. SubstituaOPENTELEMETRY_VERSIONpela versão mais recente.<dependencies> <dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-logback-mdc-1.0</artifactId> <version>OPENTELEMETRY_VERSION</version> </dependency> </dependencies> -
Atualize o arquivo
logback.xmlpara incluir%X{trace_id}e%X{span_id}no padrão e envolva o appender comOpenTelemetryAppender.<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} trace_id=%X{trace_id} span_id=%X{span_id} trace_flags=%X{trace_flags} %msg%n</pattern> </encoder> </appender> <!-- Wrap your logging appender with OpenTelemetryAppender --> <appender name="OTEL" class="io.opentelemetry.instrumentation.logback.mdc.v1_0.OpenTelemetryAppender"> <appender-ref ref="CONSOLE"/> </appender> <!-- Use the wrapped "OTEL" appender instead of the original "CONSOLE" one --> <root level="INFO"> <appender-ref ref="OTEL"/> </root> </configuration>
Configure o Logback no Spring Boot
O Spring Boot utiliza o Logback por padrão. Em vez de editar XML, adicione uma única linha ao arquivo application.properties:
logging.pattern.level=trace_id=%mdc{trace_id} span_id=%mdc{span_id} %5p
Exemplo de saída:
2024-06-26 10:56:31.200 trace_id=8f7ebd8a73f9a8f50e6a00a87a20952a span_id=1b08f18b8858bb9a INFO 53724 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-06-26 10:56:31.201 trace_id=8f7ebd8a73f9a8f50e6a00a87a20952a span_id=1b08f18b8858bb9a INFO 53724 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2024-06-26 10:56:31.209 trace_id=8f7ebd8a73f9a8f50e6a00a87a20952a span_id=1b08f18b8858bb9a INFO 53724 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 8 ms
2024-06-26 10:56:31.296 trace_id=8f7ebd8a73f9a8f50e6a00a87a20952a span_id=5743699405074f4e INFO 53724 --- [nio-8081-exec-1] com.example.httpserver.ot.OTServer : hello world
Go
O OpenTelemetry em Go não oferece suporte à injeção automática de contexto de trace nos logs. Extraia os trace IDs e span IDs do contexto do span manualmente.
Configure o logrus
-
Importe os pacotes necessários.
import ( oteltrace "go.opentelemetry.io/otel/trace" "github.com/sirupsen/logrus" ) -
Crie uma função auxiliar para extrair trace IDs e span IDs de um span e retorná-los como campos do logrus.
func LogrusFields(span oteltrace.Span) logrus.Fields { return logrus.Fields{ "trace_id": span.SpanContext().TraceID().String(), "span_id": span.SpanContext().SpanID().String(), } } -
Use a função auxiliar após criar um span para registrar logs com o contexto de trace.
_, span := tracer.Start(ctx, "spanName") defer span.End() logEntry := logrus.WithFields(LogrusFields(span)) logEntry.Info("This is an info message with trace and span ID")
Python
O OpenTelemetry em Python permite a injeção automática de contexto de trace nos logs. Para mais detalhes, consulte Instrumentação de Logging do OpenTelemetry.
Configure o módulo de logging
-
Ative a injeção automática definindo a seguinte variável de ambiente:
export OTEL_PYTHON_LOG_CORRELATION=true -
Adicione
%(otelTraceID)se%(otelSpanID)sao formato do log. O OpenTelemetry substitui esses placeholders pelo trace ID e span ID reais durante a execução.Exemplo de formato de log:
formatter = logging.Formatter( '%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s resource.service.name=%(otelServiceName)s] - %(message)s' )Exemplo de saída:
2024-06-25 10:00:55,494 INFO [app] [test.py:80] [trace_id=70561de6a164ac991bfff2281b7f**** span_id=4b7f3c798460**** resource.service.name=ot-python-demo] - hello world
Exemplo de ponta a ponta com Flask
Este exemplo apresenta uma configuração completa: crie uma aplicação Flask, instrumente-a com OpenTelemetry e verifique se os trace IDs aparecem nos logs.
Pré-requisitos:
Python e pip instalados (este exemplo utiliza Python 3.12.4 e pip 24.1.1)
Etapa 1: Instale as dependências
Instale o Flask:
pip3 install flask
Instale a distribuição do OpenTelemetry e as bibliotecas de auto-instrumentação:
pip3 install opentelemetry-distro \
opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
Etapa 2: Crie a aplicação
Salve o código abaixo como test.py:
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask
app = Flask(__name__)
# Create a formatter that includes OpenTelemetry trace context
formatter = logging.Formatter(
'%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s resource.service.name=%(otelServiceName)s] - %(message)s'
)
# Write logs to a file with rotation
# Replace <log-file-path> with the actual path, for example: /var/log/app.log
file_handler = RotatingFileHandler('<log-file-path>', maxBytes=10000, backupCount=1)
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
app.logger.addHandler(file_handler)
@app.route('/')
def hello_world():
app.logger.info('Hello World!!!')
return 'Hello, World!'
if __name__ == '__main__':
app.run()
Etapa 3: Execute a aplicação com instrumentação OpenTelemetry
Defina as variáveis de ambiente e inicie a aplicação com o wrapper de auto-instrumentação do OpenTelemetry:
export OTEL_PYTHON_LOG_CORRELATION=true
export OTEL_SERVICE_NAME=ot-python-demo
export OTEL_TRACES_EXPORTER=otlp
export OTEL_METRICS_EXPORTER=none
# Replace test.py with your actual filename if different
opentelemetry-instrument python3 test.py
Se a aplicação iniciar com sucesso, uma saída semelhante à seguinte será exibida:
* Running on http://127.0.**.**:5000
Etapa 4: Verifique a saída do log
Envie uma solicitação para a aplicação e verifique o arquivo de log. Cada entrada agora inclui o trace ID e o span ID:
2024-06-25 10:00:55,494 INFO [app] [test.py:80] [trace_id=70561de6a164ac991bfff2281b7f**** span_id=4b7f3c798460**** resource.service.name=ot-python-demo] - hello world
Próximos passos
Associar logs a traces -- Navegue das entradas de log para traces distribuídos no console do ARMS.
Associar logs de aplicação a trace IDs no Simple Log Service -- Configure a correlação bidirecional entre traces do ARMS e logs do Simple Log Service.