Pular para o conteúdo

Comandos Grafana Alloy

Grafana Alloy é uma distribuição OpenTelemetry flexível e agnóstica de fornecedor para coletar, processar e exportar dados telemétricos (métricas, logs, traces). Sucessor do Grafana Agent, usa uma linguagem de configuração baseada em componentes.

Instalação

Repositórios de Pacotes Linux

Debian/Ubuntu

sudo mkdir -p /etc/apt/keyrings/
wget -qO - https://apt.grafana.com/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/grafana.gpg
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get install alloy

RHEL/CentOS/Fedora

sudo tee /etc/yum.repos.d/grafana.repo << EOF
[grafana]
name=grafana
baseurl=https://rpm.grafana.com
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://rpm.grafana.com/gpg.key
EOF
sudo dnf install alloy

macOS

brew install grafana/grafana/alloy
alloy --version

Download de Binário

# Baixar versão mais recente
wget https://github.com/grafana/alloy/releases/download/v1.14.0/alloy-v1.14.0-linux-amd64.zip
unzip alloy-v1.14.0-linux-amd64.zip
sudo mv alloy /usr/local/bin/
alloy --version

Docker

docker pull grafana/alloy:latest
docker run -v /path/to/config.alloy:/etc/alloy/config.alloy \
  grafana/alloy:latest run /etc/alloy/config.alloy --server.http.listen-addr=0.0.0.0:12345

Helm Chart

helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm install alloy grafana/alloy --namespace monitoring --create-namespace \
  -f values.yaml

Comandos Básicos

ComandoDescrição
alloy run config.alloyExecutar Alloy com arquivo de configuração especificado
alloy run config.alloy --server.http.listen-addr=0.0.0.0:12345Executar com endereço de servidor HTTP customizado para UI
alloy fmt config.alloyFormatar e validar arquivo de configuração (dry-run)
alloy fmt -w config.alloyFormatar arquivo de configuração no lugar
alloy tools parse config.alloyAnalisar e validar sintaxe de configuração
alloy tools lint config.alloyValidar configuração para problemas
alloy --versionExibir versão do Alloy
alloy --helpMostrar informações de ajuda
alloy run --helpMostrar opções do comando run

Conceitos Básicos de Configuração

Extensão de Arquivo e Sintaxe

Alloy usa extensão de arquivo .alloy com linguagem de configuração baseada em componentes (similar a HCL).

Estrutura Básica

// Comentários usam //

// Instanciação de componente: <component_type>.<unique_name> { ... }
prometheus.scrape "example" {
  targets = [{"__address__" = "localhost:9090"}]
  forward_to = [prometheus.remote_write.grafana.receiver]
}

// Exportar dados de componente para outro
prometheus.remote_write "grafana" {
  endpoint {
    url = "https://prometheus.grafana.net/api/prom/push"
    headers = {
      "Authorization" = "Bearer ${GRAFANA_TOKEN}"
    }
  }
}

Variáveis e Segredos

// Variáveis de ambiente
GRAFANA_TOKEN = env("GRAFANA_TOKEN")
PROMETHEUS_URL = env("PROMETHEUS_URL")

// Variáveis locais
local "my_targets" {
  value = [
    {"__address__" = "localhost:9090"},
    {"__address__" = "localhost:9100"},
  ]
}

// Referenciar variáveis
prometheus.scrape "nodes" {
  targets = local.my_targets.value
}

Blocos de Argumento e Exportação

// A maioria dos componentes aceita argumentos
prometheus.scrape "example" {
  targets    = [{"__address__" = "localhost:9090"}]
  scrape_interval = "30s"
  scrape_timeout  = "10s"
  forward_to = [prometheus.remote_write.grafana.receiver]
}

// Componentes exportam dados (visíveis na UI em Exports)
// Exemplo: prometheus.scrape exporta scraped_targets e targets

Componentes - Fontes

Prometheus Scrape

prometheus.scrape "kubernetes" {
  targets    = discovery.kubernetes.nodes.targets
  scrape_interval = "30s"
  scrape_timeout  = "10s"
  metrics_path    = "/metrics"
  scheme          = "http"

  forward_to = [prometheus.relabel.drop_internal.receiver]
}

Loki File Source

loki.source.file "app_logs" {
  targets = [
    {
      __path__ = "/var/log/app/*.log",
      job      = "app",
      env      = "production",
    }
  ]

  forward_to = [loki.relabel.add_labels.receiver]
}

Receptor OpenTelemetry (OTLP)

otelcol.receiver.otlp "default" {
  grpc {
    endpoint = "0.0.0.0:4317"
  }

  http {
    endpoint = "0.0.0.0:4318"
  }

  output {
    traces  = [otelcol.processor.batch.default.input]
    metrics = [otelcol.processor.batch.default.input]
    logs    = [otelcol.processor.batch.default.input]
  }
}

Receptor Prometheus Remote Write

prometheus.receive_http "example" {
  http {
    address = "0.0.0.0:9009"
  }

  forward_to = [prometheus.relabel.example.receiver]
}

Servidor API Loki

loki.relabel "add_labels" {
  forward_to = [loki.write.grafana.receiver]

  rule {
    source_labels = ["__path__"]
    target_label  = "job"
    replacement   = "app-logs"
  }
}

Componentes - Processadores

Processador em Lote

otelcol.processor.batch "default" {
  send_batch_size    = 1000
  timeout            = "10s"
  send_batch_max_size = 2000

  output {
    traces  = [otelcol.exporter.otlp.grafana.input]
    metrics = [otelcol.exporter.prometheus.grafana.input]
    logs    = [otelcol.exporter.loki.grafana.input]
  }
}

Processador de Filtro

otelcol.processor.filter "drop_internal" {
  metrics {
    exclude {
      match_type = "regexp"
      regexp     = "internal_.*"
    }
  }

  output {
    metrics = [otelcol.exporter.prometheus.grafana.input]
  }
}

Processador de Detecção de Recurso

otelcol.processor.resourcedetection "default" {
  detectors = ["env", "system", "gcp", "aws", "azure", "docker", "kubernetes"]

  output {
    traces  = [otelcol.processor.batch.default.input]
    metrics = [otelcol.processor.batch.default.input]
    logs    = [otelcol.processor.batch.default.input]
  }
}

Processador de Atributo

otelcol.processor.attributes "add_env" {
  action {
    key    = "environment"
    value  = "production"
    action = "insert"
  }

  action {
    key         = "pod_name"
    from_attribute = "k8s.pod.name"
    action      = "insert"
  }

  output {
    traces  = [otelcol.processor.batch.default.input]
    metrics = [otelcol.processor.batch.default.input]
    logs    = [otelcol.processor.batch.default.input]
  }
}

Processador de Limitador de Memória

otelcol.processor.memory_limiter "default" {
  check_interval       = "5s"
  limit_mib            = 512
  spike_limit_mib      = 256

  output {
    traces  = [otelcol.processor.batch.default.input]
    metrics = [otelcol.processor.batch.default.input]
    logs    = [otelcol.processor.batch.default.input]
  }
}

Processador de Span (Traces)

otelcol.processor.span "extract_attributes" {
  name {
    to_attributes {
      rules = ["^/api/(?P<version>v\\d)/(?P<resource>\\w+)"]
    }
  }

  output {
    traces = [otelcol.processor.batch.default.input]
  }
}

Componentes - Exportadores

Prometheus Remote Write

prometheus.remote_write "grafana" {
  endpoint {
    url = "https://prometheus.grafana.net/api/prom/push"

    basic_auth {
      username = "GRAFANA_USER_ID"
      password = "${GRAFANA_TOKEN}"
    }

    headers = {
      "X-Custom-Header" = "value"
    }

    tls_config {
      insecure_skip_verify = false
    }
  }

  wal {
    enabled = true
    directory = "/var/lib/alloy/wal"
  }

  queue_settings {
    capacity = 10000
  }
}

Loki Write

loki.write "grafana" {
  endpoint {
    url = "https://logs.grafana.net/loki/api/v1/push"

    basic_auth {
      username = "GRAFANA_USER_ID"
      password = "${GRAFANA_TOKEN}"
    }
  }

  tenant_id = "production"
}

Exportador OpenTelemetry (OTLP)

otelcol.exporter.otlp "grafana_cloud" {
  client {
    endpoint = "tempo.grafana.net:4317"

    auth = otelcol.auth.basic "grafana" {}

    tls {
      insecure = false
    }
  }

  retry_on_failure {
    enabled       = true
    initial_interval = "5s"
    max_interval  = "30s"
    max_elapsed_time = "5m"
  }
}

Autenticação OTLP

otelcol.auth.basic "grafana" {
  username = "GRAFANA_USER_ID"
  password = "${GRAFANA_TOKEN}"
}

// OTLP com autenticação básica
otelcol.exporter.otlp "example" {
  client {
    endpoint = "tempo.grafana.net:4317"
    auth = otelcol.auth.basic.grafana.handler
  }
}

Exportador Prometheus (Estilo Node Exporter)

prometheus.exporter.unix "local_system" {
  disabled_collectors = ["netdev", "netstat"]
}

prometheus.scrape "local_system" {
  targets = prometheus.exporter.unix.local_system.targets
  forward_to = [prometheus.remote_write.grafana.receiver]
}

Componentes - Descoberta

Descoberta Kubernetes

discovery.kubernetes "cluster" {
  role = "pod"
  namespaces {
    names = ["default", "monitoring", "production"]
  }
}

prometheus.scrape "kubernetes" {
  targets    = discovery.kubernetes.cluster.targets
  forward_to = [prometheus.remote_write.grafana.receiver]

  relabel_configurations {
    source_labels = ["__meta_kubernetes_pod_annotation_prometheus_io_scrape"]
    regex         = "true"
    action        = "keep"
  }
}

Descoberta Docker

discovery.docker "local" {
  host = "unix:///var/run/docker.sock"
}

prometheus.scrape "docker" {
  targets    = discovery.docker.local.targets
  forward_to = [prometheus.remote_write.grafana.receiver]
}

Descoberta Consul

discovery.consul "example" {
  server   = "localhost:8500"
  datacenter = "dc1"
  services = ["prometheus", "app"]
}

prometheus.scrape "consul" {
  targets    = discovery.consul.example.targets
  forward_to = [prometheus.remote_write.grafana.receiver]
}

Descoberta Baseada em Arquivo

discovery.file "dynamic_targets" {
  files = ["/etc/alloy/targets.json"]
  refresh_interval = "30s"
}

prometheus.scrape "file_targets" {
  targets    = discovery.file.dynamic_targets.targets
  forward_to = [prometheus.remote_write.grafana.receiver]
}

Coleta de Métricas

Scraping Prometheus com Relabeling

prometheus.scrape "prometheus" {
  targets = [
    {
      __address__ = "prometheus.example.com:9090",
      job         = "prometheus",
    },
    {
      __address__ = "alertmanager.example.com:9093",
      job         = "alertmanager",
    },
  ]

  metrics_path    = "/metrics"
  scrape_interval = "30s"
  scrape_timeout  = "10s"

  relabel_configurations {
    source_labels = ["__address__"]
    target_label  = "instance"
    regex         = "([^:]+)(?::\\d+)?"
    replacement   = "${1}"
  }

  metric_relabel_configurations {
    source_labels = ["__name__"]
    regex         = "up|job|instance"
    action        = "keep"
  }

  forward_to = [prometheus.relabel.drop_internal.receiver]
}

Integração Node Exporter

prometheus.exporter.unix "node_metrics" {
  collectors = ["cpu", "diskstats", "filesystem", "loadavg", "meminfo", "netdev", "netstat"]
  disabled_collectors = ["netdev"]
  set_collectors = ["textfile"]
  textfile_directory = "/var/lib/node_exporter/textfile_collector"
}

prometheus.scrape "node_exporter" {
  targets    = prometheus.exporter.unix.node_metrics.targets
  forward_to = [prometheus.remote_write.grafana.receiver]
}

Endpoint de Métricas Customizado

prometheus.scrape "custom_app" {
  targets = [
    {
      __address__ = "app.example.com:8080",
      __metrics_path__ = "/api/metrics",
      job = "custom-app",
      env = "production",
    },
  ]

  scrape_interval = "15s"
  forward_to = [prometheus.remote_write.grafana.receiver]
}

Coleta de Logs

Tail de Arquivo com Loki

loki.source.file "application" {
  targets = [
    {
      __path__ = "/var/log/app/app.log",
      job      = "app",
      service  = "web",
      env      = "production",
    },
    {
      __path__ = "/var/log/app/error.log",
      job      = "app",
      level    = "error",
    },
  ]

  forward_to = [loki.relabel.add_labels.receiver]
}

Logs de Journal (systemd)

loki.source.journal "systemd" {
  path   = "/var/log/journal"
  labels = {
    job = "systemd",
  }

  forward_to = [loki.relabel.add_labels.receiver]
}

Analisar Logs JSON

loki.relabel "parse_json" {
  forward_to = [loki.process.extract_json.receiver]

  rule {
    source_labels = ["__path__"]
    target_label  = "filename"
  }
}

loki.process "extract_json" {
  forward_to = [loki.write.grafana.receiver]

  stage {
    json {
      expressions = {
        timestamp = "ts",
        message   = "msg",
        level     = "level",
        service   = "service",
      }
    }
  }

  stage {
    labels {
      values = {
        level   = "level",
        service = "service",
      }
    }
  }

  stage {
    timestamp {
      source = "timestamp"
      format = "Unix"
    }
  }
}

Logs Multilinhas (Stack Traces)

loki.process "multiline" {
  forward_to = [loki.write.grafana.receiver]

  stage {
    multiline {
      line_start_pattern = "^\\d{4}-\\d{2}-\\d{2}"
    }
  }

  stage {
    regex {
      expression = "^(?P<timestamp>\\d{4}-\\d{2}-\\d{2}) (?P<level>\\w+) (?P<message>.*)"
    }
  }

  stage {
    labels {
      values = {
        level = "level",
      }
    }
  }
}

Coleta de Traces

Pipeline de Traces OpenTelemetry

otelcol.receiver.otlp "app" {
  grpc {
    endpoint = "0.0.0.0:4317"
  }

  http {
    endpoint = "0.0.0.0:4318"
  }

  output {
    traces = [otelcol.processor.memory_limiter.default.input]
  }
}

otelcol.processor.memory_limiter "default" {
  check_interval  = "5s"
  limit_mib       = 512
  spike_limit_mib = 256

  output {
    traces = [otelcol.processor.batch.default.input]
  }
}

otelcol.processor.batch "default" {
  send_batch_size = 100
  timeout         = "10s"

  output {
    traces = [otelcol.exporter.otlp.grafana.input]
  }
}

otelcol.exporter.otlp "grafana" {
  client {
    endpoint = "tempo.grafana.net:4317"
    auth = otelcol.auth.basic.grafana.handler
  }
}

otelcol.auth.basic "grafana" {
  username = "GRAFANA_USER_ID"
  password = "${GRAFANA_TOKEN}"
}

Receptor Jaeger

otelcol.receiver.jaeger "default" {
  protocols {
    grpc {
      endpoint = "0.0.0.0:14250"
    }

    thrift_http {
      endpoint = "0.0.0.0:14268"
    }
  }

  output {
    traces = [otelcol.processor.batch.default.input]
  }
}

Receptor Zipkin

otelcol.receiver.zipkin "default" {
  endpoint = "0.0.0.0:9411"

  output {
    traces = [otelcol.processor.batch.default.input]
  }
}

Deployment Kubernetes

Valores Helm (values.yaml)

config: |
  otelcol.receiver.otlp "default" {
    grpc {
      endpoint = "0.0.0.0:4317"
    }
    http {
      endpoint = "0.0.0.0:4318"
    }
    output {
      traces = [otelcol.processor.batch.default.input]
    }
  }

  otelcol.processor.batch "default" {
    send_batch_size = 100
    output {
      traces = [otelcol.exporter.otlp.grafana.input]
    }
  }

  otelcol.exporter.otlp "grafana" {
    client {
      endpoint = "tempo.grafana.net:4317"
      auth = otelcol.auth.basic.grafana.handler
    }
  }

  otelcol.auth.basic "grafana" {
    username = "GRAFANA_USER_ID"
    password = "${GRAFANA_TOKEN}"
  }

alloy:
  remoteConfigUrl: ""

serviceAccount:
  create: true

rbac:
  create: true

daemonset:
  enabled: true

deployment:
  enabled: true
  replicas: 1

configMap:
  content: ""

livenessProbe:
  enabled: true

readinessProbe:
  enabled: true

Instalação Helm

# Instalar com valores customizados
helm install alloy grafana/alloy \
  --namespace monitoring \
  --create-namespace \
  -f values.yaml

# Atualizar instalação existente
helm upgrade alloy grafana/alloy \
  --namespace monitoring \
  -f values.yaml

# Desinstalar
helm uninstall alloy --namespace monitoring

Exemplo de DaemonSet

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: alloy
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: alloy
  template:
    metadata:
      labels:
        app: alloy
    spec:
      serviceAccountName: alloy
      containers:
      - name: alloy
        image: grafana/alloy:latest
        args:
        - run
        - /etc/alloy/config.alloy
        - --server.http.listen-addr=0.0.0.0:12345
        ports:
        - name: http
          containerPort: 12345
        - name: otlp-grpc
          containerPort: 4317
        - name: otlp-http
          containerPort: 4318
        volumeMounts:
        - name: config
          mountPath: /etc/alloy
        - name: varlog
          mountPath: /var/log
          readOnly: true
      volumes:
      - name: config
        configMap:
          name: alloy-config
      - name: varlog
        hostPath:
          path: /var/log
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: alloy-config
  namespace: monitoring
data:
  config.alloy: |
    prometheus.scrape "kubernetes" {
      targets = discovery.kubernetes.nodes.targets
      forward_to = [prometheus.remote_write.grafana.receiver]
    }

    discovery.kubernetes "nodes" {
      role = "node"
    }

    prometheus.remote_write "grafana" {
      endpoint {
        url = "https://prometheus.grafana.net/api/prom/push"
        basic_auth {
          username = "GRAFANA_USER_ID"
          password = "${GRAFANA_TOKEN}"
        }
      }
    }

Exemplo de ServiceMonitor

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: app-metrics
  namespace: production
spec:
  selector:
    matchLabels:
      app: myapp
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics

Configuração Docker

Arquivo Compose

version: '3.8'
services:
  alloy:
    image: grafana/alloy:latest
    container_name: alloy
    command:
      - run
      - /etc/alloy/config.alloy
      - --server.http.listen-addr=0.0.0.0:12345
    ports:
      - "12345:12345"
      - "4317:4317"
      - "4318:4318"
    volumes:
      - ./alloy-config.alloy:/etc/alloy/config.alloy
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/log:/var/log:ro
    environment:
      - GRAFANA_TOKEN=${GRAFANA_TOKEN}
    networks:
      - monitoring

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    networks:
      - monitoring

networks:
  monitoring:
    driver: bridge

Executar Container

# Executar com arquivo de configuração
docker run -d \
  --name alloy \
  -v /path/to/config.alloy:/etc/alloy/config.alloy \
  -p 12345:12345 \
  -p 4317:4317 \
  -p 4318:4318 \
  -e GRAFANA_TOKEN=$GRAFANA_TOKEN \
  grafana/alloy:latest run /etc/alloy/config.alloy \
  --server.http.listen-addr=0.0.0.0:12345

# Ver logs
docker logs -f alloy

# Parar container
docker stop alloy
docker rm alloy

Depuração

Acesso da Web UI

# Acessar Alloy UI (porta padrão 12345)
# Mostra status de componentes, exports, métricas
curl http://localhost:12345
# Browser: http://localhost:12345/graph

Níveis de Log

# Executar com logging de debug
alloy run config.alloy --log.level=debug

# Executar com logging de info (padrão)
alloy run config.alloy --log.level=info

# Executar com logging de aviso
alloy run config.alloy --log.level=warn

Validar Configuração

# Analisar configuração sem executar
alloy tools parse config.alloy

# Verificar erros de sintaxe
alloy fmt config.alloy

# Validar e verificar
alloy tools lint config.alloy

Inspecionar Componentes

# Ver todos os tipos de componente
alloy tools component list

# Obter documentação de componente
alloy tools component doc prometheus.scrape

# Mostrar schema de componente
alloy tools component schema prometheus.scrape

Profilamento Pprof

# Ativar servidor pprof (padrão: http://localhost:6060/debug/pprof)
alloy run config.alloy --pprof.enabled=true --pprof.address=0.0.0.0:6060

# Ver perfil de heap
curl http://localhost:6060/debug/pprof/heap > heap.prof
go tool pprof heap.prof

# Ver perfil de goroutine
curl http://localhost:6060/debug/pprof/goroutine

Inspeção de Traces

# Ativar rastreamento distribuído
alloy run config.alloy --traces.enabled=true

# Acessar UI de trace (se exposto)
curl http://localhost:12345/traces

Variáveis de Ambiente

VariávelDescrição
ALLOY_CONFIG_FILECaminho para arquivo de configuração
GRAFANA_TOKENToken de autenticação para Grafana Cloud
PROMETHEUS_URLEndpoint do servidor Prometheus
LOKI_URLEndpoint da API Loki
TEMPO_URLEndpoint da API Tempo
OTEL_EXPORTER_OTLP_ENDPOINTEndpoint do exportador OpenTelemetry OTLP
OTEL_EXPORTER_OTLP_HEADERSHeaders do exportador OTLP
OTEL_SDK_DISABLEDDesativar SDK OpenTelemetry
LOG_LEVELNível de logging: debug, info, warn, error
ALLOY_REMOTE_CONFIG_URLURL de configuração remota
NODE_NAMEIdentificador de nó (nome de nó k8s)
POD_NAMENome do pod (para k8s)
NAMESPACENamespace Kubernetes

Usando Variáveis de Ambiente

# Exportar variáveis
export GRAFANA_TOKEN="glc_xxx"
export PROMETHEUS_URL="https://prometheus.grafana.net"

# Executar Alloy
alloy run config.alloy

# Em config.alloy, referenciar com ${ }
prometheus.remote_write "grafana" {
  endpoint {
    url = "${PROMETHEUS_URL}/api/prom/push"
    basic_auth {
      password = "${GRAFANA_TOKEN}"
    }
  }
}

Recursos