Loki Console Logger Python

Elven Observability Official Logger:

Um coletor de logs, eventos e exceções de apps Python que envia tudo para o Grafana Loki, com suporte a labels dinâmicas, alta performance, envio assíncrono e integração instantânea com o Elven Stack.


✨ Features

  • Altíssima performance com asyncio + aiohttp
  • 🔗 Captura tudo automaticamente:
    • print()
    • logging
    • Exceções não tratadas
    • Eventos personalizados via track_event
  • 🏷️ Suporte a labels fixas e dinâmicas
  • 📦 Buffer com envio em lote e intervalo configurável
  • ✅ Seguro contra falhas de rede
  • 🧵 Compatível com apps síncronos e assíncronos
  • 🔁 Envio final garantido com atexit (até em scripts simples)

📦 Instalação

pip install loki-console-logger-python

🚀 Uso básico

from loki_console_logger_python import LokiLogger
from loki_console_logger_python.config import LokiLoggerOptions

options = LokiLoggerOptions(
    url="<https://loki.elvenobservability.com/loki/api/v1/push>",
    tenant_id="elven",
    app_name="my-awesome-app",
    auth_token="seu-token-opcional",  # JWT Elven
    batch_size=10,
    flush_interval=2,
    labels={"env": "production"},
    dynamic_labels={"hostname": lambda: "api-01.local"},
)

logger = LokiLogger(options)

print("Isso será enviado ao Loki!")
logger.track_event("usuario_cadastrado", {"user_id": 123})
raise Exception("Erro de teste!")  # Capturado automaticamente

⚙️ Opções de Configuração

ParâmetroTipoDescriçãoPadrão
urlstrEndpoint do Loki HTTP Push API
tenant_idstrUsado no header X-Scope-OrgID (multi-tenant)
app_namestrLabel de identificação da aplicação
auth_tokenstrToken JWT para autenticaçãoNone
batch_sizeintQuantidade de logs para envio em lote10
flush_intervalint (segundos)Tempo máximo antes do envio2
labelsdict[str, str]Labels fixas{}
dynamic_labelsdict[str, Callable[[]])Labels geradas dinamicamente em cada envio{}

🧪 Exemplo com FastAPI

from fastapi import FastAPI
from loki_console_logger_python import LokiLogger
from loki_console_logger_python.config import LokiLoggerOptions

app = FastAPI()

logger = LokiLogger(
    LokiLoggerOptions(
        url="<https://loki.elvenobservability.com/loki/api/v1/push>",
        tenant_id="elven",
        app_name="fastapi-app",
        auth_token="seu-token",
        labels={"env": "dev"},
        dynamic_labels={"hostname": lambda: "devbox"}
    )
)

@app.get("/ping")
async def ping():
    print("ping chamado")
    logger.track_event("ping")
    return {"message": "pong"}

@app.get("/erro")
async def erro():
    raise ValueError("Erro proposital")

💡 Boas práticas

SituaçãoRecomendações
Script curto (ex: CLI, cron)O logger garante envio com atexit, mas prefira logger.flush_sync() no final para garantir
Aplicações web (ex: FastAPI)Nada extra é necessário, o envio é feito automaticamente em background
Ambientes sem asyncio rodandoNão se preocupe: o logger detecta e adapta automaticamente
Alta concorrênciaUse batch_size > 10 e ajuste flush_interval para evitar excesso de requisições

🧯 Troubleshooting

ProblemaCausa comumSolução
SyntaxError em linha com url=Caractere invisível (ex: vindo de copy/paste)Reescreva o trecho manualmente
Logs não aparecem no LokiLabels inconsistentes ou sem flush suficienteVerifique tenant_id, auth_token, use flush_logs() antes de encerrar
RuntimeError em atexitScript puro sem loop asyncioJá tratado internamente com fallback seguro
Uvicorn reiniciando em loopCódigo com erro de sintaxeVeja o log e corrija a linha apontada (normalmente url=)

🔄 Flush manual (opcional)

Em scripts curtos ou síncronos, você pode forçar o envio assim:

logger.flush_sync()  # Bloca até todos os logs serem enviados

📤 Eventos customizados

logger.track_event("usuario_ativo", {"user_id": "abc123", "source": "mobile"})

Esses eventos aparecerão no Loki como:

[EVENT] usuario_ativo {"user_id": "abc123", "source": "mobile"}

📁 Formato dos logs no Loki

Cada entrada tem:

  • Timestamp com precisão de nanossegundos
  • Labels definidas na config
  • Mensagem prefixada com [PRINT], [EXCEPTION], [EVENT], [INFO], etc

📄 Licença

Este projeto é licenciado sob a MIT License.


🙌 Contribuindo

  1. Fork este repositório
  2. Crie uma branch com sua feature ou correção
  3. Envie um Pull Request

Toda contribuição é bem-vinda para tornar a observabilidade Python ainda mais poderosa!


💚 Feito com amor pela Elven Observability

Ficou com dúvida? Fale com a gente!

Nesta página
Rolar para cima