Logs e CloudWatch para Lambda
Introdução
Os logs são essenciais para entender o comportamento das suas funções Lambda e diagnosticar problemas. Amazon CloudWatch Logs é o serviço nativo para coletar, armazenar e analisar esses logs.
Arquitetura dos Logs Lambda
┌─────────────────────────────────────────────────────────────────┐
│ FLUXO DOS LOGS LAMBDA │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Lambda │────►│ CloudWatch │────►│ Análise │ │
│ │ Function │ │ Logs │ │ / Alertas │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ Cada invocação gera: │
│ • START RequestId │
│ • Seus logs (print, console.log) │
│ • END RequestId │
│ • REPORT (duração, memória, cobrança) │
│ │
└─────────────────────────────────────────────────────────────────┘
Estrutura dos Log Groups
CloudWatch Logs
│
├── /aws/lambda/minha-funcao-1
│ ├── Log Stream 2024/01/15/[$LATEST]abc123
│ ├── Log Stream 2024/01/15/[$LATEST]def456
│ └── Log Stream 2024/01/16/[$LATEST]ghi789
│
├── /aws/lambda/minha-funcao-2
│ └── ...
│
└── /aws/lambda/minha-funcao-3
└── ...
Conceitos-chave:
- Log Group: Um grupo por função Lambda (
/aws/lambda/nome-funcao) - Log Stream: Um fluxo por instância de container Lambda
- Log Event: Cada linha individual de log
Formato dos Logs Lambda
Mensagem START
START RequestId: 12345-abcde-67890 Version: $LATEST
Mensagens personalizadas (seu código)
# Python
print("Processando usuário:", user_id)
logger.info("Conectando ao banco de dados")
logger.error("Erro: arquivo não encontrado")
// Node.js
console.log("Processando usuário:", userId);
console.info("Conectando ao banco de dados");
console.error("Erro: arquivo não encontrado");
Mensagem END
END RequestId: 12345-abcde-67890
Mensagem REPORT (muito importante!)
REPORT RequestId: 12345-abcde-67890
Duration: 234.56 ms
Billed Duration: 235 ms
Memory Size: 128 MB
Max Memory Used: 67 MB
Init Duration: 145.23 ms
Análise do REPORT
┌─────────────────────────────────────────────────────────────────┐
│ ANÁLISE DO REPORT │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Duration: 234.56 ms │
│ └── Tempo real de execução do seu código │
│ │
│ Billed Duration: 235 ms │
│ └── Tempo cobrado (arredondado para cima) │
│ │
│ Memory Size: 128 MB │
│ └── Memória ALOCADA (configurada) │
│ │
│ Max Memory Used: 67 MB │
│ └── Memória REALMENTE utilizada │
│ Se próximo de Memory Size = risco de OOM! │
│ │
│ Init Duration: 145.23 ms (apenas Cold Start) │
│ └── Tempo de inicialização do container │
│ │
└─────────────────────────────────────────────────────────────────┘
Boas Práticas de Logging
1. Logging Estruturado (JSON)
import json
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
# Log estruturado para facilitar a análise
log_entry = {
"level": "INFO",
"request_id": context.aws_request_id,
"action": "process_order",
"order_id": event.get("order_id"),
"user_id": event.get("user_id")
}
logger.info(json.dumps(log_entry))
2. Níveis de Log
┌─────────────────────────────────────────────────────────────────┐
│ NÍVEIS DE LOG │
├─────────────────────────────────────────────────────────────────┤
│ │
│ DEBUG → Detalhes técnicos (apenas dev) │
│ INFO → Operações normais │
│ WARNING → Situações anormais mas tratadas │
│ ERROR → Erros que requerem atenção │
│ CRITICAL → Erros graves, função comprometida │
│ │
│ Produção: INFO e acima │
│ Desenvolvimento: DEBUG e acima │
│ │
└─────────────────────────────────────────────────────────────────┘
3. Informações Essenciais para Logar
def lambda_handler(event, context):
# SEMPRE logar no início
logger.info(f"START - RequestId: {context.aws_request_id}")
logger.info(f"Event: {json.dumps(event)}")
try:
# Sua lógica
result = process_data(event)
# Logar sucesso
logger.info(f"SUCCESS - Result: {result}")
return result
except Exception as e:
# Logar erro com detalhes
logger.error(f"ERROR - Type: {type(e).__name__}")
logger.error(f"ERROR - Message: {str(e)}")
logger.error(f"ERROR - Event: {json.dumps(event)}")
raise
Pesquisa nos Logs
CloudWatch Logs Insights
-- Encontrar todos os erros
fields @timestamp, @message
| filter @message like /ERROR/
| sort @timestamp desc
| limit 100
-- Analisar as durações de execução
fields @timestamp, @duration
| filter @type = "REPORT"
| stats avg(@duration), max(@duration), min(@duration)
-- Encontrar Cold Starts
fields @timestamp, @message
| filter @message like /Init Duration/
| sort @timestamp desc
-- Memória próxima do limite
fields @timestamp, @maxMemoryUsed, @memorySize
| filter @type = "REPORT"
| filter @maxMemoryUsed / @memorySize > 0.8
Filtros de Padrão
# Encontrar erros
?ERROR ?Error ?error
# Encontrar um RequestId específico
"12345-abcde-67890"
# Encontrar timeouts
"Task timed out"
# Encontrar OOM (Out of Memory)
"Runtime exited" "memory"
Retenção dos Logs
┌─────────────────────────────────────────────────────────────────┐
│ RETENÇÃO DOS LOGS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Padrão: Os logs são mantidos INDEFINIDAMENTE │
│ └── Atenção aos custos de armazenamento! │
│ │
│ Opções de retenção: │
│ • 1 dia, 3 dias, 5 dias, 1 semana │
│ • 2 semanas, 1 mês, 2 meses, 3 meses │
│ • 6 meses, 1 ano, 13 meses, 18 meses │
│ • 2 anos, 3 anos, 5 anos, 10 anos │
│ • Nunca expirar │
│ │
│ Recomendação: │
│ • Dev/Teste: 1-7 dias │
│ • Produção: 30-90 dias │
│ • Compliance: conforme regulamentação │
│ │
└─────────────────────────────────────────────────────────────────┘
Métricas Importantes
| Métrica | Descrição | Limite típico de alerta |
|---|---|---|
| Invocations | Número de chamadas | Conforme baseline |
| Duration | Tempo de execução | > 80% do timeout |
| Errors | Número de erros | > 1% das invocações |
| Throttles | Invocações limitadas | > 0 |
| ConcurrentExecutions | Execuções paralelas | > 80% do limite |
Exercício Prático
Cenário: Analisar os logs de uma função problemática
Logs observados:
────────────────────────────────────────────────────────
START RequestId: abc-123
Connecting to database...
REPORT Duration: 29543.21 ms Billed: 29544 ms
Memory: 128 MB Max Used: 125 MB
START RequestId: def-456
Connecting to database...
Task timed out after 30.00 seconds
START RequestId: ghi-789
Runtime exited with error: signal: killed
────────────────────────────────────────────────────────
Perguntas:
1. Qual é o principal problema?
2. Quais métricas estão anormais?
3. Quais soluções você propõe?
Ver análise
Problemas identificados:
- Timeout: A função leva quase 30 segundos (limite)
- Memória: 125/128 MB usados (97% - crítico!)
- OOM: "Runtime exited... signal: killed" = Out of Memory
Soluções:
- Aumentar a memória (256 MB ou mais)
- Otimizar o código de conexão com o banco de dados (connection pooling)
- Aumentar o timeout se necessário
- Adicionar logs para identificar o gargalo
Resumo
- CloudWatch Logs captura automaticamente todos os logs Lambda
- A mensagem REPORT contém as métricas de performance
- Use logging estruturado (JSON) para facilitar a análise
- Configure a retenção para controlar custos
- CloudWatch Logs Insights permite consultas SQL sobre os logs
Próxima seção: Quiz de Validação