ecom-store/utils/example_usage.py
root 33fb270ecf feat(ecom-store): adicionar logger centralizado M5 (m5log)
Wrapper do loguru com 3 modos de saida para o motor e-commerce:
- Texto (default): console colorido + arquivos rotacionados em
  /root/ecommerce/logs/, retencao 30/90 dias, compressao gzip
- JSON padrao (M5_LOG_JSON=1): mesmo formato de arquivo, com
  serialize=True do loguru
- JSON clean (M5_LOG_JSON_CLEAN=1): sink customizado sem campo
  'text' e com exception.traceback_str como string unica, otimizado
  para ingestao em Loki/Elastic/n8n

API publica:
- get_logger(name) -> logger bindado com module + context
- bind_context(**kwargs) -> context manager para request_id/agent
- log_exception(log, message, **kwargs) -> captura traceback estruturado
- configure() -> idempotente, controla os 3 modos via env vars

Acompanha example_usage.py com 4 cenarios reais:
1. Sync marketplace (com bind_context por SKU)
2. Agente async (Telegram -> Amazon sync)
3. Pedido com erro de NF-e (log_exception com sefaz_status)
4. Job batch Black Friday (progresso a cada N SKUs)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 15:30:53 -03:00

147 lines
4.2 KiB
Python

"""
Exemplo de uso real do logger M5 em diferentes cenarios.
Cobre os 4 casos que vao aparecer no motor e-commerce:
1. Script de sincronizacao com marketplace
2. Agente async com contexto de execucao
3. Worker de pedido com tratamento de erro
4. Job batch com progresso
Rodar:
/root/ecommerce/scripts/venv/bin/python utils/example_usage.py
M5_LOG_JSON=1 /root/ecommerce/scripts/venv/bin/python utils/example_usage.py
"""
from __future__ import annotations
import time
from utils.m5log import get_logger, bind_context, log_exception, configure
def cenario_1_sync_marketplace() -> None:
"""Sync pontual de produtos para um marketplace (ex: TikTok Shop)."""
log = get_logger(__name__)
log.info("Iniciando sincronizacao com marketplace", marketplace="tiktok_shop")
time.sleep(0.05)
produtos = [
{"sku": "SKU-001", "preco": 99.90, "estoque": 12},
{"sku": "SKU-002", "preco": 149.00, "estoque": 0},
{"sku": "SKU-003", "preco": 49.90, "estoque": 200},
]
for p in produtos:
if p["estoque"] == 0:
log.warning("Produto sem estoque, pulando", sku=p["sku"])
continue
with bind_context(sku=p["sku"], marketplace="tiktok_shop"):
log.info(
"Produto sincronizado",
preco=p["preco"],
estoque=p["estoque"],
)
log.info("Sincronizacao concluida", total=len(produtos), enviados=2)
def cenario_2_agente_async() -> None:
"""Agente do Telegram processando comando do usuario."""
log = get_logger(__name__)
comando = {"user_id": 5511999999999, "texto": "/sync amazon"}
log.info("Comando recebido", **comando)
with bind_context(
agent="amazon-sync",
user_id=comando["user_id"],
request_id="req-7f3a2b",
):
log.info("Delegando para agente especializado")
for step in ["auth", "catalog", "pricing", "stock"]:
log.info("Etapa concluida", step=step)
time.sleep(0.02)
log.info("Agente finalizou")
def cenario_3_pedido_com_erro() -> None:
"""Processamento de pedido com erro de NF-e (deve gerar log estruturado)."""
log = get_logger(__name__)
pedido_id = "PED-2026-00042"
with bind_context(pedido_id=pedido_id, canal="mercado_livre"):
log.info("Pedido recebido")
try:
nota = {"numero": None, "serie": "1"}
if nota["numero"] is None:
raise ValueError("NF-e sem numero atribuido pela SEFAZ")
log.info("NF-e emitida", **nota)
except Exception:
log_exception(
log,
"Falha ao emitir NF-e",
sefaz_status="rejeitado",
tentativa=1,
)
log.info("Pedido finalizado com erro registrado")
def cenario_4_job_batch() -> None:
"""Job em lote com progresso (ex: recálculo de preços Black Friday)."""
log = get_logger(__name__)
log.info("Job batch iniciado", evento="black_friday_2026")
with bind_context(job="recalcular_precos", batch_id="bf-2026-1"):
total_skus = 250
processados = 0
erros = 0
for i in range(1, total_skus + 1):
try:
if i % 47 == 0:
raise ConnectionError("API do marketplace timeout")
processados += 1
except Exception:
erros += 1
log_exception(log, "Falha ao recalcular preco", sku=f"SKU-{i:05d}")
if i % 50 == 0:
log.info(
"Progresso",
processados=processados,
erros=erros,
percentual=round(i / total_skus * 100, 1),
)
log.info(
"Job batch finalizado",
total=total_skus,
sucessos=processados,
erros=erros,
)
if __name__ == "__main__":
configure()
print("\n--- 1. Sync marketplace ---\n")
cenario_1_sync_marketplace()
print("\n--- 2. Agente async ---\n")
cenario_2_agente_async()
print("\n--- 3. Pedido com erro ---\n")
cenario_3_pedido_com_erro()
print("\n--- 4. Job batch ---\n")
cenario_4_job_batch()
print("\n--- FIM ---\n")