Chapter 2. Monitor collector metrics
You can monitor and configure collector metrics to understand monitoring impact and reduce cardinality in multitenant environments.
2.1. Understand collector metrics cardinality and monitoring impact Copy linkLink copied to clipboard!
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_idvalues 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
ClusterLogForwarderinstances -
You have separate
ClusterLogForwarderinstances 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.
2.2. Configure metrics collection profiles to reduce cardinality Copy linkLink copied to clipboard!
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-admincluster role. -
You have installed the OpenShift CLI (
oc).
Procedure
Edit the cluster monitoring configuration:
$ oc edit configmap cluster-monitoring-config -n openshift-monitoringAdd or update the
collectionProfilefield to use theminimalprofile:apiVersion: v1 kind: ConfigMap metadata: name: cluster-monitoring-config namespace: openshift-monitoring data: config.yaml: | prometheusK8s: collectionProfile: minimalNoteSetting the collection profile to
minimalaffects 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.
- Save the ConfigMap.
- The cluster monitoring operator automatically applies the profile change. Wait approximately 2-3 minutes for the monitoring components to reconcile.
Verification
Verify that the minimal ServiceMonitor resources were created for the log collector:
$ oc get servicemonitor -n openshift-logging -l monitoring.openshift.io/collection-profile=minimalExample output
NAME AGE minimal-instance 5m minimal-lfme 5mThe ServiceMonitor names follow the pattern
minimal-<forwarder-name>where<forwarder-name>is typicallyinstancefor the default ClusterLogForwarder.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_bucketWith the minimal profile, this metric should not appear in the output, as it is excluded from the minimal metric set.
Monitor Prometheus resource usage to verify the reduction:
$ oc adm top pod -n openshift-monitoring prometheus-k8s-0You should observe reduced CPU and memory consumption compared to the full profile.
2.3. Minimal metrics collected for the log collector Copy linkLink copied to clipboard!
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.
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.
2.4. Best practices for multitenant logging configurations Copy linkLink copied to clipboard!
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,
AtLeastOnceversusAtMostOnce)
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.