Pular para o conteúdo principal

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étricaDescriçãoLimite típico de alerta
InvocationsNúmero de chamadasConforme baseline
DurationTempo de execução> 80% do timeout
ErrorsNúmero de erros> 1% das invocações
ThrottlesInvocações limitadas> 0
ConcurrentExecutionsExecuçõ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:

  1. Timeout: A função leva quase 30 segundos (limite)
  2. Memória: 125/128 MB usados (97% - crítico!)
  3. OOM: "Runtime exited... signal: killed" = Out of Memory

Soluções:

  1. Aumentar a memória (256 MB ou mais)
  2. Otimizar o código de conexão com o banco de dados (connection pooling)
  3. Aumentar o timeout se necessário
  4. 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