elven-instrumentation-serverless-plugin
v1.1.0
Published
Serverless Framework plugin to add Elven observability layers and environment variables automatically.
Maintainers
Readme
Instrumentação Lambda com Serverless Framework e Elven Plugin
Guia prático para instrumentar funções AWS Lambda com o elven-instrumentation-serverless-plugin, incluindo seleção automática de layers para node, python, ruby, javaagent e javawrapper.
Visão geral
O plugin automatiza três partes da instrumentação:
- Adiciona a layer OpenTelemetry correta para o runtime da função.
- Adiciona a Elven Log Extension correta para
x86_64ouarm64. - Injeta as variáveis de ambiente de traces e logs sem sobrescrever o que já existe na função.
O runtime efetivo é resolvido nesta ordem:
functions.<nome>.elvenRuntimecustom.elvenLayerPlugin.runtimenode
Se provider.runtime ou functions.<nome>.runtime indicarem claramente outra linguagem, o plugin mostra um warning, mas não muda a configuração sozinho.
Instalação
npm install --save-dev elven-instrumentation-serverless-pluginplugins:
- elven-instrumentation-serverless-pluginQuick start
Serviço homogêneo
service: minha-api
provider:
name: aws
runtime: python3.12
region: us-east-1
stage: ${opt:stage, 'dev'}
plugins:
- elven-instrumentation-serverless-plugin
custom:
elvenLayerPlugin:
tenant: "seu-tenant-id"
token: "seu-api-token"
collector_endpoint: "https://otel-collector.minha-infra.com:4318"
runtime: python
functions:
hello:
handler: handler.helloServiço misto
service: mixed-service
provider:
name: aws
runtime: nodejs22.x
region: us-east-1
plugins:
- elven-instrumentation-serverless-plugin
custom:
elvenLayerPlugin:
tenant: "seu-tenant-id"
token: "seu-api-token"
collector_endpoint: "https://otel-collector.minha-infra.com:4318"
runtime: node
functions:
api:
handler: src/api.handler
worker:
handler: src/worker.handler
elvenRuntime: python
architecture: arm64
billing:
handler: com.example.BillingHandler::handleRequest
elvenRuntime: javaagentOutput esperado
✅ [Elven] Instrumented function: mixed-service_dev_api (runtime=node, arch=x86_64)
✅ [Elven] Instrumented function: mixed-service_dev_worker (runtime=python, arch=arm64)
✅ [Elven] Instrumented function: mixed-service_dev_billing (runtime=javaagent, arch=x86_64)
📍 [Elven] Region: us-east-1
🧩 [Elven] Default runtime: node
🏗️ [Elven] Default architecture: x86_64
📦 [Elven] Instrumented functions: 3Configuração do plugin
Todas as opções ficam em custom.elvenLayerPlugin:
custom:
elvenLayerPlugin:
tenant: "seu-tenant-id"
token: "seu-api-token"
collector_endpoint: "https://otel-collector.minha-infra.com:4318"
region: "us-east-1"
runtime: "node" # node | python | ruby | javaagent | javawrapper
architecture: "x86_64"
logs_endpoint: "https://loki.elvenobservability.com"
log_version: "8"
log_version_arm64: "7"
enabled_instrumentations: "http,express,pg"
disabled_instrumentations: "flask,sidekiq"
layers:
- "arn:aws:lambda:us-east-1:111111111111:layer:custom-otel:5"
- "arn:aws:lambda:us-east-1:111111111111:layer:custom-log:9"Opções disponíveis
| Opção | Default | Descrição |
| --- | --- | --- |
| tenant | "default-tenant" | Tenant da Elven |
| token | "" | Token de autenticação |
| collector_endpoint | "" | URL do seu collector OTLP |
| region | us-east-1 | Região usada nos ARNs das layers |
| runtime | node | Runtime padrão do serviço |
| architecture | x86_64 | Arquitetura padrão do serviço |
| logs_endpoint | https://loki.elvenobservability.com | URL base do Loki |
| log_version | 8 | Versão da log extension para x86_64 |
| log_version_arm64 | 7 | Versão da log extension para arm64 |
| enabled_instrumentations | lista default Node | Instrumentações habilitadas para Node.js |
| disabled_instrumentations | "" | Instrumentações desabilitadas para Node, Python ou Ruby |
| layers | automático | Override completo das layers para todas as funções instrumentadas |
Valores suportados para runtime
| Valor | Observação |
| --- | --- |
| node | valor recomendado para Node.js |
| nodejs | alias aceito para node |
| python | usa a layer Python |
| ruby | usa a layer Ruby |
| javaagent | usa o Java agent |
| javawrapper | usa o Java wrapper |
Controle por função
Desabilitar a instrumentação
functions:
internal:
handler: src/internal.handler
disableElven: trueEscolher runtime por função
functions:
api:
handler: src/api.handler
# usa o runtime global
worker:
handler: src/worker.handler
elvenRuntime: python
billing:
handler: com.example.BillingHandler::handleRequest
elvenRuntime: javawrapperSobrescrever variáveis manualmente
O plugin não sobrescreve variáveis de ambiente já definidas na função:
functions:
heavy-worker:
handler: src/worker.handler
elvenRuntime: python
environment:
OTEL_TRACES_SAMPLER: "traceidratio"
OTEL_TRACES_SAMPLER_ARG: "0.1"Variáveis de ambiente injetadas
Comuns a todos os runtimes
| Variável | Valor |
| --- | --- |
| AWS_LAMBDA_EXEC_WRAPPER | /opt/otel-handler |
| OTEL_SERVICE_NAME | {service}_{stage}_{function} |
| OTEL_TRACES_SAMPLER | always_on |
| OTEL_LAMBDA_TRACE_MODE | capture |
| OTEL_PROPAGATORS | tracecontext,baggage,xray |
| OTEL_RESOURCE_ATTRIBUTES | service.name=...,environment=... |
| OTEL_EXPORTER_OTLP_ENDPOINT | collector_endpoint |
| TENANT_ID | tenant |
| SERVICE_NAME | {service}_{stage}_{function} |
| RESOURCES_ATTRIBUTES | service=...,environment=... |
| API_TOKEN | token |
| LOKI_URL | logs_endpoint |
| LOKI_TENANT_ID | tenant |
| LOKI_AUTH_TOKEN | token |
| DEBUG | false |
Específicas por runtime
| Runtime | Variáveis |
| --- | --- |
| node | OTEL_NODE_ENABLED_INSTRUMENTATIONS, OTEL_NODE_DISABLED_INSTRUMENTATIONS |
| python | OTEL_PYTHON_DISABLED_INSTRUMENTATIONS |
| ruby | OTEL_RUBY_DISABLED_INSTRUMENTATIONS |
| javaagent | OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED=true |
| javawrapper | OTEL_INSTRUMENTATION_COMMON_DEFAULT_ENABLED=true |
enabled_instrumentationsé uma opção específica de Node.js. Para Python e Ruby, o plugin só mapeiadisabled_instrumentations.
Layers padrão
OpenTelemetry por runtime
| Runtime | ARN |
| --- | --- |
| node | arn:aws:lambda:{region}:184161586896:layer:opentelemetry-nodejs-0_21_0:1 |
| python | arn:aws:lambda:{region}:184161586896:layer:opentelemetry-python-0_19_0:1 |
| ruby | arn:aws:lambda:{region}:184161586896:layer:opentelemetry-ruby-0_13_0:1 |
| javaagent | arn:aws:lambda:{region}:184161586896:layer:opentelemetry-javaagent-0_19_0:1 |
| javawrapper | arn:aws:lambda:{region}:184161586896:layer:opentelemetry-javawrapper-0_19_0:1 |
Elven Log Extension por arquitetura
| Arquitetura | ARN |
| --- | --- |
| x86_64 | arn:aws:lambda:{region}:911167927290:layer:elven-lambda-log-extension:{version} |
| arm64 | arn:aws:lambda:{region}:911167927290:layer:elven-lambda-log-extension-arm64:{version} |
Override completo das layers
Ao definir custom.elvenLayerPlugin.layers, o plugin usa exatamente a lista informada em todas as funções instrumentadas:
custom:
elvenLayerPlugin:
runtime: ruby
layers:
- "arn:aws:lambda:us-east-1:111111111111:layer:custom-otel:5"
- "arn:aws:lambda:us-east-1:111111111111:layer:custom-log:9"As variáveis de ambiente continuam sendo resolvidas pelo runtime efetivo.
Exemplos completos
Node.js padrão
provider:
name: aws
runtime: nodejs22.x
custom:
elvenLayerPlugin:
tenant: ${env:ELVEN_TENANT}
token: ${env:ELVEN_TOKEN}
collector_endpoint: "https://otel-collector.minha-infra.com:4318"
runtime: nodePython com arm64
provider:
name: aws
runtime: python3.12
architecture: arm64
custom:
elvenLayerPlugin:
tenant: ${env:ELVEN_TENANT}
token: ${env:ELVEN_TOKEN}
collector_endpoint: "https://otel-collector.minha-infra.com:4318"
runtime: pythonServiço misto Node + Python + Java
custom:
elvenLayerPlugin:
tenant: ${env:ELVEN_TENANT}
token: ${env:ELVEN_TOKEN}
collector_endpoint: "https://otel-collector.minha-infra.com:4318"
runtime: node
functions:
api:
handler: src/api.handler
worker:
handler: src/worker.handler
elvenRuntime: python
billing:
handler: com.example.BillingHandler::handleRequest
elvenRuntime: javaagentTroubleshooting
Erro de layer inexistente
Verifique:
regionlog_versionelog_version_arm64- se o runtime efetivo está correto para a função
Exemplo para validar a layer Node:
aws lambda get-layer-version \
--layer-name opentelemetry-nodejs-0_21_0 \
--version-number 1 \
--region us-east-1 \
--query "LayerVersionArn"Warning de runtime incompatível
Exemplo típico:
provider.runtime: python3.12custom.elvenLayerPlugin.runtime: node
Nesse caso o plugin avisa, mas continua usando o runtime Elven explícito.
Traces ou logs não aparecem
Verifique:
collector_endpointtenantetoken- se a função recebeu a layer OTel correta para o runtime
- se
LOKI_URLestá configurado como URL base, sem/loki/api/v1/push
FAQ
Preciso configurar cada função individualmente?
Não. Só use elvenRuntime quando a função fugir do runtime global.
O plugin funciona com outros runtimes além de Node.js?
Sim. Há suporte automático para node, python, ruby, javaagent e javawrapper.
O plugin sobrescreve minhas layers?
Não. Ele só adiciona o que falta e evita duplicação.
O plugin sobrescreve minhas variáveis de ambiente?
Não. Variáveis já definidas na função têm prioridade.
Posso continuar usando layers customizadas?
Sim. Use custom.elvenLayerPlugin.layers.
Como atualizo a versão das layers padrão?
Para a log extension, altere log_version e log_version_arm64. Para a layer OTel, use layers se precisar sair dos defaults do plugin.
Quais runtimes do Lambda fazem mais sentido hoje?
Em abril de 2026, para novas funções AWS Lambda, a recomendação geral é preferir nodejs22.x ou nodejs24.x, python3.12+, java21 e ruby3.3+, conforme compatibilidade do seu projeto e da sua versão do Serverless Framework.
