Package: observability-mtl-instrument
Observability-mtl-instrumentO observability-mtl-instrument é um pacote que simplifica a instrumentação e configuração para coleta e envio de métricas, traces e logs. Por padrão a Stack utilizada é:Métricas: Prometheus e PushGatewayTraces: Grafana/TempoLogs: Grafana/LokiTabela de conteúdosPacote de observabilidadeInstalaçãoComo usarMétricasTracesLogsInformações adicionaisMétricasTracesLogsPróximas funcionalidadesLinksPacote de observabilidadePara simplificar ainda mais o gerenciamento, armazenamento e visualizações de métricas, traces e logs, além de integração com a biblioteca é possível utilizar o pacote de observabilidade, que traz um docker-compose, diversas configurações e exemplos de uso para containers de Prometheus, Grafana/Loki, Grafana/Tempo, Grafana e NGINX. Está disponível em:https://github.com/SergioRicJr/observability-packageInstalaçãoInstale e atualize usando pip:pipinstallobservability-mtl-instrumentComo usarMétricasimportação da configuração de métricas:fromobservability_mtl_instrument.metrics.metric_configimportMetricConfigConfiguração básica para uso:metric_config=MetricConfig(job_name='nome escolhido para a aplicação',prometheus_url='url do pushGateway para envio de métrica')Chamada das métricasAs métricas utilizadas são baseadas e utilizam por baixo dos panos o prometheus_client, sendo assim, sejam as métricas padrões ou aquelas criadas por quem está usando, possuem os métodos e as formas de registrar as métricas seguindo a seguinte documentação:https://prometheus.github.io/client_python/. Sendo utilizado em código da seguinte forma:metrics=metric_config.metrics# As métricas podem ser utilizadas em um middleware da aplicação para funcionar de forma a poluir menos o códigometrics['requests_in_progress'].labels(service='fastapi-app').inc()Envio das métricasO envio das métricas registradas em código é realizado da seguinte forma:metric_config.send_metrics()Tracesimportação da configuração dos traces:fromobservability_mtl_instrument.tracer.trace_configimportTraceConfigConfiguração básica para uso:trace_config=TraceConfig(service_name="nome do serviço",tempo_url="http://endereço do tempo/tempo/v1/traces")Criação de traces no códigoExistem duas maneiras de adicionar trace no código, uma delas é com instrumentação automática, que gera os traces a cada chamada de api ou requisição feito durante uma chamada a um endpoint, um exemplo pode ser visto utilizando FastAPIInstrumentor:fromopentelemetry.instrumentation.fastapiimportFastAPIInstrumentortrace=trace_config.get_trace()FastAPIInstrumentor.instrument_app(app,tracer_provider=trace.get_tracer_provider())A outra forma é realizando a criação manual dos traces:tracer=trace_config.get_tracer()withtracer.start_as_current_span("name"):# Código que fará parte desse traceÉ possível também adicionar eventos e atributos no centexto do tracer, para conhecer mais acessehttps://opentelemetry-python.readthedocs.io/en/latest/api/trace.htmlLogsimportação da configuração dos logs:fromobservability_mtl_instrument.logs.builders.fullLogConfigimportFullLogConfigConfiguração básica para uso:log_config=FullLogConfig(service_name='nome escolhido para a aplicação',loki_url='http://<url-do-loki>/loki/api/v1/push').get_log_config()obs: A configuração do log_level é feita importando a biblioteca logging e utilizando seus níveis de log, que são:logging.DEBUGlogging.INFOlogging.WARNlogging.ERRORlogging.CRITICALpor padrão o nível de log é DEBUG.Chamada de logsOs logs são configurados utilizando a biblioteca logging do python, sendo assim, para realizar a chamada e registro dos logs é necessário resgatar o logger em uma variável, como é possível ver na documentação dologging. Um exemplo de chamada é:logger=log_config.get_logger()# Essa linha de código é responsável por registrar um log do tipo e realizar seu envio ao Lokilogger.info('hello message was sent')Informações adicionaisMétricas:Tipos de métricaO prometheus possui diversos tipos de métrica, que podem ser conhecidas através de sua documentação, emhttps://prometheus.io/docs/concepts/metric_types. O projeto observability-mtl-instrument, trabalha com todas elas.Métricas defaultÉ possível adicionar e criar métricas de acordo com o seu objetivo, porém, a biblioteca já apresenta três métricas por padrão, são elas:http_requests_total_by_code:Tipo: CounterLabels:NomeTipoDescriçãohttp_codestringCódigo do status HTTP.unmappedbooleanTrue ou False, para dizer se a rota é ou não conhecida pela aplicação.service_namestringNome do serviço, aplicação ou job.http_requests_duration_secondsTipo: SummaryLabels:NomeTipoDescriçãourl_pathstringRota da requisiçãohttp_methodstringMétodo HTTP usado na requisiçãounmappedbooleanTrue ou False, para dizer se a rota é ou não conhecida pela aplicação.service_namestringNome do serviço, aplicação ou job.requests_in_progressTipo: GaugeLabels:NomeTipoDescriçãoservice_namestringNome do serviço, aplicação ou job.Adição de métricasAlém das métricas já existentes ao realizar a configuração, é possível criar outras completamente personalizadas, adicionando o título, seu tipo, sua descrição e os labels. Segue um exemplo dessa criação de métricas:fromobservability_mtl_instrument.metric_configimportMetricType# Após instânciar MetricConfigmetric_config.add_metrics(title="requests_in_progress",type=MetricType.GAUGE,description:"",labels=['service'])LogsEnvio assíncrono de logsÉ possível enviar os logs ao container Loki também de forma assíncrona, utilizando a classe FullLogConfigAsync ao invés da FullLogConfig, o que é feito da segunda forma:log_config=FullLogConfigAsync(service_name='nome escolhido para a aplicação',loki_url='http://<url-do-loki>/loki/api/v1/push').get_log_config()Vale ressaltar que o envio assíncrono de logs é suportado em funções assíncronas, como usadas no fastapi, ou flask, da seguinte forma:fromfastapiimportFastAPIapp=FastAPI()@app.get("/")asyncdefwelcome():logger.info('hello message was sent')return{"message":"Hello, welcome to the application!"}Obs: Ainda está sendo estudada a compatibilidade do envio assíncrono com aplicações utilizando o Framework Django.Integração com TraceA configuração padrão dos Logs já realiza a integração com os dados do Trace mas caso seja interessante para o uso escolhido, é possível alterar a formatação do log, alterando o parâmetro log_format ao instânciar o LogConfig:log_config=FullLogConfig(service_name='nome escolhido para a aplicação',loki_url='http://<url-do-loki>/loki/api/v1/push',log_format='%(asctime)slevelname=%(levelname)sname=%(name)sfile=%(filename)s:%(lineno)dtrace_id=%(otelTraceID)sspan_id=%(otelSpanID)sresource.service.name=%(otelServiceName)strace_sampled=%(otelTraceSampled)s- message="%(message)s"',).get_log_config()LabelsOs labels são utilizados para facilitar a busca por logs no Grafana/Loki, sendo assim, há duas formas possíveis de realizar a adição de labels:Na configuração dos logs, onde todos os logs apresentarão esses labels:log_config=FullLogConfig(service_name='nome escolhido para a aplicação',loki_url='http://<url-do-loki>/loki/api/v1/push',extra_labels={"label1":"valor1","label2":"valor2"}).get_log_config()Em chamadas específicas de log:logger.info('hello message was sent',extra={'extra_labels':{"label3":"valor3"}})Próximas funcionalidadesDesenvolvimento de envio assíncrono de métricas e traces ✏️🚧Desenvolvimento de Middleware para Django Rest Framework ✏️🚧Desenvolvimento de Middleware para FastAPI ✏️🚧LinksPyPi releasesDocumentação ReadTheDocsCódigo fonte