Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions api/operator/v1beta1/vmextra_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,21 @@ const (
ClusterComponentStorage ClusterComponent = "storage"
)

type MetadataStrategy string

const (
// MetadataStrategyPreferVM - prefers VM object meta values, ignores prometheus
MetadataStrategyPreferVM MetadataStrategy = "prefer-victoriametrics"
// MetadataStrategyPreferProm - prefers prometheus
MetadataStrategyPreferProm MetadataStrategy = "prefer-prometheus"
// MetadataStrategyMergeVMPriority merges both label sets
// its not possible to remove values
MetadataStrategyMergeVMPriority MetadataStrategy = "merge-victoriametrics-priority"
// MetadataStrategyMergePromPriority merges both label sets
// its not possible to remove values
MetadataStrategyMergePromPriority MetadataStrategy = "merge-prometheus-priority"
)

const (
httpPathPrefixFlag = "http.pathPrefix"
httpUseProxyProtocolFlag = "httpListenAddr.useProxyProtocol"
Expand All @@ -71,6 +86,19 @@ const (
VMAuthLBServiceProxyTargetLabel = "operator.victoriametrics.com/vmauthlb-proxy-name"
VMAuthLBServiceProxyJobNameLabel = "operator.victoriametrics.com/vmauthlb-proxy-job-name"
KubeNodeEnvName = "KUBE_NODE_NAME"
// IgnoreConversionLabel this annotation disables updating of corresponding VMObject
// must be added to annotation of VMObject
// annotations:
// operator.victoriametrics.com/ignore-prometheus-updates: enabled
IgnoreConversionLabel = "operator.victoriametrics.com/ignore-prometheus-updates"
// IgnoreConversion - disables updates from prometheus api
IgnoreConversion = "enabled"
// MetadataStrategyLabel merge strategy by default prefer prometheus meta labels
// but with annotation value added to VMObject:
// annotations:
// operator.victoriametrics.com/merge-api-strategy: prefer-victoriametrics
// metadata from VMObject will be preferred during merge
MetadataStrategyLabel = "operator.victoriametrics.com/merge-meta-strategy"
)

const (
Expand Down
4 changes: 4 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ aliases:

## tip

**Update note 1**: deprecated env variables for Prometheus CRs conversion `VM_ENABLEDPROMETHEUSCONVERTER_PODMONITOR`, `VM_ENABLEDPROMETHEUSCONVERTER_SERVICESCRAPE`, `VM_ENABLEDPROMETHEUSCONVERTER_PROMETHEUSRULE`, `VM_ENABLEDPROMETHEUSCONVERTER_PROBE`, `VM_ENABLEDPROMETHEUSCONVERTER_SCRAPECONFIG`. Use `-controller.disableReconcileFor` command-line flag with comma-separated list of controller names, that should be disabled.
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
**Update note 2**: removed `operator_prometheus_converter_watch_events_total` metric since migration of Prometheus object watchers to controllers made this counter obsolete.
**Update note 3**: made `controller.prometheusCRD.resyncPeriod` command line flag noop, which was relevant to Prometheus object watchers.

* Dependency: [vmoperator](https://docs.victoriametrics.com/operator/): Updated default versions for VM apps to [v1.138.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.138.0) version
* Dependency: [vmoperator](https://docs.victoriametrics.com/operator/): Updated default versions for VL apps to [v1.48.0](https://github.com/VictoriaMetrics/VictoriaLogs/releases/tag/v1.48.0).

Expand Down
12 changes: 6 additions & 6 deletions docs/env.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,12 +247,12 @@
| VM_VTCLUSTERDEFAULT_INSERT_RESOURCE_REQUEST_CPU: `100m` <a href="#variables-vm-vtclusterdefault-insert-resource-request-cpu" id="variables-vm-vtclusterdefault-insert-resource-request-cpu">#</a> |
| VM_VTCLUSTERDEFAULT_INSERT_RESOURCE_REQUEST_EPHEMERAL_STORAGE: `unlimited` <a href="#variables-vm-vtclusterdefault-insert-resource-request-ephemeral-storage" id="variables-vm-vtclusterdefault-insert-resource-request-ephemeral-storage">#</a> |
| VM_VTCLUSTERDEFAULT_INSERT_TERMINATION_GRACE_PERIOD_SECONDS: `30` <a href="#variables-vm-vtclusterdefault-insert-termination-grace-period-seconds" id="variables-vm-vtclusterdefault-insert-termination-grace-period-seconds">#</a> |
| VM_ENABLEDPROMETHEUSCONVERTER_PODMONITOR: `true` <a href="#variables-vm-enabledprometheusconverter-podmonitor" id="variables-vm-enabledprometheusconverter-podmonitor">#</a> |
| VM_ENABLEDPROMETHEUSCONVERTER_SERVICESCRAPE: `true` <a href="#variables-vm-enabledprometheusconverter-servicescrape" id="variables-vm-enabledprometheusconverter-servicescrape">#</a> |
| VM_ENABLEDPROMETHEUSCONVERTER_PROMETHEUSRULE: `true` <a href="#variables-vm-enabledprometheusconverter-prometheusrule" id="variables-vm-enabledprometheusconverter-prometheusrule">#</a> |
| VM_ENABLEDPROMETHEUSCONVERTER_PROBE: `true` <a href="#variables-vm-enabledprometheusconverter-probe" id="variables-vm-enabledprometheusconverter-probe">#</a> |
| VM_ENABLEDPROMETHEUSCONVERTER_ALERTMANAGERCONFIG: `true` <a href="#variables-vm-enabledprometheusconverter-alertmanagerconfig" id="variables-vm-enabledprometheusconverter-alertmanagerconfig">#</a> |
| VM_ENABLEDPROMETHEUSCONVERTER_SCRAPECONFIG: `true` <a href="#variables-vm-enabledprometheusconverter-scrapeconfig" id="variables-vm-enabledprometheusconverter-scrapeconfig">#</a> |
| VM_ENABLEDPROMETHEUSCONVERTER_PODMONITOR: `true` <a href="#variables-vm-enabledprometheusconverter-podmonitor" id="variables-vm-enabledprometheusconverter-podmonitor">#</a><br>Deprecated: use command-line flag with value -controller.disableReconcileFor=PodMonitor instead |
| VM_ENABLEDPROMETHEUSCONVERTER_SERVICESCRAPE: `true` <a href="#variables-vm-enabledprometheusconverter-servicescrape" id="variables-vm-enabledprometheusconverter-servicescrape">#</a><br>Deprecated: use command-line flag with value -controller.disableReconcileFor=ServiceMonitor instead |
| VM_ENABLEDPROMETHEUSCONVERTER_PROMETHEUSRULE: `true` <a href="#variables-vm-enabledprometheusconverter-prometheusrule" id="variables-vm-enabledprometheusconverter-prometheusrule">#</a><br>Deprecated: use command-line flag with value -controller.disableReconcileFor=PrometheusRule instead |
| VM_ENABLEDPROMETHEUSCONVERTER_PROBE: `true` <a href="#variables-vm-enabledprometheusconverter-probe" id="variables-vm-enabledprometheusconverter-probe">#</a><br>Deprecated: use command-line flag with value -controller.disableReconcileFor=Probe instead |
| VM_ENABLEDPROMETHEUSCONVERTER_ALERTMANAGERCONFIG: `true` <a href="#variables-vm-enabledprometheusconverter-alertmanagerconfig" id="variables-vm-enabledprometheusconverter-alertmanagerconfig">#</a><br>Deprecated: use command-line flag with value -controller.disableReconcileFor=AlertmanagerConfig instead |
| VM_ENABLEDPROMETHEUSCONVERTER_SCRAPECONFIG: `true` <a href="#variables-vm-enabledprometheusconverter-scrapeconfig" id="variables-vm-enabledprometheusconverter-scrapeconfig">#</a><br>Deprecated: use command-line flag with value -controller.disableReconcileFor=ScrapeConfig instead |
| VM_PROMETHEUSCONVERTERADDARGOCDIGNOREANNOTATIONS: `false` <a href="#variables-vm-prometheusconverteraddargocdignoreannotations" id="variables-vm-prometheusconverteraddargocdignoreannotations">#</a><br>adds compare-options and sync-options for prometheus objects converted by operator. It helps to properly use converter with ArgoCD |
| VM_ENABLEDPROMETHEUSCONVERTEROWNERREFERENCES: `false` <a href="#variables-vm-enabledprometheusconverterownerreferences" id="variables-vm-enabledprometheusconverterownerreferences">#</a> |
| VM_FILTERPROMETHEUSCONVERTERLABELPREFIXES: `-` <a href="#variables-vm-filterprometheusconverterlabelprefixes" id="variables-vm-filterprometheusconverterlabelprefixes">#</a><br>allows filtering for converted labels, labels with matched prefix will be ignored |
Expand Down
16 changes: 6 additions & 10 deletions docs/integrations/prometheus.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,12 @@ By default, the vmoperator converts all existing [prometheus-operator](https://g
API objects into corresponding VictoriaMetrics Operator objects,
i.e. creates resources of VictoriaMetrics similar to Prometheus resources in the same namespace.

You can control this behaviour by setting env variable for operator:

```sh
# disable conversion for each object
VM_ENABLEDPROMETHEUSCONVERTER_PODMONITOR=false
VM_ENABLEDPROMETHEUSCONVERTER_SERVICESCRAPE=false
VM_ENABLEDPROMETHEUSCONVERTER_PROMETHEUSRULE=false
VM_ENABLEDPROMETHEUSCONVERTER_PROBE=false
VM_ENABLEDPROMETHEUSCONVERTER_SCRAPECONFIG=false
```
You can control this behaviour by setting `-controller.disableReconcileFor` operator command-line flag with values:
- `PodMonitor` - disable PodMonitor conversion
- `ServiceMonitor` - disable ServiceMonitor conversion
- `PrometheusRule` - disable PrometheusRule conversion
- `Probe` - disable Probe conversion
- `ScrapeConfig` - disable ScrapeConfig conversion

For [victoria-metrics-operator helm-chart](https://docs.victoriametrics.com/helm/victoria-metrics-operator/) you can use following way:

Expand Down
16 changes: 11 additions & 5 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -557,12 +557,18 @@ type BaseOperatorConf struct {
} `prefix:"VM_VTCLUSTERDEFAULT_"`

EnabledPrometheusConverter struct {
PodMonitor bool `default:"true" env:"PODMONITOR"`
ServiceScrape bool `default:"true" env:"SERVICESCRAPE"`
PrometheusRule bool `default:"true" env:"PROMETHEUSRULE"`
Probe bool `default:"true" env:"PROBE"`
// Deprecated: use command-line flag with value -controller.disableReconcileFor=PodMonitor instead
PodMonitor bool `default:"true" env:"PODMONITOR"`
// Deprecated: use command-line flag with value -controller.disableReconcileFor=ServiceMonitor instead
ServiceMonitor bool `default:"true" env:"SERVICESCRAPE"`
// Deprecated: use command-line flag with value -controller.disableReconcileFor=PrometheusRule instead
PrometheusRule bool `default:"true" env:"PROMETHEUSRULE"`
// Deprecated: use command-line flag with value -controller.disableReconcileFor=Probe instead
Probe bool `default:"true" env:"PROBE"`
// Deprecated: use command-line flag with value -controller.disableReconcileFor=AlertmanagerConfig instead
AlertmanagerConfig bool `default:"true" env:"ALERTMANAGERCONFIG"`
ScrapeConfig bool `default:"true" env:"SCRAPECONFIG"`
// Deprecated: use command-line flag with value -controller.disableReconcileFor=ScrapeConfig instead
ScrapeConfig bool `default:"true" env:"SCRAPECONFIG"`
} `prefix:"VM_ENABLEDPROMETHEUSCONVERTER_"`
// adds compare-options and sync-options for prometheus objects converted by operator.
// It helps to properly use converter with ArgoCD
Expand Down
7 changes: 6 additions & 1 deletion internal/controller/operator/controllers.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,16 @@ var (
Name: "operator_controller_reconcile_errors_total",
Help: "Counts number context.Canceled errors",
})
activeConverterWatchers = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "operator_prometheus_converter_active_watchers",
Comment thread
vrutkovs marked this conversation as resolved.
}, []string{"object_type_name"})
)

// InitMetrics adds metrics to the Registry
func init() {
metrics.Registry.MustRegister(parseObjectErrorsTotal, getObjectsErrorsTotal, conflictErrorsTotal, contextCancelErrorsTotal)
metrics.Registry.MustRegister(
parseObjectErrorsTotal, getObjectsErrorsTotal, conflictErrorsTotal,
contextCancelErrorsTotal, activeConverterWatchers)
}

func getDefaultOptions() controller.Options {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
package converter

import (
"context"
"math"
"strings"

promv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
logf "sigs.k8s.io/controller-runtime/pkg/log"

vmv1beta1 "github.com/VictoriaMetrics/operator/api/operator/v1beta1"
"github.com/VictoriaMetrics/operator/internal/config"
"github.com/VictoriaMetrics/operator/internal/controller/operator/factory/logger"
)

const (
prometheusSecretDir = "/etc/prometheus/secrets"
prometheusConfigmapDir = "/etc/prometheus/configmaps"
)

var log = logf.Log.WithName("controller.PrometheusConverter")

// ConvertPromRule creates VMRule from PrometheusRule
func ConvertPromRule(prom *promv1.PrometheusRule, conf *config.BaseOperatorConf) *vmv1beta1.VMRule {
// PrometheusRule creates VMRule from PrometheusRule
func PrometheusRule(ctx context.Context, prom *promv1.PrometheusRule, conf *config.BaseOperatorConf) *vmv1beta1.VMRule {
ruleGroups := make([]vmv1beta1.RuleGroup, 0, len(prom.Spec.Groups))
for _, promGroup := range prom.Spec.Groups {
ruleItems := make([]vmv1beta1.Rule, 0, len(promGroup.Rules))
Expand Down Expand Up @@ -100,8 +99,8 @@ func MaybeAddArgoCDIgnoreAnnotations(mustAdd bool, dst map[string]string) map[st
return dst
}

// ConvertServiceMonitor create VMServiceScrape from ServiceMonitor
func ConvertServiceMonitor(serviceMon *promv1.ServiceMonitor, conf *config.BaseOperatorConf) *vmv1beta1.VMServiceScrape {
// ServiceMonitor create VMServiceScrape from ServiceMonitor
func ServiceMonitor(ctx context.Context, serviceMon *promv1.ServiceMonitor, conf *config.BaseOperatorConf) *vmv1beta1.VMServiceScrape {
cs := &vmv1beta1.VMServiceScrape{
ObjectMeta: metav1.ObjectMeta{
Name: serviceMon.Name,
Expand All @@ -114,7 +113,7 @@ func ConvertServiceMonitor(serviceMon *promv1.ServiceMonitor, conf *config.BaseO
TargetLabels: serviceMon.Spec.TargetLabels,
PodTargetLabels: serviceMon.Spec.PodTargetLabels,
Selector: serviceMon.Spec.Selector,
Endpoints: convertEndpoint(serviceMon.Spec.Endpoints),
Endpoints: convertEndpoint(ctx, serviceMon.Spec.Endpoints),
NamespaceSelector: vmv1beta1.NamespaceSelector{
Any: serviceMon.Spec.NamespaceSelector.Any,
MatchNames: serviceMon.Spec.NamespaceSelector.MatchNames,
Expand Down Expand Up @@ -201,7 +200,7 @@ func convertBearerToken(src *corev1.SecretKeySelector) *corev1.SecretKeySelector
return src
}

func convertEndpoint(promEndpoint []promv1.Endpoint) []vmv1beta1.Endpoint {
func convertEndpoint(ctx context.Context, promEndpoint []promv1.Endpoint) []vmv1beta1.Endpoint {
endpoints := make([]vmv1beta1.Endpoint, 0, len(promEndpoint))
for _, endpoint := range promEndpoint {
ep := vmv1beta1.Endpoint{
Expand Down Expand Up @@ -231,8 +230,8 @@ func convertEndpoint(promEndpoint []promv1.Endpoint) []vmv1beta1.Endpoint {
BearerTokenSecret: convertBearerToken(endpoint.BearerTokenSecret),
},
EndpointRelabelings: vmv1beta1.EndpointRelabelings{
MetricRelabelConfigs: ConvertRelabelConfig(endpoint.MetricRelabelConfigs),
RelabelConfigs: ConvertRelabelConfig(endpoint.RelabelConfigs),
MetricRelabelConfigs: ConvertRelabelConfig(ctx, endpoint.MetricRelabelConfigs),
RelabelConfigs: ConvertRelabelConfig(ctx, endpoint.RelabelConfigs),
},
}

Expand Down Expand Up @@ -303,7 +302,7 @@ func convertSecretOrConfigmap(promSCM promv1.SecretOrConfigMap) vmv1beta1.Secret
}

// ConvertRelabelConfig converts Prometheus relabel config to VM one
func ConvertRelabelConfig(promRelabelConfig []promv1.RelabelConfig) []*vmv1beta1.RelabelConfig {
func ConvertRelabelConfig(ctx context.Context, promRelabelConfig []promv1.RelabelConfig) []*vmv1beta1.RelabelConfig {
if promRelabelConfig == nil {
return nil
}
Expand Down Expand Up @@ -331,10 +330,10 @@ func ConvertRelabelConfig(promRelabelConfig []promv1.RelabelConfig) []*vmv1beta1
relabelCfg[idx].Regex = vmv1beta1.StringOrArray{relabel.Regex}
}
}
return filterUnsupportedRelabelCfg(relabelCfg)
return filterUnsupportedRelabelCfg(ctx, relabelCfg)
}

func convertPodEndpoints(promPodEnpoints []promv1.PodMetricsEndpoint) []vmv1beta1.PodMetricsEndpoint {
func convertPodEndpoints(ctx context.Context, promPodEnpoints []promv1.PodMetricsEndpoint) []vmv1beta1.PodMetricsEndpoint {
if promPodEnpoints == nil {
return nil
}
Expand Down Expand Up @@ -364,8 +363,8 @@ func convertPodEndpoints(promPodEnpoints []promv1.PodMetricsEndpoint) []vmv1beta
FollowRedirects: promEndPoint.FollowRedirects,
},
EndpointRelabelings: vmv1beta1.EndpointRelabelings{
RelabelConfigs: ConvertRelabelConfig(promEndPoint.RelabelConfigs),
MetricRelabelConfigs: ConvertRelabelConfig(promEndPoint.MetricRelabelConfigs),
RelabelConfigs: ConvertRelabelConfig(ctx, promEndPoint.RelabelConfigs),
MetricRelabelConfigs: ConvertRelabelConfig(ctx, promEndPoint.MetricRelabelConfigs),
},

EndpointAuth: vmv1beta1.EndpointAuth{
Expand All @@ -383,8 +382,8 @@ func convertPodEndpoints(promPodEnpoints []promv1.PodMetricsEndpoint) []vmv1beta
return endPoints
}

// ConvertPodMonitor create VMPodScrape from PodMonitor
func ConvertPodMonitor(podMon *promv1.PodMonitor, conf *config.BaseOperatorConf) *vmv1beta1.VMPodScrape {
// PodMonitor create VMPodScrape from PodMonitor
func PodMonitor(ctx context.Context, podMon *promv1.PodMonitor, conf *config.BaseOperatorConf) *vmv1beta1.VMPodScrape {
cs := &vmv1beta1.VMPodScrape{
ObjectMeta: metav1.ObjectMeta{
Name: podMon.Name,
Expand All @@ -400,7 +399,7 @@ func ConvertPodMonitor(podMon *promv1.PodMonitor, conf *config.BaseOperatorConf)
Any: podMon.Spec.NamespaceSelector.Any,
MatchNames: podMon.Spec.NamespaceSelector.MatchNames,
},
PodMetricsEndpoints: convertPodEndpoints(podMon.Spec.PodMetricsEndpoints),
PodMetricsEndpoints: convertPodEndpoints(ctx, podMon.Spec.PodMetricsEndpoints),
ScrapeClassName: podMon.Spec.ScrapeClassName,
},
}
Expand Down Expand Up @@ -428,8 +427,8 @@ func ConvertPodMonitor(podMon *promv1.PodMonitor, conf *config.BaseOperatorConf)
return cs
}

// ConvertProbe creates VMProbe from prometheus probe
func ConvertProbe(probe *promv1.Probe, conf *config.BaseOperatorConf) *vmv1beta1.VMProbe {
// Probe creates VMProbe from prometheus probe
func Probe(ctx context.Context, probe *promv1.Probe, conf *config.BaseOperatorConf) *vmv1beta1.VMProbe {
var (
k8sTargets []*vmv1beta1.VMProbeTargetKubernetes
staticTargets *vmv1beta1.VMProbeTargetStatic
Expand All @@ -442,14 +441,14 @@ func ConvertProbe(probe *promv1.Probe, conf *config.BaseOperatorConf) *vmv1beta1
Any: probe.Spec.Targets.Ingress.NamespaceSelector.Any,
MatchNames: probe.Spec.Targets.Ingress.NamespaceSelector.MatchNames,
},
RelabelConfigs: ConvertRelabelConfig(probe.Spec.Targets.Ingress.RelabelConfigs),
RelabelConfigs: ConvertRelabelConfig(ctx, probe.Spec.Targets.Ingress.RelabelConfigs),
})
}
if probe.Spec.Targets.StaticConfig != nil {
staticTargets = &vmv1beta1.VMProbeTargetStatic{
Targets: probe.Spec.Targets.StaticConfig.Targets,
Labels: probe.Spec.Targets.StaticConfig.Labels,
RelabelConfigs: ConvertRelabelConfig(probe.Spec.Targets.StaticConfig.RelabelConfigs),
RelabelConfigs: ConvertRelabelConfig(ctx, probe.Spec.Targets.StaticConfig.RelabelConfigs),
}
}
var safeTLS *promv1.SafeTLSConfig
Expand Down Expand Up @@ -479,7 +478,7 @@ func ConvertProbe(probe *promv1.Probe, conf *config.BaseOperatorConf) *vmv1beta1
Interval: string(probe.Spec.Interval),
ScrapeTimeout: string(probe.Spec.ScrapeTimeout),
},
MetricRelabelConfigs: ConvertRelabelConfig(probe.Spec.MetricRelabelConfigs),
MetricRelabelConfigs: ConvertRelabelConfig(ctx, probe.Spec.MetricRelabelConfigs),
EndpointAuth: vmv1beta1.EndpointAuth{
BasicAuth: ConvertBasicAuth(probe.Spec.BasicAuth),
BearerTokenSecret: convertBearerToken(probe.Spec.BearerTokenSecret), //nolint:staticcheck
Expand Down Expand Up @@ -512,13 +511,13 @@ func ConvertProbe(probe *promv1.Probe, conf *config.BaseOperatorConf) *vmv1beta1
return cp
}

func filterUnsupportedRelabelCfg(relabelCfgs []*vmv1beta1.RelabelConfig) []*vmv1beta1.RelabelConfig {
func filterUnsupportedRelabelCfg(ctx context.Context, relabelCfgs []*vmv1beta1.RelabelConfig) []*vmv1beta1.RelabelConfig {
newRelabelCfg := make([]*vmv1beta1.RelabelConfig, 0, len(relabelCfgs))
for _, r := range relabelCfgs {
switch r.Action {
case "keep", "hashmod", "drop":
if len(r.SourceLabels) == 0 {
log.Info("filtering unsupported format of relabelConfig", "action", r.Action, "reason", "source labels are empty")
logger.WithContext(ctx).Info("filtering unsupported format of relabelConfig", "action", r.Action, "reason", "source labels are empty")
continue
}
}
Expand Down
Loading
Loading