Skip to main content

Deploy Alloy for Windows Host Monitoring

Introduction

Alloy is Grafana’s distribution of the OpenTelemetry (OTel) Collector. You can use Alloy to collect system metrics and logs from Windows servers. Alloy uses a configuration file, config.alloy, to define the scrape, processing, and forwarding pipelines for metrics and logs. This topic explains how to deploy and configure Alloy on Windows hosts to send metrics and logs to your monitoring backend.

Prerequisites

OTel Metric Collector must be running and accessible on an external port.

  1. Open the values.yaml file.

    • Locate the otel-metric-collector configuration section.

    • Change the service type from ClusterIP to either NodePort or LoadBalancer.

      otel-metric-collector:
        service:
          type: LoadBalancer # or NodePort
  2. Run kubectl get svc -n opscruise to find the Metrics Endpoint and Port.

    • Notate the endpoint with <address>:<port> format to add to the alloy.config

  3. Loki Service Endpoint Listening on Externally Accessible Port

    • In the values.yaml, modify the Loki service to change it from the default type to NodePort or LoadBalancer:

      loki-stack:
        loki:
          service:
            type: LoadBalancer # or NodePort
  4. Run kubectl get svc -n opscruise to find the Metrics Endpoint and Port

    • Notate the endpoint with: http:<loki-endpoint>:3100/loki/api/v1/push format to add to the alloy.config

Additional Prerequisites:

  • Ensure that the Windows Server image (tested with Windows Server 2025 Datacenter) is running on the host.

  • This is required to enable DNS and DHCP application object discovery.

Configuring Alloy

Update the above-mentioned endpoints in the config.alloy file based on your environment.

logging "debug" {

  level  = "debug"

  format = "logfmt"

}

declare "collect_forward_metrics" {

  argument "scrape_interval" {

    optional = false

    comment = "prometheus remote write endpoint"

  }

  argument "otel_export_endpoint" {

    optional = false

    comment = "otel grpc-otlp remote endpoint"

  }

  argument "prometheus_remote_write_endpoint" {

    optional = false

    comment = "prometheus remote write endpoint"

  }

  argument "exporter_enabled_collectors" {

    optional = false

    comment = "prometheus remote write endpoint"

  }

  //enabled_collectors = ["*"]

  prometheus.exporter.windows "default" {

                enabled_collectors = argument.exporter_enabled_collectors.value

  }

  // Configure a prometheus.scrape component to collect process_exporter metrics.

  prometheus.scrape "prom_scrape" {

    targets = prometheus.exporter.windows.default.targets

    forward_to = [prometheus.remote_write.prom_remote_write.receiver, otelcol.receiver.prometheus.default.receiver]

    scrape_interval = argument.scrape_interval.value

    //metrics_path    = "/api/v0/component/prometheus.exporter.windows.default/metrics"

  }

  prometheus.remote_write "prom_remote_write" {

    endpoint {

      url = argument.prometheus_remote_write_endpoint.value

    }

  }

  otelcol.receiver.prometheus "default" {

    output {

      metrics = [otelcol.exporter.otlp.metrics.input]

    }

  }

  otelcol.exporter.otlp "metrics" {

    client {

      endpoint = argument.otel_export_endpoint.value

      tls {

        insecure             = true

        insecure_skip_verify = true

      }

    }

  }

}

// Windows LOG Collection

declare "collect_forward_logs"  {

  argument "loki_write_endpoint" {

    optional = false

    comment = "otel grpc-otlp remote endpoint"

  }

  local.file_match "tmplogs" {

      path_targets = [{"__path__" = "/tmp/alloy-logs/*.log",  "path_type" = "dynamic_path"}]

  }

  loki.source.file "local_files" {

      targets    = local.file_match.tmplogs.targets

      forward_to = [loki.write.loki_endpoint.receiver]

  }

  loki.source.file "local_files_direct" {

      targets    = [{"__path__" = "/tmp/alloy-logs/log.log", "path_type" = "direct_path"}]

      forward_to = [loki.write.loki_endpoint.receiver]

  }

  loki.source.windowsevent "win_application_events"  {

      eventlog_name = "Application"

      forward_to = [otelcol.receiver.loki.default.receiver]

      labels = {

        job = "logs/windows_application",

        host = "host.name",

        namespace = "windowsNamespaceForVirtanaCO",

      }

  }

  loki.source.windowsevent "win_system_events"  {

      eventlog_name = "System"

      forward_to = [otelcol.receiver.loki.default.receiver]

      labels = {

        job = "logs/windows_system",

        namespace = "windowsNamespaceForVirtanaCO",

      }

  }

  loki.source.windowsevent "win_security_events"  {

      eventlog_name = "Security"

      forward_to = [otelcol.receiver.loki.default.receiver]

      labels = {

        job = "logs/windows_security",

        namespace = "windowsNamespaceForVirtanaCO",

      }

  }

  loki.source.windowsevent "win_forwarded_events"  {

      eventlog_name = "ForwardedEvents"

      forward_to = [otelcol.receiver.loki.default.receiver]

      labels = {

        job = "logs/windows_forwarded",

        namespace = "windowsNamespaceForVirtanaCO",

      }

  }

  loki.source.windowsevent "win_setup_events"  {

      eventlog_name = "Setup"

      forward_to = [otelcol.receiver.loki.default.receiver]

      labels = {

        job = "logs/windows_setup",

        namespace = "windowsNamespaceForVirtanaCO",

      }

  }

  otelcol.receiver.loki "default" {

    output {

      logs = [otelcol.processor.transform.set_labels.input]

    }

  }

  otelcol.processor.transform "set_labels" {

    error_mode = "ignore"

    log_statements {

      context = "log"

      statements = [

        `set(attributes["host"],attributes["computer"]) where attributes["computer"] != nil`,

      ]

    }

    output {

      //metrics = [otelcol.exporter.otlp.default.input]

      logs    = [otelcol.exporter.loki.default.input]

      //traces  = [otelcol.exporter.otlp.default.input]

    }

  }

  otelcol.exporter.loki "default" {

    forward_to = [loki.write.loki_endpoint.receiver]

  }

  loki.write "loki_endpoint" {

      endpoint {

          url = argument.loki_write_endpoint.value

      }

  }

}

// Configuraion fields

collect_forward_metrics "metrics" {

  otel_export_endpoint = "<otel_endpoint>:4317"

  prometheus_remote_write_endpoint  = "http://localhost:9090/api/v1/write"

  exporter_enabled_collectors  = ["os","cpu", "cpu_info","cs","memory","logical_disk","net","service","system","network","process","physical_disk"]

  scrape_interval = "15s"

}

collect_forward_logs "logs" {

  loki_write_endpoint = "http://<loki-endpoint>:3100/loki/api/v1/push"

}

 

Below Config have to provided while apply config file[config.alloy]

// Configuraion fields

collect_forward_metrics "metrics" {

  scrape_interval = "15s"

  otel_export_endpoint = "<otel_endpoint>:4317"

  prometheus_remote_write_endpoint  = "http://localhost:9090/api/v1/write"

  exporter_enabled_collectors  = ["os","cpu", "cpu_info","cs","memory","logical_disk","net","service","system","network","process","physical_disk"]

}

collect_forward_logs "logs" {

  loki_write_endpoint = "http://<loki-endpoint>:3100/loki/api/v1/push"

}

Metrics collected from Alloy are sent to the otel_export_endpoint or prometheus_remote_write_endpoint.

Once delivered, the metrics undergo processing through:

  • Prometheus recording rules, or

  • OTel transformations

Installation

For details on installing Alloy on Windows, see Alloy installation

Running Alloy

After installation, start Alloy with the following command:

alloy-windows-amd64.exe run config.alloy --storage.path=data

This command runs Alloy using your config.alloy configuration and stores temporary state in the data directory.