Chapter 2. Monitor collector metrics


You can monitor and configure collector metrics to understand monitoring impact and reduce cardinality in multitenant environments.

The Vector log collector exposes Prometheus metrics that track log collection performance and health. In deployments with many inputs, outputs, and pipelines, these metrics can exhibit high cardinality. High cardinality increases resource consumption in the Red Hat OpenShift Logging monitoring stack.

Understanding how ClusterLogForwarder configuration affects metrics cardinality helps you balance tenant isolation requirements with monitoring stack stability.

Metrics cardinality refers to the number of unique time series created by a metric. Each unique combination of metric name and label values creates a separate time series. Prometheus must store and query each time series. For example, if a metric has labels component_id and namespace, and there are 100 unique component_id values and 50 unique namespace values, the potential cardinality is 100 × 50 = 5,000 time series for that metric.

High cardinality metrics require the following resources: more memory in Prometheus pods to store time series, more CPU to process queries across many series, more storage to persist historical data, and longer query response times.

The Vector log collector creates internal components for each stage of log processing. Each component is identified by a component_id label in Vector metrics. The number of components grows with the complexity of your ClusterLogForwarder configuration.

A ClusterLogForwarder with the following configuration:

  • 3 inputs (application, infrastructure, audit)
  • 2 outputs (LokiStack, Splunk)
  • 2 pipelines (one per output)

Creates these types of components:

  • Input source components (3)
  • Metadata enrichment transforms per input (3)
  • Filter transforms if configured (varies)
  • Routing and transformation components (varies)
  • Output sink components (2)

Each input typically requires multiple transformation stages before reaching an output. This creates 5-10 components per input-output path. In this example, you might have 30-50 unique component_id values.

In multitenant environments with many separate inputs, outputs, or pipelines for tenant isolation, the number of components can grow to hundreds:

  • 100 tenant-specific inputs
  • 50 tenant-specific outputs
  • 100 tenant-specific pipelines

This configuration can create 400-500 unique component_id values or more.

The following Vector metrics use the component_id label and are most affected by high cardinality:

vector_component_received_events_count_bucket
A histogram that tracks the number of events received by each component. This is typically the highest cardinality metric.
vector_buffer_send_duration_seconds_bucket
A histogram that tracks how long it takes to send events from buffers. This metric exhibits high cardinality because it tracks every component that sends data.
vector_source_lag_time_seconds_bucket
A histogram that tracks lag time for source components.
vector_adaptive_concurrency_*_bucket
Multiple histogram metrics that track adaptive concurrency behavior for outputs that support it. Each output creates multiple series.

Histogram metrics are particularly problematic. They create multiple time series per unique label combination (one per bucket plus sum and count).

A single component_id value in a histogram metric with 8 buckets creates:

  • 8 bucket series (le="0.001", le="0.01", …​ le="+Inf")
  • 1 sum series (_sum)
  • 1 count series (_count)

Total: 10 time series per component_id.

With 450 unique component_id values:

  • vector_component_received_events_count_bucket: 450 × 10 = 4,500 time series
  • vector_buffer_send_duration_seconds_bucket: 450 × 10 = 4,500 time series
  • Additional histogram metrics contribute similarly

High cardinality from Vector metrics affects the Red Hat OpenShift Logging monitoring stack in several ways:

Memory consumption
Prometheus stores all active time series data in memory. High cardinality can cause Prometheus pods to consume significantly more memory. This can potentially trigger out-of-memory (OOM) conditions.
CPU usage
Query processing time increases with the number of time series. High cardinality metrics slow down Prometheus queries and dashboard rendering.
Storage growth
Prometheus persistently stores time series data. High cardinality increases the rate of storage consumption. This can exhaust available storage faster than expected.
Query performance
Queries that aggregate across all component_id values become slower as cardinality increases. This affects monitoring dashboards and alerting evaluation.
Cluster stability

The monitoring stack is critical for cluster operations including:

  • Cluster upgrades
  • Horizontal pod autoscaling (HPA)
  • Vertical pod autoscaling (VPA)
  • Node management
  • Alerting

Monitoring stack instability or resource exhaustion can impact these operations.

Consider reviewing your ClusterLogForwarder configuration if:

  • You have more than 50 inputs, outputs, or pipelines across all ClusterLogForwarder instances
  • You have separate ClusterLogForwarder instances per tenant or namespace
  • Prometheus pods are consuming more memory than expected
  • Prometheus storage is growing faster than anticipated
  • Prometheus queries are slow or timing out
  • You observe high cardinality warnings in Prometheus logs

You can check the current cardinality of Vector metrics by using the Prometheus API. See "Troubleshooting high collector metrics cardinality" for diagnostic procedures.

You can configure the cluster monitoring operator to use metrics collection profiles. These profiles control how many metrics Prometheus collects from the log collector. The minimal profile reduces metrics cardinality by collecting only the metrics needed for alerts, dashboards, and telemetry.

Metrics collection profiles provide a supported method to reduce Prometheus resource consumption without manually editing ServiceMonitor resources. The Red Hat OpenShift Logging Operator automatically reverts manual edits to ServiceMonitor resources.

Prerequisites

  • You have access to the cluster as a user with the cluster-admin cluster role.
  • You have installed the OpenShift CLI (oc).

Procedure

  1. Edit the cluster monitoring configuration:

    $ oc edit configmap cluster-monitoring-config -n openshift-monitoring
  2. Add or update the collectionProfile field to use the minimal profile:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: cluster-monitoring-config
      namespace: openshift-monitoring
    data:
      config.yaml: |
        prometheusK8s:
          collectionProfile: minimal
    Note

    Setting the collection profile to minimal affects all platform services that expose metrics, not only the log collector. Any service that explicitly provides a minimal metrics set will have reduced metrics collection.

    Available profiles:

    full
    Collects all metrics exposed by platform components. This is the default profile.
    minimal
    Collects only metrics required for platform alerts, console dashboards, telemetry, and Horizontal and Vertical Pod Autoscaling. This profile significantly reduces Prometheus resource usage.
  3. Save the ConfigMap.
  4. The cluster monitoring operator automatically applies the profile change. Wait approximately 2-3 minutes for the monitoring components to reconcile.

Verification

  1. Verify that the minimal ServiceMonitor resources were created for the log collector:

    $ oc get servicemonitor -n openshift-logging -l monitoring.openshift.io/collection-profile=minimal

    Example output

    NAME                  AGE
    minimal-instance      5m
    minimal-lfme          5m

    The ServiceMonitor names follow the pattern minimal-<forwarder-name> where <forwarder-name> is typically instance for the default ClusterLogForwarder.

  2. Query Prometheus to confirm that only minimal metrics are being collected:

    $ oc exec -n openshift-monitoring prometheus-k8s-0 -c prometheus -- \
      /bin/sh -c "promtool tsdb analyze /prometheus" | \
      grep vector_component_received_events_count_bucket

    With the minimal profile, this metric should not appear in the output, as it is excluded from the minimal metric set.

  3. Monitor Prometheus resource usage to verify the reduction:

    $ oc adm top pod -n openshift-monitoring prometheus-k8s-0

    You should observe reduced CPU and memory consumption compared to the full profile.

When you use the minimal metrics collection profile, Prometheus collects only the metrics required for platform functionality: alerts, console dashboards, telemetry, and Horizontal and Vertical Pod Autoscaling. This significantly reduces metrics cardinality compared to the full profile.

Note

The minimal profile excludes high-cardinality histogram metrics, such as vector_component_received_events_count_bucket and vector_buffer_send_duration_seconds_bucket. These metrics create thousands of time series in multitenant environments but are not required for platform functionality.

Additionally, the minimal profile drops the following metrics specifically for transform components (component_kind=transform): vector_component_received_bytes_total, vector_component_received_event_bytes_total, vector_component_received_events_total, and vector_component_sent_bytes_total. This further reduces cardinality while preserving metrics for source and sink components where they are most valuable.

In multitenant Red Hat OpenShift Logging clusters, configure logging to isolate logs between tenants while minimizing the impact on the monitoring stack. Balance tenant isolation requirements with the metrics cardinality that your configuration creates.

Instead of creating separate inputs for each tenant or namespace, use label selectors to route logs from multiple sources through a single input.

The following configuration example shows an anti-pattern with separate inputs per namespace:

apiVersion: observability.openshift.io/v1
kind: ClusterLogForwarder
metadata:
  name: tenant-logs
  namespace: openshift-logging
spec:
  inputs:
    - name: tenant-a-logs
      type: application
      application:
        namespaces:
          - tenant-a
    - name: tenant-b-logs
      type: application
      application:
        namespaces:
          - tenant-b
    # ... 98 more tenant inputs
  outputs:
    - name: tenant-a-splunk
      type: splunk
      # ...
    - name: tenant-b-splunk
      type: splunk
      # ...
  pipelines:
    - name: tenant-a-pipeline
      inputRefs:
        - tenant-a-logs
      outputRefs:
        - tenant-a-splunk
    - name: tenant-b-pipeline
      inputRefs:
        - tenant-b-logs
      outputRefs:
        - tenant-b-splunk

Each tenant input creates multiple Vector components. This increases cardinality. This configuration with 100 tenants creates approximately 400-500 unique component_id values.

The following configuration example shows the recommended approach with a single input and filtering:

apiVersion: observability.openshift.io/v1
kind: ClusterLogForwarder
metadata:
  name: tenant-logs
  namespace: openshift-logging
spec:
  inputs:
    - name: all-tenants
      type: application
      application:
        selector:
          matchLabels:
            tenant-logging: "enabled"
  filters:
    - name: tenant-a-filter
      type: drop
      drop:
        - test:
            - field: .kubernetes.namespace_name
              notMatches: "^tenant-a$"
    - name: tenant-b-filter
      type: drop
      drop:
        - test:
            - field: .kubernetes.namespace_name
              notMatches: "^tenant-b$"
  outputs:
    - name: tenant-a-splunk
      type: splunk
      # ...
    - name: tenant-b-splunk
      type: splunk
      # ...
  pipelines:
    - name: tenant-a-pipeline
      inputRefs:
        - all-tenants
      filterRefs:
        - tenant-a-filter
      outputRefs:
        - tenant-a-splunk
    - name: tenant-b-pipeline
      inputRefs:
        - all-tenants
      filterRefs:
        - tenant-b-filter
      outputRefs:
        - tenant-b-splunk

A single input for all tenant logs reduces the component count. Use pod labels to control which pods are included in log collection. This configuration creates far fewer Vector components because there is only one input source.

If multiple tenants send logs to the same destination system (for example, the same Splunk instance or LokiStack), use a single output rather than creating separate outputs per tenant.

The following configuration example shows an anti-pattern with separate outputs per tenant to the same destination:

spec:
  outputs:
    - name: tenant-a-splunk
      type: splunk
      splunk:
        url: https://splunk.example.com:8088
        token:
          secretName: tenant-a-splunk-token
    - name: tenant-b-splunk
      type: splunk
      splunk:
        url: https://splunk.example.com:8088
        token:
          secretName: tenant-b-splunk-token

Both outputs point to the same Splunk instance. This creates duplicate components.

The following configuration example shows the recommended approach with a single output and tenant identification:

spec:
  outputs:
    - name: shared-splunk
      type: splunk
      splunk:
        url: https://splunk.example.com:8088
        token:
          secretName: splunk-token
  pipelines:
    - name: tenant-a-pipeline
      inputRefs:
        - all-tenants
      filterRefs:
        - tenant-a-filter
      outputRefs:
        - shared-splunk
    - name: tenant-b-pipeline
      inputRefs:
        - all-tenants
      filterRefs:
        - tenant-b-filter
      outputRefs:
        - shared-splunk

A single output reduces the component count. Multiple pipelines can share the same output. Tenant isolation is maintained by the namespace information in the log records. Use Splunk, LokiStack, or other destination capabilities to filter and route logs by tenant.

Each pipeline creates additional components for routing and processing. Where possible, combine pipelines that share inputs and outputs.

Separate pipelines are necessary when:

  • Logs require different transformations before reaching different outputs
  • Security or compliance requires strict separation of processing paths
  • Different tenants require different delivery guarantees (for example, AtLeastOnce versus AtMostOnce)

Pipelines can be combined when:

  • Logs go through the same filters to reach the same output
  • The only difference is the source namespace or labels
  • Tenant isolation is handled at the destination

Creating multiple ClusterLogForwarder custom resources increases the overall component count. Each ClusterLogForwarder instance deploys a separate collector pod with its own set of components.

Use multiple ClusterLogForwarder instances when:

  • Different service accounts are required for different log collection purposes
  • Different security or network policies apply
  • Logs from different sources require completely different processing pipelines

A single ClusterLogForwarder is sufficient when:

  • All logs can use the same service account
  • Tenant isolation is achieved through filtering and routing
  • Network policies allow a single collector to reach all destinations

The following example shows a multitenant logging configuration that balances tenant isolation with low metrics cardinality:

apiVersion: observability.openshift.io/v1
kind: ClusterLogForwarder
metadata:
  name: multitenant-logging
  namespace: openshift-logging
spec:
  serviceAccount:
    name: logcollector
  inputs:
    - name: application-logs
      type: application
      application:
        selector:
          matchExpressions:
            - key: logging-enabled
              operator: In
              values:
                - "true"
    - name: infrastructure-logs
      type: infrastructure
  filters:
    - name: add-tenant-label
      type: detectMultilineException
  outputs:
    - name: tenant-lokistack
      type: lokiStack
      lokiStack:
        target:
          name: logging-loki
          namespace: openshift-logging
    - name: compliance-s3
      type: s3
      s3:
        authentication:
          type: awsAccessKey
          awsAccessKey:
            keyId:
              key: aws_access_key_id
              secretName: s3-secret
            keySecret:
              key: aws_secret_access_key
              secretName: s3-secret
        bucket: audit-logs
        keyPrefix: compliance/
        region: us-east-1
  pipelines:
    - name: application-to-loki
      inputRefs:
        - application-logs
      filterRefs:
        - add-tenant-label
      outputRefs:
        - tenant-lokistack
    - name: infrastructure-to-loki
      inputRefs:
        - infrastructure-logs
      outputRefs:
        - tenant-lokistack
    - name: audit-to-s3
      inputRefs:
        - audit
      outputRefs:
        - compliance-s3

This configuration uses:

  • A single input for all application logs, controlled by pod label
  • A single filter that applies to all tenants
  • A single LokiStack output for all tenant application and infrastructure logs
  • A separate output for compliance because it goes to a different destination type
  • Three pipelines for different log types, sharing inputs and outputs where possible

This configuration creates approximately 40-60 component_id values, compared to 400-500 values for a per-tenant input/output design.

In LokiStack, tenant isolation is achieved through the namespace labels in the logs. Use LogQL queries to filter logs by tenant:

{kubernetes_namespace_name="tenant-a"}

Use the following rough estimates to predict the cardinality impact of your ClusterLogForwarder configuration:

  • Each input creates approximately 5-10 components (source + metadata + routing)
  • Each output creates approximately 3-5 components (routing + sink + buffer management)
  • Each filter creates approximately 1-2 components
  • Each pipeline adds approximately 2-4 components for routing

For example, a ClusterLogForwarder with:

  • 5 inputs ~40 components
  • 3 outputs ~12 components
  • 2 filters ~4 components
  • 5 pipelines ~15 components

Estimated total: ~70 component_id values

Each histogram metric creates 10 time series per component_id:

  • vector_component_received_events_count_bucket: 70 × 10 = 700 series
  • vector_buffer_send_duration_seconds_bucket: 70 × 10 = 700 series

These estimates are approximate. Use the diagnostic procedures in "Troubleshoot the collector" to measure actual cardinality.

Red Hat logoGithubRedditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat Documentation

Legal Notice

Theme

© 2026 Red Hat
Back to top