> For the complete documentation index, see [llms.txt](https://docs.elven.works/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.elven.works/elven-platform/elven-observability/integracao-e-instrumentacao/aws-lambda/instrumentando-aws-lambda-com-elven-observability.md).

# Instrumentando AWS Lambda com Elven Observability

***

### Sumário

* Quando usar este guia
* Arquitetura
* Pré-requisitos
* Quick start
* Passo 1 - Coletar dados da função
* Passo 2 - Escolher as layers
* Passo 3 - Aplicar as layers com segurança
* Passo 4 - Configurar variáveis de ambiente
* Passo 5 - Validar ponta a ponta
* Referência de versões e ARNs
* Referência de variáveis de ambiente
* Scripts completos
* Migração de funções antigas com variáveis LOKI
* Boas práticas
* Troubleshooting
* FAQ

***

### Quando usar este guia

Use este guia quando você quer instrumentar funções Lambda manualmente, por AWS CLI, Console AWS, Terraform, CloudFormation, SAM, CDK ou qualquer ferramenta que permita definir layers e variáveis de ambiente.

Se o projeto usa **Serverless Framework**, prefira o plugin da Elven. Ele injeta layers, versões e variáveis automaticamente:

* Instrumentação Lambda com Serverless Framework e Elven Plugin

Este guia manual é útil para:

* funções já existentes em produção;
* ambientes que não usam Serverless Framework;
* rollout controlado por função;
* validações e troubleshooting;
* IaC que precisa declarar explicitamente cada layer e variável.

***

### Arquitetura

A instrumentação usa duas layers na Lambda:

| Layer                          | Responsabilidade                                                               | Para onde envia           |
| ------------------------------ | ------------------------------------------------------------------------------ | ------------------------- |
| **OpenTelemetry Lambda Layer** | Auto-instrumenta o runtime e gera traces, spans e, quando habilitado, métricas | Collector OTLP do cliente |
| **Elven Lambda Log Extension** | Captura `stdout`, `stderr` e logs de plataforma pela AWS Lambda Logs API       | Collector OTLP do cliente |

Fluxo completo:

```
┌────────────────────────────────────────────────────────────────────┐
│                            AWS Lambda                              │
│                                                                    │
│  ┌────────────────────────────┐   ┌─────────────────────────────┐  │
│  │ OpenTelemetry Runtime Layer│   │ Elven Lambda Log Extension  │  │
│  │                            │   │                             │  │
│  │ - instrumenta HTTP/DB/etc. │   │ - assina a Lambda Logs API  │  │
│  │ - cria traces/spans        │   │ - captura stdout/stderr     │  │
│  │ - exporta OTLP             │   │ - exporta logs OTLP         │  │
│  └──────────────┬─────────────┘   └──────────────┬──────────────┘  │
│                 │                                │                 │
└─────────────────┼────────────────────────────────┼─────────────────┘
                  │                                │
                  └──────────────┬─────────────────┘
                                 ▼
                    Collector OpenTelemetry do cliente
                    OTLP HTTP :4318 ou endpoint privado equivalente
                                 │
                ┌────────────────┼────────────────┐
                ▼                ▼                ▼
              Tempo            Mimir             Loki
             traces           métricas           logs
```

Pontos importantes:

* O **Collector é do cliente**, implantado na infraestrutura do cliente.
* O endpoint usado na Lambda é `OTEL_EXPORTER_OTLP_ENDPOINT`.
* Logs, traces e métricas seguem o mesmo caminho lógico: **Lambda -> Collector do cliente -> backends**.
* Credenciais de Loki, Tempo ou Mimir ficam no Collector, não na Lambda.
* O tenant é enviado como atributo de recurso (`tenant.id`) para o Collector aplicar roteamento/política.

***

### Pré-requisitos

Na máquina de quem vai aplicar:

* AWS CLI v2 configurado para a conta da função.
* `jq` instalado.
* Permissão para ler e atualizar configuração de Lambda:
  * `lambda:GetFunctionConfiguration`
  * `lambda:UpdateFunctionConfiguration`
  * `lambda:GetLayerVersion`
* Permissão para ler logs no CloudWatch durante validação:
  * `logs:FilterLogEvents`

Na infraestrutura do cliente:

* Collector OpenTelemetry implantado e acessível pela Lambda.
* Receiver OTLP HTTP habilitado, normalmente em `:4318`.
* Pipeline `logs` habilitado no Collector.
* Exporters server-side configurados para os backends da Elven.
* Roteamento de tenant configurado no Collector, por endpoint dedicado ou por `tenant.id`.

Na Lambda:

* Função existente.
* Runtime suportado pela layer OTel quando quiser traces automáticos:
  * Node.js
  * Python
  * Java
  * Ruby
* Para logs, a **Elven Lambda Log Extension é runtime-agnostic**. Ela funciona também com Go, .NET, `provided.al2`, `provided.al2023` e outros runtimes porque lê logs pela AWS Lambda Logs API.

Dados que você precisa saber:

| Dado                  | Exemplo                               | Observação                                               |
| --------------------- | ------------------------------------- | -------------------------------------------------------- |
| Nome da função        | `orders-api-prod`                     | Nome real da Lambda                                      |
| Região AWS            | `us-east-1`                           | Região onde a função está                                |
| Runtime lógico        | `nodejs`                              | `nodejs`, `python`, `javaagent`, `javawrapper` ou `ruby` |
| Endpoint do Collector | `http://otel-collector.internal:4318` | Endpoint do Collector do cliente                         |
| Tenant Elven          | `cliente-a`                           | Vai em `tenant.id`; não é segredo                        |
| Ambiente              | `production`                          | Usado em `OTEL_RESOURCE_ATTRIBUTES`                      |

***

### Quick start

Para uma função Node.js em `us-east-1`, x86\_64:

```bash
FUNCTION_NAME="minha-funcao"
REGION="us-east-1"
STAGE="production"
RUNTIME="nodejs"
ELVEN_TENANT="meu-tenant"
COLLECTOR_ENDPOINT="http://otel-collector.internal:4318"
```

Adicione as duas layers:

```bash
aws lambda update-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --layers \
    "arn:aws:lambda:${REGION}:184161586896:layer:opentelemetry-nodejs-0_22_0:1" \
    "arn:aws:lambda:${REGION}:911167927290:layer:elven-lambda-log-extension:9"
```

Configure as variáveis principais:

```bash
ENV_PAYLOAD=$(jq -n \
  --arg service "$FUNCTION_NAME" \
  --arg stage "$STAGE" \
  --arg tenant "$ELVEN_TENANT" \
  --arg endpoint "$COLLECTOR_ENDPOINT" '
  {
    Variables: {
      AWS_LAMBDA_EXEC_WRAPPER: "/opt/otel-handler",
      OTEL_SERVICE_NAME: $service,
      OTEL_EXPORTER_OTLP_ENDPOINT: $endpoint,
      OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf",
      OTEL_RESOURCE_ATTRIBUTES: ("service.name=" + $service + ",environment=" + $stage + ",tenant.id=" + $tenant),
      OTEL_TRACES_SAMPLER: "always_on",
      OTEL_PROPAGATORS: "tracecontext,baggage,xray",
      OTEL_LAMBDA_TRACE_MODE: "capture",
      EXPORTER_MODE: "otlp",
      DEBUG: "false"
    }
  }
')

aws lambda update-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --environment "$ENV_PAYLOAD"
```

Esse exemplo é propositalmente curto, mas ele **substitui layers e variáveis existentes**. Para produção, use os scripts seguros abaixo, que fazem merge e preservam configuração existente.

***

### Passo 1 - Coletar dados da função

Leia a configuração atual antes de alterar qualquer coisa:

```bash
FUNCTION_NAME="minha-funcao"
REGION="us-east-1"

aws lambda get-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --query '{
    FunctionName: FunctionName,
    Runtime: Runtime,
    Architectures: Architectures,
    Timeout: Timeout,
    MemorySize: MemorySize,
    Layers: Layers[].Arn,
    Environment: Environment.Variables
  }' \
  --output json
```

Confira especialmente:

* `Runtime`: ajuda a escolher a layer OTel.
* `Architectures`: `x86_64` ou `arm64`.
* `Layers`: para evitar duplicar layer antiga.
* `Environment.Variables`: para preservar variáveis já existentes.
* `Timeout`: se estiver muito baixo, ajuste antes do rollout.

***

### Passo 2 - Escolher as layers

Você precisa de:

1. Uma layer OTel oficial conforme o runtime.
2. Uma layer Elven Log Extension conforme arquitetura e região.

#### Runtime -> Layer OTel

Versões verificadas nas releases oficiais do projeto `open-telemetry/opentelemetry-lambda` em **2026-05-15**. As releases mais recentes usadas aqui foram publicadas em **2026-05-08**.

| Runtime      | Use quando                   | ARN                                                                             |
| ------------ | ---------------------------- | ------------------------------------------------------------------------------- |
| Node.js      | Funções Node.js              | `arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-nodejs-0_22_0:1`      |
| Python       | Funções Python               | `arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-python-0_20_0:1`      |
| Java Agent   | Java com auto-instrumentação | `arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-javaagent-0_20_0:1`   |
| Java Wrapper | Java com wrapper/manual      | `arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-javawrapper-0_20_0:1` |
| Ruby         | Funções Ruby                 | `arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-ruby-0_14_0:1`        |

Fonte oficial: [open-telemetry/opentelemetry-lambda releases](https://github.com/open-telemetry/opentelemetry-lambda/releases).

#### Arquitetura e região -> Elven Log Extension

As versões abaixo foram publicadas pela Elven no account `911167927290` em **2026-05-15**.

| Região      | x86\_64                                                                    | arm64                                                                            |
| ----------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `us-east-1` | `arn:aws:lambda:us-east-1:911167927290:layer:elven-lambda-log-extension:9` | `arn:aws:lambda:us-east-1:911167927290:layer:elven-lambda-log-extension-arm64:8` |
| `us-east-2` | `arn:aws:lambda:us-east-2:911167927290:layer:elven-lambda-log-extension:9` | `arn:aws:lambda:us-east-2:911167927290:layer:elven-lambda-log-extension-arm64:8` |
| `us-west-2` | `arn:aws:lambda:us-west-2:911167927290:layer:elven-lambda-log-extension:9` | `arn:aws:lambda:us-west-2:911167927290:layer:elven-lambda-log-extension-arm64:8` |
| `eu-west-1` | `arn:aws:lambda:eu-west-1:911167927290:layer:elven-lambda-log-extension:8` | `arn:aws:lambda:eu-west-1:911167927290:layer:elven-lambda-log-extension-arm64:8` |
| `sa-east-1` | `arn:aws:lambda:sa-east-1:911167927290:layer:elven-lambda-log-extension:8` | `arn:aws:lambda:sa-east-1:911167927290:layer:elven-lambda-log-extension-arm64:8` |

Para uma região que não esteja na tabela, confirme com a Elven antes de aplicar. A layer de logs precisa existir na mesma região da função Lambda.

#### Sobre a layer "collector" oficial

As releases oficiais também publicam:

```
arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-collector-<amd64|arm64>-0_22_0:1
```

No padrão Elven, **não use essa layer por padrão**.

O Collector da Elven para esse fluxo é um serviço de infraestrutura no ambiente do cliente, não um Collector rodando dentro de cada Lambda. Isso reduz overhead de cold start e mantém credenciais dos backends fora das funções.

Use a layer oficial de Collector apenas em cenários avançados e explicitamente desenhados para rodar Collector dentro da Lambda.

***

### Passo 3 - Aplicar as layers com segurança

O parâmetro `--layers` da AWS CLI substitui a lista inteira de layers. O script abaixo:

* preserva layers que não são da Elven/OpenTelemetry Lambda runtime;
* remove versões antigas da Elven Log Extension;
* remove versões antigas das layers OTel oficiais de runtime;
* adiciona a versão correta para runtime, região e arquitetura.

```bash
#!/usr/bin/env bash
set -euo pipefail

FUNCTION_NAME="minha-funcao"
REGION="us-east-1"
RUNTIME="nodejs" # nodejs | python | javaagent | javawrapper | ruby

function otel_layer_for_runtime() {
  case "$1" in
    nodejs)      echo "arn:aws:lambda:${REGION}:184161586896:layer:opentelemetry-nodejs-0_22_0:1" ;;
    python)      echo "arn:aws:lambda:${REGION}:184161586896:layer:opentelemetry-python-0_20_0:1" ;;
    javaagent)   echo "arn:aws:lambda:${REGION}:184161586896:layer:opentelemetry-javaagent-0_20_0:1" ;;
    javawrapper) echo "arn:aws:lambda:${REGION}:184161586896:layer:opentelemetry-javawrapper-0_20_0:1" ;;
    ruby)        echo "arn:aws:lambda:${REGION}:184161586896:layer:opentelemetry-ruby-0_14_0:1" ;;
    *)
      echo "Runtime inválido: $1" >&2
      return 1
      ;;
  esac
}

function elven_log_layer_for_arch_region() {
  local arch="$1"

  if [ "$arch" = "arm64" ]; then
    echo "arn:aws:lambda:${REGION}:911167927290:layer:elven-lambda-log-extension-arm64:8"
    return
  fi

  case "$REGION" in
    us-east-1|us-east-2|us-west-2)
      echo "arn:aws:lambda:${REGION}:911167927290:layer:elven-lambda-log-extension:9"
      ;;
    eu-west-1|sa-east-1)
      echo "arn:aws:lambda:${REGION}:911167927290:layer:elven-lambda-log-extension:8"
      ;;
    *)
      echo "Região sem versão Elven Log Extension documentada: $REGION" >&2
      return 1
      ;;
  esac
}

CONFIG=$(aws lambda get-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --output json)

ARCH=$(echo "$CONFIG" | jq -r '.Architectures[0] // "x86_64"')
OTEL_LAYER=$(otel_layer_for_runtime "$RUNTIME")
LOG_LAYER=$(elven_log_layer_for_arch_region "$ARCH")

FINAL_LAYERS_JSON=$(echo "$CONFIG" | jq \
  --arg otel "$OTEL_LAYER" \
  --arg log "$LOG_LAYER" '
    def is_elven_log_layer:
      test(":911167927290:layer:elven-lambda-log-extension(-arm64)?:");
    def is_otel_runtime_layer:
      test(":184161586896:layer:opentelemetry-(nodejs|python|javaagent|javawrapper|ruby)-");

    ([.Layers[]?.Arn] // [])
    | map(select((is_elven_log_layer or is_otel_runtime_layer) | not))
    | . + [$otel, $log]
    | unique
  ')

echo "Arquitetura detectada: $ARCH"
echo "Layer OTel: $OTEL_LAYER"
echo "Layer logs: $LOG_LAYER"

aws lambda update-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --layers "$FINAL_LAYERS_JSON" \
  --output json | jq '{FunctionName, LastModified, Layers: [.Layers[].Arn]}'
```

***

### Passo 4 - Configurar variáveis de ambiente

O parâmetro `--environment` também substitui todas as variáveis da função. Use merge seguro.

#### Variáveis principais

| Variável                      | Exemplo                                                             | Obrigatória?                | Observação                                                    |
| ----------------------------- | ------------------------------------------------------------------- | --------------------------- | ------------------------------------------------------------- |
| `AWS_LAMBDA_EXEC_WRAPPER`     | `/opt/otel-handler`                                                 | Sim para traces automáticos | Inicializa a layer OTel antes do handler                      |
| `OTEL_SERVICE_NAME`           | `orders-api-prod`                                                   | Sim                         | Nome do serviço em traces e logs                              |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | `http://otel-collector.internal:4318`                               | Sim                         | Endpoint do Collector do cliente                              |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | `http/protobuf`                                                     | Recomendado                 | Mantém o protocolo explícito                                  |
| `OTEL_RESOURCE_ATTRIBUTES`    | `service.name=orders-api-prod,environment=prod,tenant.id=cliente-a` | Sim                         | `tenant.id` é obrigatório no modo OTLP da Elven Log Extension |
| `OTEL_TRACES_SAMPLER`         | `always_on`                                                         | Recomendado                 | Ajuste para `traceidratio` em alto volume                     |
| `OTEL_PROPAGATORS`            | `tracecontext,baggage,xray`                                         | Recomendado                 | Mantém compatibilidade com contexto AWS/X-Ray                 |
| `OTEL_LAMBDA_TRACE_MODE`      | `capture`                                                           | Recomendado                 | Captura o contexto da invocação Lambda                        |
| `EXPORTER_MODE`               | `otlp`                                                              | Sim para logs via Collector | Garante que logs vão para OTLP, não Loki direto               |
| `DEBUG`                       | `false`                                                             | Não                         | Use `true` só em troubleshooting curto                        |

#### O que não configurar mais na Lambda

Não configure estas variáveis em novas implantações:

```
LOKI_URL
LOKI_TENANT_ID
LOKI_AUTH_TOKEN
```

Essas credenciais e headers pertencem ao Collector do cliente. A Lambda deve conhecer apenas:

* endpoint OTLP do Collector;
* identidade do serviço;
* `tenant.id` como atributo de roteamento;
* opcionalmente um header de autenticação para falar com o Collector, se o cliente exigir.

#### Auth Lambda -> Collector

O padrão recomendado é Collector em rede privada/VPC-only, sem token na Lambda.

Se o cliente exigir autenticação entre Lambda e Collector, use:

```bash
OTEL_EXPORTER_OTLP_HEADERS="authorization=Bearer%20TOKEN"
```

Use headers apenas para autenticar no Collector do cliente. Não coloque token do Loki ou de backend final nessa variável.

#### Script seguro para aplicar envs

```bash
#!/usr/bin/env bash
set -euo pipefail

FUNCTION_NAME="minha-funcao"
REGION="us-east-1"
STAGE="production"
RUNTIME="nodejs" # nodejs | python | javaagent | javawrapper | ruby

ELVEN_TENANT="meu-tenant"
COLLECTOR_ENDPOINT="http://otel-collector.internal:4318"
SERVICE_NAME="$FUNCTION_NAME"

# Opcional. Use apenas se o Collector do cliente exigir auth.
OTEL_EXPORTER_OTLP_HEADERS="${OTEL_EXPORTER_OTLP_HEADERS:-}"

CONFIG=$(aws lambda get-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --output json)

ENV_ATUAL=$(echo "$CONFIG" | jq '.Environment.Variables // {}')

ELVEN_VARS=$(jq -n \
  --arg service "$SERVICE_NAME" \
  --arg stage "$STAGE" \
  --arg tenant "$ELVEN_TENANT" \
  --arg endpoint "$COLLECTOR_ENDPOINT" '
  {
    AWS_LAMBDA_EXEC_WRAPPER: "/opt/otel-handler",
    OTEL_SERVICE_NAME: $service,
    OTEL_EXPORTER_OTLP_ENDPOINT: $endpoint,
    OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf",
    OTEL_RESOURCE_ATTRIBUTES: ("service.name=" + $service + ",environment=" + $stage + ",tenant.id=" + $tenant),
    OTEL_TRACES_SAMPLER: "always_on",
    OTEL_PROPAGATORS: "tracecontext,baggage,xray",
    OTEL_LAMBDA_TRACE_MODE: "capture",
    EXPORTER_MODE: "otlp",
    DEBUG: "false"
  }
')

case "$RUNTIME" in
  nodejs)
    ELVEN_VARS=$(echo "$ELVEN_VARS" | jq '. + {
      OTEL_NODE_ENABLED_INSTRUMENTATIONS: "http,express,graphql,grpc,hapi,ioredis,koa,mongodb,mysql,net,pg,redis,memcached,mongoose,amqplib,kafkajs,knex,mysql2,nestjs-core,pino,restify,socket.io,undici,winston"
    }')
    ;;
  python)
    ELVEN_VARS=$(echo "$ELVEN_VARS" | jq '. + {
      OTEL_PYTHON_DISABLED_INSTRUMENTATIONS: "",
      OTEL_PYTHON_LOG_CORRELATION: "true"
    }')
    ;;
  javaagent|javawrapper)
    ELVEN_VARS=$(echo "$ELVEN_VARS" | jq '. + {
      OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED: "true"
    }')
    ;;
  ruby)
    ELVEN_VARS=$(echo "$ELVEN_VARS" | jq '. + {
      OTEL_RUBY_DISABLED_INSTRUMENTATIONS: ""
    }')
    ;;
  *)
    echo "Runtime inválido: $RUNTIME" >&2
    exit 1
    ;;
esac

if [ -n "$OTEL_EXPORTER_OTLP_HEADERS" ]; then
  ELVEN_VARS=$(echo "$ELVEN_VARS" | jq --arg headers "$OTEL_EXPORTER_OTLP_HEADERS" '. + {
    OTEL_EXPORTER_OTLP_HEADERS: $headers
  }')
fi

ENV_FINAL=$(jq -s '.[0] * .[1]' <(echo "$ENV_ATUAL") <(echo "$ELVEN_VARS"))
ENV_PAYLOAD=$(jq -n --argjson vars "$ENV_FINAL" '{Variables: $vars}')

aws lambda update-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --environment "$ENV_PAYLOAD" \
  --output json | jq '{FunctionName, LastModified, Environment: .Environment.Variables}'
```

***

### Passo 5 - Validar ponta a ponta

#### 1. Confirme a configuração aplicada

```bash
aws lambda get-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --query '{
    FunctionName: FunctionName,
    Runtime: Runtime,
    Architectures: Architectures,
    Layers: Layers[].Arn,
    Env: Environment.Variables
  }' \
  --output json
```

Checklist local na configuração:

* Existe uma layer OTel do runtime correto.
* Existe uma layer `elven-lambda-log-extension` compatível com a arquitetura.
* `AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-handler`.
* `OTEL_EXPORTER_OTLP_ENDPOINT` aponta para o Collector do cliente.
* `OTEL_RESOURCE_ATTRIBUTES` contém `tenant.id=<tenant>`.
* `EXPORTER_MODE=otlp`.
* Não há `LOKI_AUTH_TOKEN` na Lambda.

#### 2. Invoque a função

```bash
aws lambda invoke \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --payload '{"elven_validation":true}' \
  --cli-binary-format raw-in-base64-out \
  /tmp/lambda-response.json

cat /tmp/lambda-response.json
```

#### 3. Verifique CloudWatch

```bash
START_TIME=$((($(date +%s) - 600) * 1000))

aws logs filter-log-events \
  --log-group-name "/aws/lambda/$FUNCTION_NAME" \
  --region "$REGION" \
  --start-time "$START_TIME" \
  --query "events[?contains(message, 'Elven') || contains(message, 'elven') || contains(message, 'OTLP') || contains(message, 'Extension')].message" \
  --output text
```

Você deve ver a função executando normalmente e, em caso de erro de configuração, mensagens da extension.

#### 4. Verifique o Collector do cliente

Do lado do Collector, procure por entrada OTLP:

* traces em `/v1/traces`;
* logs em `/v1/logs`;
* `tenant.id` presente nos resource attributes;
* erros de export para Loki/Tempo/Mimir.

Se o Collector usa Kubernetes:

```bash
kubectl logs -n observability deploy/otel-collector --since=10m | grep -Ei "lambda|otlp|logs|traces|error"
```

Se usa VM/systemd:

```bash
journalctl -u otel-collector --since "10 minutes ago" | grep -Ei "lambda|otlp|logs|traces|error"
```

#### 5. Verifique na Elven Observability

No Grafana/Elven:

* procure traces pelo `service.name`;
* confirme que spans da Lambda aparecem;
* procure logs pelo mesmo `service.name` ou atributos equivalentes;
* confirme que o tenant correto vê os dados.

Com Loki OTLP nativo, os labels finais podem variar conforme a configuração do Collector/Loki. O padrão da Elven preserva os dados como resource attributes, como:

* `service.name`;
* `faas.name`;
* `function.name`;
* `cloud.region`;
* `tenant.id`;
* `aws.lambda.log.type`.

Não dependa de labels antigos como `function_name` em novas consultas, a menos que o Collector tenha uma transformação explícita para isso.

***

### Referência de versões e ARNs

#### OpenTelemetry Lambda Layers

Fonte: [open-telemetry/opentelemetry-lambda releases](https://github.com/open-telemetry/opentelemetry-lambda/releases).

| Componente          | Release                  | ARN                                                                                          |
| ------------------- | ------------------------ | -------------------------------------------------------------------------------------------- |
| Node.js             | `layer-nodejs/0.22.0`    | `arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-nodejs-0_22_0:1`                   |
| Python              | `layer-python/0.20.0`    | `arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-python-0_20_0:1`                   |
| Java Agent          | `layer-javaagent/0.20.0` | `arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-javaagent-0_20_0:1`                |
| Java Wrapper        | `layer-javaagent/0.20.0` | `arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-javawrapper-0_20_0:1`              |
| Ruby                | `layer-ruby/0.14.0`      | `arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-ruby-0_14_0:1`                     |
| Collector, avançado | `layer-collector/0.22.0` | `arn:aws:lambda:{REGION}:184161586896:layer:opentelemetry-collector-<amd64\|arm64>-0_22_0:1` |

#### Elven Lambda Log Extension

| Região      | Arquitetura | ARN                                                                              |
| ----------- | ----------- | -------------------------------------------------------------------------------- |
| `us-east-1` | x86\_64     | `arn:aws:lambda:us-east-1:911167927290:layer:elven-lambda-log-extension:9`       |
| `us-east-1` | arm64       | `arn:aws:lambda:us-east-1:911167927290:layer:elven-lambda-log-extension-arm64:8` |
| `us-east-2` | x86\_64     | `arn:aws:lambda:us-east-2:911167927290:layer:elven-lambda-log-extension:9`       |
| `us-east-2` | arm64       | `arn:aws:lambda:us-east-2:911167927290:layer:elven-lambda-log-extension-arm64:8` |
| `us-west-2` | x86\_64     | `arn:aws:lambda:us-west-2:911167927290:layer:elven-lambda-log-extension:9`       |
| `us-west-2` | arm64       | `arn:aws:lambda:us-west-2:911167927290:layer:elven-lambda-log-extension-arm64:8` |
| `eu-west-1` | x86\_64     | `arn:aws:lambda:eu-west-1:911167927290:layer:elven-lambda-log-extension:8`       |
| `eu-west-1` | arm64       | `arn:aws:lambda:eu-west-1:911167927290:layer:elven-lambda-log-extension-arm64:8` |
| `sa-east-1` | x86\_64     | `arn:aws:lambda:sa-east-1:911167927290:layer:elven-lambda-log-extension:8`       |
| `sa-east-1` | arm64       | `arn:aws:lambda:sa-east-1:911167927290:layer:elven-lambda-log-extension-arm64:8` |

***

### Referência de variáveis de ambiente

#### Obrigatórias no padrão Elven OTLP

| Variável                      | Valor recomendado                                | Componente                       |
| ----------------------------- | ------------------------------------------------ | -------------------------------- |
| `AWS_LAMBDA_EXEC_WRAPPER`     | `/opt/otel-handler`                              | OTel layer                       |
| `OTEL_SERVICE_NAME`           | `projeto-stage-funcao`                           | OTel layer e correlação          |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | endpoint do Collector do cliente                 | OTel layer e Elven Log Extension |
| `OTEL_RESOURCE_ATTRIBUTES`    | `service.name=...,environment=...,tenant.id=...` | OTel resource e roteamento       |
| `EXPORTER_MODE`               | `otlp`                                           | Elven Log Extension              |

#### Recomendadas

| Variável                      | Default recomendado         | Descrição                    |
| ----------------------------- | --------------------------- | ---------------------------- |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | `http/protobuf`             | Protocolo OTLP explícito     |
| `OTEL_TRACES_SAMPLER`         | `always_on`                 | Captura todos os traces      |
| `OTEL_TRACES_SAMPLER_ARG`     | vazio                       | Use com `traceidratio`       |
| `OTEL_PROPAGATORS`            | `tracecontext,baggage,xray` | Propagação de contexto       |
| `OTEL_LAMBDA_TRACE_MODE`      | `capture`                   | Captura contexto Lambda      |
| `DEBUG`                       | `false`                     | Debug da Elven Log Extension |

#### Runtime-specific

| Runtime | Variável                                      | Uso                                              |
| ------- | --------------------------------------------- | ------------------------------------------------ |
| Node.js | `OTEL_NODE_ENABLED_INSTRUMENTATIONS`          | Lista de instrumentações habilitadas             |
| Node.js | `OTEL_NODE_DISABLED_INSTRUMENTATIONS`         | Lista de instrumentações desabilitadas           |
| Python  | `OTEL_PYTHON_DISABLED_INSTRUMENTATIONS`       | Lista de instrumentações desabilitadas           |
| Python  | `OTEL_PYTHON_LOG_CORRELATION`                 | Correlaciona logs com trace IDs quando aplicável |
| Java    | `OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED` | Habilita instrumentações por padrão              |
| Java    | `OTEL_JAVAAGENT_DEBUG`                        | Debug do Java agent                              |
| Ruby    | `OTEL_RUBY_DISABLED_INSTRUMENTATIONS`         | Lista de instrumentações desabilitadas           |

#### Elven Log Extension - tuning avançado

| Variável        | Default                | Descrição                                  |
| --------------- | ---------------------- | ------------------------------------------ |
| `BUFFER_SIZE`   | automático por memória | Tamanho do buffer interno                  |
| `BATCH_SIZE`    | automático por memória | Quantidade de logs por envio               |
| `BATCH_TIMEOUT` | `1s`                   | Tempo máximo antes de enviar batch parcial |
| `HTTP_TIMEOUT`  | `10s`                  | Timeout para envio OTLP                    |
| `RETRY_MAX`     | `2`                    | Tentativas por batch                       |
| `RETRY_BACKOFF` | `100ms`                | Backoff entre tentativas                   |
| `CB_THRESHOLD`  | `5`                    | Threshold do circuit breaker legado        |

Defaults automáticos:

| Memória da Lambda | `BUFFER_SIZE` | `BATCH_SIZE` |
| ----------------- | ------------- | ------------ |
| `< 512 MB`        | `1000`        | `50`         |
| `512-1023 MB`     | `5000`        | `500`        |
| `>= 1024 MB`      | `10000`       | `500`        |

***

### Scripts completos

#### Script único para instrumentar uma função

Este script aplica layers e envs no padrão Elven OTLP.

```bash
#!/usr/bin/env bash
set -euo pipefail

# ============================================
# Configure estes valores
# ============================================
FUNCTION_NAME="${FUNCTION_NAME:-minha-funcao-api}"
REGION="${REGION:-us-east-1}"
STAGE="${STAGE:-production}"
RUNTIME="${RUNTIME:-nodejs}" # nodejs | python | javaagent | javawrapper | ruby
ELVEN_TENANT="${ELVEN_TENANT:-meu-tenant}"
COLLECTOR_ENDPOINT="${COLLECTOR_ENDPOINT:-http://otel-collector.internal:4318}"
SERVICE_NAME="${SERVICE_NAME:-$FUNCTION_NAME}"

# Opcional. Use somente se o Collector exigir auth.
OTEL_EXPORTER_OTLP_HEADERS="${OTEL_EXPORTER_OTLP_HEADERS:-}"
# ============================================

function otel_layer_for_runtime() {
  case "$1" in
    nodejs)      echo "arn:aws:lambda:${REGION}:184161586896:layer:opentelemetry-nodejs-0_22_0:1" ;;
    python)      echo "arn:aws:lambda:${REGION}:184161586896:layer:opentelemetry-python-0_20_0:1" ;;
    javaagent)   echo "arn:aws:lambda:${REGION}:184161586896:layer:opentelemetry-javaagent-0_20_0:1" ;;
    javawrapper) echo "arn:aws:lambda:${REGION}:184161586896:layer:opentelemetry-javawrapper-0_20_0:1" ;;
    ruby)        echo "arn:aws:lambda:${REGION}:184161586896:layer:opentelemetry-ruby-0_14_0:1" ;;
    *) echo "Runtime inválido: $1" >&2; return 1 ;;
  esac
}

function elven_log_layer_for_arch_region() {
  local arch="$1"
  if [ "$arch" = "arm64" ]; then
    echo "arn:aws:lambda:${REGION}:911167927290:layer:elven-lambda-log-extension-arm64:8"
    return
  fi

  case "$REGION" in
    us-east-1|us-east-2|us-west-2) echo "arn:aws:lambda:${REGION}:911167927290:layer:elven-lambda-log-extension:9" ;;
    eu-west-1|sa-east-1)           echo "arn:aws:lambda:${REGION}:911167927290:layer:elven-lambda-log-extension:8" ;;
    *) echo "Região sem versão Elven Log Extension documentada: $REGION" >&2; return 1 ;;
  esac
}

echo "==> Lendo configuração atual..."
CONFIG=$(aws lambda get-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --output json)

ARCH=$(echo "$CONFIG" | jq -r '.Architectures[0] // "x86_64"')
OTEL_LAYER=$(otel_layer_for_runtime "$RUNTIME")
LOG_LAYER=$(elven_log_layer_for_arch_region "$ARCH")

echo "    Função: $FUNCTION_NAME"
echo "    Região: $REGION"
echo "    Runtime Elven: $RUNTIME"
echo "    Arquitetura: $ARCH"
echo "    OTel layer: $OTEL_LAYER"
echo "    Log layer: $LOG_LAYER"

FINAL_LAYERS_JSON=$(echo "$CONFIG" | jq \
  --arg otel "$OTEL_LAYER" \
  --arg log "$LOG_LAYER" '
    def is_elven_log_layer:
      test(":911167927290:layer:elven-lambda-log-extension(-arm64)?:");
    def is_otel_runtime_layer:
      test(":184161586896:layer:opentelemetry-(nodejs|python|javaagent|javawrapper|ruby)-");

    ([.Layers[]?.Arn] // [])
    | map(select((is_elven_log_layer or is_otel_runtime_layer) | not))
    | . + [$otel, $log]
    | unique
  ')

ENV_ATUAL=$(echo "$CONFIG" | jq '.Environment.Variables // {}')

ELVEN_VARS=$(jq -n \
  --arg service "$SERVICE_NAME" \
  --arg stage "$STAGE" \
  --arg tenant "$ELVEN_TENANT" \
  --arg endpoint "$COLLECTOR_ENDPOINT" '
  {
    AWS_LAMBDA_EXEC_WRAPPER: "/opt/otel-handler",
    OTEL_SERVICE_NAME: $service,
    OTEL_EXPORTER_OTLP_ENDPOINT: $endpoint,
    OTEL_EXPORTER_OTLP_PROTOCOL: "http/protobuf",
    OTEL_RESOURCE_ATTRIBUTES: ("service.name=" + $service + ",environment=" + $stage + ",tenant.id=" + $tenant),
    OTEL_TRACES_SAMPLER: "always_on",
    OTEL_PROPAGATORS: "tracecontext,baggage,xray",
    OTEL_LAMBDA_TRACE_MODE: "capture",
    EXPORTER_MODE: "otlp",
    DEBUG: "false"
  }
')

case "$RUNTIME" in
  nodejs)
    ELVEN_VARS=$(echo "$ELVEN_VARS" | jq '. + {
      OTEL_NODE_ENABLED_INSTRUMENTATIONS: "http,express,graphql,grpc,hapi,ioredis,koa,mongodb,mysql,net,pg,redis,memcached,mongoose,amqplib,kafkajs,knex,mysql2,nestjs-core,pino,restify,socket.io,undici,winston"
    }')
    ;;
  python)
    ELVEN_VARS=$(echo "$ELVEN_VARS" | jq '. + {
      OTEL_PYTHON_DISABLED_INSTRUMENTATIONS: "",
      OTEL_PYTHON_LOG_CORRELATION: "true"
    }')
    ;;
  javaagent|javawrapper)
    ELVEN_VARS=$(echo "$ELVEN_VARS" | jq '. + {
      OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED: "true"
    }')
    ;;
  ruby)
    ELVEN_VARS=$(echo "$ELVEN_VARS" | jq '. + {
      OTEL_RUBY_DISABLED_INSTRUMENTATIONS: ""
    }')
    ;;
esac

if [ -n "$OTEL_EXPORTER_OTLP_HEADERS" ]; then
  ELVEN_VARS=$(echo "$ELVEN_VARS" | jq --arg headers "$OTEL_EXPORTER_OTLP_HEADERS" '. + {
    OTEL_EXPORTER_OTLP_HEADERS: $headers
  }')
fi

ENV_FINAL=$(jq -s '.[0] * .[1]' <(echo "$ENV_ATUAL") <(echo "$ELVEN_VARS"))
ENV_PAYLOAD=$(jq -n --argjson vars "$ENV_FINAL" '{Variables: $vars}')

echo "==> Aplicando layers e variáveis..."
aws lambda update-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --layers "$FINAL_LAYERS_JSON" \
  --environment "$ENV_PAYLOAD" \
  --output json | jq '{FunctionName, LastModified, Runtime, Architectures, Layers: [.Layers[].Arn]}'

echo "==> Pronto. Invoque a função e valide traces/logs na Elven Observability."
```

#### Instrumentar múltiplas funções

Use este modelo quando várias funções compartilham runtime, região, tenant e Collector:

```bash
#!/usr/bin/env bash
set -euo pipefail

REGION="us-east-1"
STAGE="production"
RUNTIME="nodejs"
ELVEN_TENANT="meu-tenant"
COLLECTOR_ENDPOINT="http://otel-collector.internal:4318"

FUNCTIONS=(
  "api-users"
  "api-orders"
  "worker-notifications"
)

for function_name in "${FUNCTIONS[@]}"; do
  echo
  echo "==> Instrumentando $function_name"

  FUNCTION_NAME="$function_name" \
  REGION="$REGION" \
  STAGE="$STAGE" \
  RUNTIME="$RUNTIME" \
  ELVEN_TENANT="$ELVEN_TENANT" \
  COLLECTOR_ENDPOINT="$COLLECTOR_ENDPOINT" \
  SERVICE_NAME="$function_name" \
  ./instrument-one-lambda.sh
done
```

Salve o script anterior como `instrument-one-lambda.sh` e reutilize.

#### Remover instrumentação Elven

Remove as layers da Elven/OTel runtime e variáveis adicionadas por este guia, preservando o resto:

```bash
#!/usr/bin/env bash
set -euo pipefail

FUNCTION_NAME="minha-funcao"
REGION="us-east-1"

CONFIG=$(aws lambda get-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --output json)

CLEAN_LAYERS_JSON=$(echo "$CONFIG" | jq '
  def is_elven_log_layer:
    test(":911167927290:layer:elven-lambda-log-extension(-arm64)?:");
  def is_otel_runtime_layer:
    test(":184161586896:layer:opentelemetry-(nodejs|python|javaagent|javawrapper|ruby)-");

  ([.Layers[]?.Arn] // [])
  | map(select((is_elven_log_layer or is_otel_runtime_layer) | not))
')

ENV_CLEAN=$(echo "$CONFIG" | jq '
  .Environment.Variables // {}
  | del(
      .AWS_LAMBDA_EXEC_WRAPPER,
      .OTEL_SERVICE_NAME,
      .OTEL_EXPORTER_OTLP_ENDPOINT,
      .OTEL_EXPORTER_OTLP_PROTOCOL,
      .OTEL_EXPORTER_OTLP_HEADERS,
      .OTEL_RESOURCE_ATTRIBUTES,
      .OTEL_TRACES_SAMPLER,
      .OTEL_TRACES_SAMPLER_ARG,
      .OTEL_PROPAGATORS,
      .OTEL_LAMBDA_TRACE_MODE,
      .OTEL_NODE_ENABLED_INSTRUMENTATIONS,
      .OTEL_NODE_DISABLED_INSTRUMENTATIONS,
      .OTEL_PYTHON_DISABLED_INSTRUMENTATIONS,
      .OTEL_PYTHON_LOG_CORRELATION,
      .OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED,
      .OTEL_JAVAAGENT_DEBUG,
      .OTEL_RUBY_DISABLED_INSTRUMENTATIONS,
      .EXPORTER_MODE,
      .DEBUG,
      .BUFFER_SIZE,
      .BATCH_SIZE,
      .BATCH_TIMEOUT,
      .HTTP_TIMEOUT,
      .RETRY_MAX,
      .RETRY_BACKOFF,
      .CB_THRESHOLD,
      .LOKI_URL,
      .LOKI_TENANT_ID,
      .LOKI_AUTH_TOKEN
    )
')

ENV_PAYLOAD=$(jq -n --argjson vars "$ENV_CLEAN" '{Variables: $vars}')

aws lambda update-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --layers "$CLEAN_LAYERS_JSON" \
  --environment "$ENV_PAYLOAD"
```

***

### Migração de funções antigas com variáveis LOKI

Versões antigas da Elven Log Extension enviavam logs direto para Loki usando:

```
LOKI_URL
LOKI_TENANT_ID
LOKI_AUTH_TOKEN
```

Esse modelo foi substituído pelo padrão OTLP:

```
EXPORTER_MODE=otlp
OTEL_EXPORTER_OTLP_ENDPOINT=<collector-do-cliente>
OTEL_RESOURCE_ATTRIBUTES=...,tenant.id=<tenant>
```

Estratégia recomendada:

1. Atualize a layer para a versão nova.
2. Configure o Collector do cliente com pipeline `logs`.
3. Em uma função piloto, use `EXPORTER_MODE=both` temporariamente.
4. Compare volume e exemplos de logs por 24h.
5. Troque para `EXPORTER_MODE=otlp`.
6. Remova `LOKI_AUTH_TOKEN` da Lambda.
7. Depois da janela de rollback, remova `LOKI_URL` e `LOKI_TENANT_ID`.

Rollback imediato:

```
EXPORTER_MODE=loki
LOKI_URL=<url-base-loki>
LOKI_TENANT_ID=<tenant>
LOKI_AUTH_TOKEN=<token>
```

Use rollback apenas durante a migração. O estado desejado é não manter token de Loki na Lambda.

***

### Boas práticas

#### Nome de serviço

Use nomes estáveis e fáceis de filtrar:

```
{produto}-{ambiente}-{função}
```

Exemplos:

```
checkout-production-api
orders-staging-worker
notifications-production-sender
```

Mantenha `OTEL_SERVICE_NAME` e `service.name` em `OTEL_RESOURCE_ATTRIBUTES` com o mesmo valor.

#### Tenant

`tenant.id` é obrigatório no padrão Elven OTLP:

```
OTEL_RESOURCE_ATTRIBUTES=service.name=orders-api,environment=production,tenant.id=cliente-a
```

Ele não é segredo. Ele serve para o Collector aplicar roteamento, isolamento e política de export.

#### Segurança

* O Collector deve estar em endpoint privado sempre que possível.
* Permita acesso apenas das subnets/security groups das Lambdas esperadas.
* Não coloque token de Loki, Tempo ou Mimir na Lambda.
* Se precisar autenticar Lambda -> Collector, use token específico do Collector em `OTEL_EXPORTER_OTLP_HEADERS`.
* Não exponha o Collector publicamente sem autenticação e allowlist.

#### Sampling

Para funções críticas ou baixo volume:

```
OTEL_TRACES_SAMPLER=always_on
```

Para alto volume:

```
OTEL_TRACES_SAMPLER=traceidratio
OTEL_TRACES_SAMPLER_ARG=0.1
```

`0.1` significa 10% dos traces.

#### Cold start

Layers aumentam o tempo de init. Para reduzir impacto:

* habilite só instrumentações necessárias;
* evite debug permanente;
* prefira Collector fora da Lambda;
* aumente memória quando a função é muito limitada;
* use provisioned concurrency em funções sensíveis.

#### Logs

* Evite `console.log` em loops muito intensos.
* Prefira logs estruturados JSON.
* Não escreva segredos em logs.
* Se aparecer `buffer full`, reduza volume de logs ou aumente memória.

***

### Troubleshooting

#### Função não inicia ou dá timeout no cold start

Verifique:

* `AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-handler`.
* A layer OTel corresponde ao runtime.
* A layer Elven Log Extension corresponde à arquitetura.
* O timeout da função não está baixo demais.
* Não há duas versões da mesma extension na lista de layers.

Comando útil:

```bash
aws lambda get-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --query '{Runtime: Runtime, Timeout: Timeout, Architectures: Architectures, Layers: Layers[].Arn, Wrapper: Environment.Variables.AWS_LAMBDA_EXEC_WRAPPER}' \
  --output table
```

#### Traces não aparecem

Verifique:

* A layer OTel está presente.
* `AWS_LAMBDA_EXEC_WRAPPER` está correto.
* `OTEL_EXPORTER_OTLP_ENDPOINT` aponta para o Collector do cliente.
* A Lambda consegue acessar o Collector por rede.
* O Collector tem receiver OTLP HTTP em `4318`.
* O Collector tem pipeline de traces exportando para Tempo.

No Collector:

```bash
grep -Ei "v1/traces|traces|exporter|error" /var/log/otel-collector.log
```

#### Logs não aparecem

Verifique:

* A layer `elven-lambda-log-extension` está presente.
* `EXPORTER_MODE=otlp`.
* `OTEL_EXPORTER_OTLP_ENDPOINT` está definido.
* `OTEL_RESOURCE_ATTRIBUTES` contém `tenant.id`.
* O Collector tem pipeline `logs`.
* O Collector exporta logs para Loki via configuração server-side.

Não procure `LOKI_AUTH_TOKEN` na Lambda. No modelo novo, ele não deve estar lá.

#### Erro `tenant.id is required`

A extension exige `tenant.id` em OTLP para evitar logs sem contexto de tenant.

Corrija:

```
OTEL_RESOURCE_ATTRIBUTES=service.name=minha-funcao,environment=production,tenant.id=meu-tenant
```

#### Erro 401/403 ao exportar logs

No modelo novo, 401/403 normalmente acontece do **Collector para o backend**, não da Lambda para Loki.

Verifique no Collector:

* header `X-Scope-OrgID`;
* token server-side do Loki;
* endpoint Loki OTLP;
* roteamento por `tenant.id`.

Se o erro for Lambda -> Collector, verifique `OTEL_EXPORTER_OTLP_HEADERS` e a política de rede/autenticação do Collector.

#### Logs aparecem em CloudWatch, mas não na Elven

CloudWatch sempre recebe logs da Lambda. A Elven Log Extension lê esses logs pela Lambda Logs API e envia para o Collector.

Se CloudWatch tem logs e a Elven não:

* valide se a extension iniciou;
* valide se `/logs` da extension recebeu batches;
* valide se o Collector recebeu `/v1/logs`;
* valide export do Collector para Loki.

Habilite debug por poucos minutos:

```bash
ENV_ATUAL=$(aws lambda get-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --query "Environment.Variables" \
  --output json)

ENV_DEBUG=$(jq -s '.[0] * {"DEBUG":"true"}' <(echo "$ENV_ATUAL"))
ENV_PAYLOAD=$(jq -n --argjson vars "$ENV_DEBUG" '{Variables: $vars}')

aws lambda update-function-configuration \
  --function-name "$FUNCTION_NAME" \
  --region "$REGION" \
  --environment "$ENV_PAYLOAD"
```

Depois da validação, volte `DEBUG=false`.

#### `buffer full`

Sintoma: CloudWatch mostra warning de log descartado por buffer cheio.

Causas comuns:

* função escreve muitos logs em pouco tempo;
* Collector está lento ou indisponível;
* timeout/retry segurando o worker;
* função com pouca memória.

Ações:

* reduza volume de logs;
* aumente memória da função;
* reduza `BATCH_SIZE` para flush mais frequente;
* valide latência e disponibilidade do Collector;
* mantenha `HTTP_TIMEOUT` razoável para não bloquear a Lambda por muito tempo.

#### Labels antigos no Loki não funcionam

Consultas antigas podem usar labels como:

```logql
{function_name="minha-funcao"}
```

No fluxo OTLP nativo, use os atributos padronizados:

```logql
{service_name="minha-funcao"}
```

ou filtros por metadata conforme a configuração do Loki/Collector.

Se uma query antiga precisa continuar funcionando, configure transformação no Collector com cuidado para evitar cardinalidade excessiva.

***

### FAQ

#### A telemetria vai para um endpoint compartilhado da Elven?

Não. A Lambda envia OTLP para o Collector do cliente. Esse Collector fica na infraestrutura do cliente e encaminha para os backends configurados pela Elven.

#### Preciso colocar `LOKI_AUTH_TOKEN` na Lambda?

Não no modelo atual. O token de Loki fica server-side no Collector.

#### Preciso da layer oficial `opentelemetry-collector` na Lambda?

Não no padrão Elven. O Collector roda como componente de infraestrutura do cliente. A layer de Collector só é indicada para casos avançados.

#### A Elven Log Extension funciona com Go ou .NET?

Sim para logs. Ela captura logs pela Lambda Logs API e independe do runtime.

Para traces automáticos em Go/.NET, use instrumentação adequada ao runtime ou instrumentação manual. A tabela de layers OTel oficiais deste guia cobre Node.js, Python, Java e Ruby.

#### Posso usar com função em VPC?

Sim. Garanta rota privada ou NAT/security group para a Lambda alcançar o Collector do cliente.

#### Posso usar X-Ray junto?

Sim, mantendo `xray` em `OTEL_PROPAGATORS`. Em geral, evite habilitar export duplicado para dois sistemas sem necessidade.

Quando a versão mudar, atualize os ARNs da layer OTel no IaC ou scripts de rollout.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.elven.works/elven-platform/elven-observability/integracao-e-instrumentacao/aws-lambda/instrumentando-aws-lambda-com-elven-observability.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
