From 14b22f80085db15b6d2806ca27dcaf192b827736 Mon Sep 17 00:00:00 2001 From: Kristina Pathak Date: Mon, 20 Jul 2026 09:46:44 -0700 Subject: [PATCH] feat(byoo-otel-collector): add SRE metrics pipeline Refs NVIDIA/nvcf#265 Signed-off-by: Kristina Pathak --- .../byoo-otel-collector/Dockerfile | 2 +- .../byoo-otel-collector/README.md | 4 + ...config_function_container_sre_metrics.yaml | 298 ++++++++++++++++++ .../internal/otelconfig/embed_config.go | 7 + .../internal/otelconfig/otelconfig.go | 12 + .../internal/otelconfig/otelconfig_test.go | 41 +++ .../internal/otelconfig/render.go | 202 +++++++++++- .../internal/otelconfig/render_test.go | 204 +++++++++++- .../otel-collector-build.yaml | 1 + .../byoo-otel-collector/otelcol/components.go | 6 +- .../byoo-otel-collector/otelcol/go.mod | 1 + .../byoo-otel-collector/otelcol/go.sum | 2 + .../byoo-otel-collector/otelcol/main.go | 3 - .../otelcol/main_others.go | 3 - .../otelcol/main_windows.go | 3 - 15 files changed, 773 insertions(+), 16 deletions(-) create mode 100644 src/compute-plane-services/byoo-otel-collector/examples/otelconfigs/k8s/config_function_container_sre_metrics.yaml diff --git a/src/compute-plane-services/byoo-otel-collector/Dockerfile b/src/compute-plane-services/byoo-otel-collector/Dockerfile index 7b54989cc..1ecd26aea 100644 --- a/src/compute-plane-services/byoo-otel-collector/Dockerfile +++ b/src/compute-plane-services/byoo-otel-collector/Dockerfile @@ -61,6 +61,6 @@ WORKDIR /app COPY --from=builder /app/bin/byoo-otel-collector . COPY --from=builder-otelcol /app/output/otelcol-contrib . -EXPOSE 14357/tcp 14358/tcp 13133/tcp 18888/tcp 19090/tcp +EXPOSE 14357/tcp 14358/tcp 13133/tcp 18888/tcp 19090/tcp 19091/tcp ENTRYPOINT ["/app/byoo-otel-collector"] diff --git a/src/compute-plane-services/byoo-otel-collector/README.md b/src/compute-plane-services/byoo-otel-collector/README.md index e24bfc31a..bc76ee65d 100644 --- a/src/compute-plane-services/byoo-otel-collector/README.md +++ b/src/compute-plane-services/byoo-otel-collector/README.md @@ -104,6 +104,7 @@ Exposed Ports: - 14358: OTLP HTTP receiver - 13133: `/health?verbose` endpoint to get detailed health status of collector (healthcheck v2 extension) - 19090: `/metrics` endpoint for the byoo-otel-collector metrics +- 19091: `/metrics` endpoint for optional SRE user metrics ### nvcf-otel-collector Image @@ -128,6 +129,9 @@ Chunking is disabled by default. Configure it with: - `BYOO_LOG_CHUNK_MAX_BODY_BYTES`: maximum log body size in bytes before chunking. `0` disables the processor. Enabled values must be at least `4` bytes so chunks can preserve UTF-8 rune boundaries. Use `983040` bytes for normal BYOO deployments to leave room for log attributes and exporter envelope overhead under a `1000000` byte backend entry limit. - `BYOO_LOG_CHUNK_DRY_RUN`: records oversized-log metrics and warnings without mutating log payloads. Dry-run metric datapoints use `mode=dry_run`. - `BYOO_LOG_EXPORTER_BATCH_MAX_SIZE_BYTES`: serialized log export request batch size used for exporterhelper byte splitting. `0` or unset uses the default `1000000` bytes. +- `BYOO_SRE_METRICS_ENABLED`: enables an additional OTLP-only metrics pipeline that exposes filtered user metrics through a Prometheus exporter on port `19091`. Disabled by default. +- `BYOO_SRE_METRICS_FILTER_CONFIG`: optional YAML filter processor config for the SRE metrics pipeline. If unset, the default drops every metric except `BpsInstrument`, `FpsInstrument`, `RtdInstrument`, and `StageOpenDuration`, and drops datapoints/resources explicitly labeled `sre_metrics_enabled=false` or `sre_enabled_metrics=false`. +- `BYOO_CUSTOMER_METRICS_DROP_LABELS`: comma-separated resource attribute names removed from the customer metrics pipeline when SRE metrics are enabled. If unset, defaults to `sre_metrics_enabled,sre_enabled_metrics`. When chunking is enabled, each emitted chunk preserves the original log metadata and adds these attributes so chunks can be grouped in the backend: diff --git a/src/compute-plane-services/byoo-otel-collector/examples/otelconfigs/k8s/config_function_container_sre_metrics.yaml b/src/compute-plane-services/byoo-otel-collector/examples/otelconfigs/k8s/config_function_container_sre_metrics.yaml new file mode 100644 index 000000000..ea45e2dca --- /dev/null +++ b/src/compute-plane-services/byoo-otel-collector/examples/otelconfigs/k8s/config_function_container_sre_metrics.yaml @@ -0,0 +1,298 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +receivers: + otlp: + protocols: + grpc: + endpoint: ${env:OTEL_POD_IP:-0.0.0.0}:14357 + http: + endpoint: ${env:OTEL_POD_IP:-0.0.0.0}:14358 + prometheus: + config: + scrape_configs: + - honor_labels: true + job_name: nvcf-worker + metric_relabel_configs: + - action: labelkeep + regex: (__name__|container|job|pod|error_code|le) + metrics_path: /federate + params: + match[]: + - '{job=~"nvcf-worker", namespace="nvcf-backend", pod=~".*fake-instance-id.*", container=~"utils", __name__=~"(nvcf_worker_service_request_total|nvcf_worker_service_response_total|nvcf_worker_service_stream_streaming_app_ready|nvcf_worker_service_stream_streaming_app_ready_timestamp|nvcf_worker_service_stream_session_duration_seconds_bucket|nvcf_worker_service_stream_session_duration_seconds_count|nvcf_worker_service_stream_session_duration_seconds_sum|nvcf_worker_service_inference_request_time_seconds_total|nvcf_worker_service_inference_uploads_total|nvcf_worker_service_inference_bytes_total|nvcf_worker_service_inference_failure_total|nvcf_worker_service_worker_thread_count_total|nvcf_worker_service_worker_thread_busy_seconds_total|nvcf_worker_service_bytes_total|nvcf_worker_service_request_latency_seconds_bucket|nvcf_worker_service_request_latency_seconds_sum|nvcf_worker_service_request_latency_seconds_count|nvcf_worker_service_stream_latency_seconds_bucket|nvcf_worker_service_stream_latency_seconds_sum|nvcf_worker_service_stream_latency_seconds_count|nvct_worker_service_result_total|nvcf_worker_service_stream_active)"}' + scrape_interval: 30s + scrape_timeout: 25s + static_configs: + - targets: + - nvcf-byoo-prometheus-kube-prometheus.monitoring.svc.cluster.local:9090 + - honor_labels: true + job_name: nvca + metric_relabel_configs: + - action: labelkeep + regex: (__name__|instance_type|nvca_cluster_group|nvca_cluster_name|nvca_nca_id|nvca_version|job|pod) + metrics_path: /federate + params: + match[]: + - '{job=~"nvca", namespace="nvca-system", pod=~"nvca.*", container="agent", __name__=~"(nvca_instance_type_allocatable|nvca_instance_type_capacity)"}' + scrape_interval: 30s + scrape_timeout: 25s + static_configs: + - targets: + - nvcf-byoo-prometheus-kube-prometheus.monitoring.svc.cluster.local:9090 + - honor_labels: true + honor_timestamps: false + job_name: kubernetes-cadvisor + metric_relabel_configs: + - action: keep + regex: (^$|/dev/root|/dev/shm|/run) + source_labels: + - device + - regex: kubelet + replacement: kubernetes-cadvisor + source_labels: + - job + target_label: job + - action: labelkeep + regex: (__name__|container|cpu|device|image|job|interface|pod) + metrics_path: /federate + params: + match[]: + - '{job=~"kubelet", namespace="nvcf-backend", pod=~".*fake-instance-id.*", container=~"inference|task|", __name__=~"(container_cpu_cfs_throttled_periods_total|container_cpu_cfs_throttled_seconds_total|container_cpu_usage_seconds_total|container_memory_cache|container_memory_rss|container_memory_swap|container_memory_usage_bytes|container_memory_working_set_bytes|container_fs_limit_bytes|container_fs_usage_bytes|container_fs_reads_bytes_total|container_fs_reads_total|container_fs_writes_bytes_total|container_fs_writes_total|container_network_receive_bytes_total|container_network_receive_errors_total|container_network_receive_packets_dropped_total|container_network_receive_packets_total|container_network_transmit_bytes_total|container_network_transmit_errors_total|container_network_transmit_packets_dropped_total|container_network_transmit_packets_total)"}' + scrape_interval: 30s + scrape_timeout: 25s + static_configs: + - targets: + - nvcf-byoo-prometheus-kube-prometheus.monitoring.svc.cluster.local:9090 + - honor_labels: true + job_name: kube-state-metrics + metric_relabel_configs: + - action: labelkeep + regex: (__name__|container|image|job|pod|reason|resource|unit) + metrics_path: /federate + params: + match[]: + - '{job=~"kube-state-metrics", namespace="nvcf-backend", pod=~".*fake-instance-id.*", container=~"inference|task", __name__=~"(kube_pod_container_info|kube_pod_container_resource_limits|kube_pod_container_resource_requests|kube_pod_container_status_last_terminated_exitcode|kube_pod_container_status_last_terminated_reason|kube_pod_container_status_ready|kube_pod_container_status_restarts_total|kube_pod_container_status_running|kube_pod_container_status_terminated|kube_pod_container_status_terminated_reason|kube_pod_container_status_waiting|kube_pod_container_status_waiting_reason|kube_pod_container_state_started)"}' + scrape_interval: 30s + scrape_timeout: 25s + static_configs: + - targets: + - nvcf-byoo-prometheus-kube-prometheus.monitoring.svc.cluster.local:9090 + - honor_labels: true + job_name: nvidia-dcgm-exporter + metric_relabel_configs: + - action: labelmap + regex: exported_(.+) + replacement: $1 + - action: labelkeep + regex: (__name__|container|DCGM_FI_DRIVER_VERSION|device|job|modelName|pci_bus_id|pod) + metrics_path: /federate + params: + match[]: + - '{job=~"nvidia-dcgm-exporter", exported_namespace="nvcf-backend", exported_pod=~".*fake-instance-id.*", exported_container=~"inference|task", __name__=~"DCGM_FI_DEV_GPU_UTIL|DCGM_FI_PROF_PIPE_TENSOR_ACTIVE|DCGM_FI_PROF_DRAM_ACTIVE|DCGM_FI_PROF_SM_ACTIVE|DCGM_FI_PROF_SM_OCCUPANCY|DCGM_FI_PROF_PCIE_TX_BYTES|DCGM_FI_PROF_PCIE_RX_BYTES|DCGM_FI_PROF_NVLINK_TX_BYTES|DCGM_FI_PROF_NVLINK_RX_BYTES|DCGM_FI_DEV_POWER_USAGE|DCGM_FI_DEV_VGPU_MEMORY_USAGE"}' + scrape_interval: 30s + scrape_timeout: 25s + static_configs: + - targets: + - nvcf-byoo-prometheus-kube-prometheus.monitoring.svc.cluster.local:9090 + - job_name: opentelemetry-collector + metric_relabel_configs: + - action: keep + regex: (otelcol_receiver_refused_metric_points_total|otelcol_receiver_refused_spans_total|otelcol_receiver_refused_log_records_total|otelcol_receiver_accepted_metric_points_total|otelcol_receiver_accepted_spans_total|otelcol_receiver_accepted_log_records_total|otelcol_exporter_sent_metric_points_total|otelcol_exporter_sent_spans_total|otelcol_exporter_sent_log_records_total|otelcol_exporter_send_failed_metric_points_total|otelcol_exporter_send_failed_spans_total|otelcol_exporter_send_failed_log_records_total|otelcol_processor_incoming_items_total|otelcol_processor_outgoing_items_total) + source_labels: + - __name__ + scrape_interval: 30s + scrape_timeout: 25s + static_configs: + - targets: + - ${env:OTEL_POD_IP:-0.0.0.0}:18888 +exporters: + prometheus/user-metrics: + enable_open_metrics: true + endpoint: ${env:OTEL_POD_IP:-0.0.0.0}:19091 + metric_expiration: 5m + resource_to_telemetry_conversion: + enabled: true + send_timestamps: true + prometheusremotewrite/PROMETHEUS-customer-metrics-metrics: + endpoint: https://customer-metrics.example.invalid/api/v1/write + tls: + cert_file: /etc/byoo-otel-collector/secrets/customer-metrics-clientCert + key_file: /etc/byoo-otel-collector/secrets/customer-metrics-clientKey +processors: + attributes/add-metadata: + actions: + - action: insert + key: nca_id + value: ${env:NCA_ID:-unknown} + - action: insert + key: cloud_provider + value: ${env:NVCF_CLOUD_PROVIDER:-unknown} + - action: insert + key: instance_id + value: ${env:NVCF_INSTANCE_ID:-unknown} + - action: insert + key: host.id + value: ${env:NVCF_INSTANCE_ID:-unknown} + - action: insert + key: function_id + value: ${env:NVCF_FUNCTION_ID:-unknown} + - action: insert + key: function_version_id + value: ${env:NVCF_FUNCTION_VERSION_ID:-unknown} + - action: insert + key: cloud_region + value: fake-zone-name + - action: insert + key: origin + value: nvcf-byoo + batch: + send_batch_max_size: 8192 + send_batch_size: 4096 + timeout: 400ms + batch/sre_metrics: + send_batch_max_size: 8192 + send_batch_size: 4096 + timeout: 400ms + filter/metrics: + metrics: + exclude: + match_type: strict + metric_names: + - scrape_duration_seconds + - scrape_samples_post_metric_relabeling + - scrape_samples_scraped + - scrape_series_added + filter/sre_metrics: + error_mode: ignore + metric_conditions: + - metric.name != "BpsInstrument" and metric.name != "FpsInstrument" and metric.name != "RtdInstrument" and metric.name != "StageOpenDuration" + - resource.attributes["sre_metrics_enabled"] == "false" + - resource.attributes["sre_enabled_metrics"] == "false" + - datapoint.attributes["sre_metrics_enabled"] == "false" + - datapoint.attributes["sre_enabled_metrics"] == "false" + memory_limiter: + check_interval: 1s + limit_percentage: 80 + spike_limit_percentage: 10 + metrics_transform: + transforms: + - action: update + include: ^.*$ + match_type: regexp + operations: + - action: add_label + new_label: nca_id + new_value: ${env:NCA_ID:-unknown} + - action: add_label + new_label: cloud_provider + new_value: ${env:NVCF_CLOUD_PROVIDER:-unknown} + - action: add_label + new_label: instance_id + new_value: ${env:NVCF_INSTANCE_ID:-unknown} + - action: add_label + new_label: host.id + new_value: ${env:NVCF_INSTANCE_ID:-unknown} + - action: add_label + new_label: function_id + new_value: ${env:NVCF_FUNCTION_ID:-unknown} + - action: add_label + new_label: function_version_id + new_value: ${env:NVCF_FUNCTION_VERSION_ID:-unknown} + - action: add_label + new_label: cloud_region + new_value: fake-zone-name + - action: add_label + new_label: origin + new_value: nvcf-byoo + resource: + attributes: + - action: delete + key: service.instance.id + resource/customer_metrics: + attributes: + - action: delete + key: sre_metrics_enabled + - action: delete + key: sre_enabled_metrics +extensions: + cgroup_runtime: + gomaxprocs: + enabled: true + gomemlimit: + enabled: true + ratio: 0.8 + healthcheckv2: + component_health: + include_permanent_errors: true + include_recoverable_errors: true + recovery_duration: 1m + http: + config: + enabled: false + endpoint: ${env:OTEL_POD_IP:-0.0.0.0}:13133 + status: + enabled: true + path: /health + use_v2: true +service: + telemetry: + logs: + initial_fields: + public: "true" + level: warn + metrics: + level: detailed + readers: + - pull: + exporter: + prometheus: + host: ${env:OTEL_POD_IP:-0.0.0.0} + port: 18888 + resource: + attributes: + - name: service.namespace + value: sr-fake-namespace + - name: service.name + value: byoo-otel-collector + - name: function.id + value: fake-function-id + - name: function.version.id + value: fake-function-version-id + traces: + processors: + - batch: + exporter: + otlp: + endpoint: ${env:OTEL_EXPORTER_OTLP_ENDPOINT:-http://localhost:4317} + headers: + - name: lightstep-access-token + value: ${env:OTEL_TRACING_ACCESS_TOKEN} + protocol: grpc + pipelines: + metrics: + receivers: + - otlp + - prometheus + exporters: + - prometheusremotewrite/PROMETHEUS-customer-metrics-metrics + processors: + - memory_limiter + - filter/metrics + - resource + - resource/customer_metrics + - metrics_transform + - batch + metrics/sre: + receivers: + - otlp + exporters: + - prometheus/user-metrics + processors: + - memory_limiter + - filter/sre_metrics + - resource + - metrics_transform + - batch/sre_metrics + extensions: + - healthcheckv2 + - cgroup_runtime diff --git a/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/embed_config.go b/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/embed_config.go index b8c908f94..1d8e3567c 100644 --- a/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/embed_config.go +++ b/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/embed_config.go @@ -47,6 +47,7 @@ type TemplateConfig struct { InstanceID string ZoneName string LogChunking LogChunkingConfig + SREMetrics SREMetricsConfig // LogExporterBatchMaxSizeBytes configures exporterhelper byte batching for logs. // Zero uses the default selected for BYOO. LogExporterBatchMaxSizeBytes int @@ -57,6 +58,12 @@ type LogChunkingConfig struct { DryRun bool } +type SREMetricsConfig struct { + Enabled bool + FilterConfig map[string]interface{} + CustomerMetricsDropLabels []string +} + func ExecuteTemplate(w io.Writer, tcfg TemplateConfig) error { var templateName string switch tcfg.BackendType { diff --git a/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/otelconfig.go b/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/otelconfig.go index ad42a0b5d..1f4ff457a 100644 --- a/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/otelconfig.go +++ b/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/otelconfig.go @@ -42,6 +42,9 @@ type envConfig struct { ByooLogChunkMaxBodyBytes int `split_words:"true"` ByooLogChunkDryRun bool `split_words:"true"` ByooLogExporterBatchMaxSizeBytes int `split_words:"true"` + ByooSreMetricsEnabled bool `split_words:"true"` + ByooSreMetricsFilterConfig string `split_words:"true"` + ByooCustomerMetricsDropLabels string `split_words:"true"` } func processEnvConfig(env *envConfig) error { @@ -76,6 +79,15 @@ func getTemplateConfig() (TemplateConfig, error) { return TemplateConfig{}, fmt.Errorf("BYOO_LOG_EXPORTER_BATCH_MAX_SIZE_BYTES: %w", err) } tcgf.LogExporterBatchMaxSizeBytes = logExporterBatchMaxSizeBytes + sreMetricsFilterConfig, err := resolvedSREMetricsFilterConfig(env.ByooSreMetricsFilterConfig) + if err != nil { + return TemplateConfig{}, fmt.Errorf("BYOO_SRE_METRICS_FILTER_CONFIG: %w", err) + } + tcgf.SREMetrics = SREMetricsConfig{ + Enabled: env.ByooSreMetricsEnabled, + FilterConfig: sreMetricsFilterConfig, + CustomerMetricsDropLabels: resolvedCustomerMetricsDropLabels(env.ByooCustomerMetricsDropLabels), + } functionID := env.NvcfFunctionID functionVersionID := env.NvcfFunctionVersionID diff --git a/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/otelconfig_test.go b/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/otelconfig_test.go index 0ef6d0216..4977328df 100644 --- a/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/otelconfig_test.go +++ b/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/otelconfig_test.go @@ -116,6 +116,44 @@ func TestGetTemplateConfig(t *testing.T) { assert.Equal(t, 2_000_000, cfg.LogExporterBatchMaxSizeBytes) }, }, + { + name: "custom SRE metrics config", + env: map[string]string{ + "NVCF_BACKEND_TYPE": "gfn", + "NVCF_INSTANCE_ID": "test-instance", + "NVCF_NAMESPACE": "test-ns", + "NVCF_WORKLOAD_TYPE": "function", + "NVCT_TASK_ID": "task-123", + "NVCF_ZONE_NAME": "zone-1", + "BYOO_SRE_METRICS_ENABLED": "true", + "BYOO_SRE_METRICS_FILTER_CONFIG": "error_mode: ignore\nmetric_conditions:\n - 'metric.name == \"drop\"'\n", + "BYOO_CUSTOMER_METRICS_DROP_LABELS": "sre_metrics_enabled, custom_label, sre_metrics_enabled", + }, + expectErr: false, + expect: func(t *testing.T, cfg TemplateConfig) { + assert.True(t, cfg.SREMetrics.Enabled) + assert.Equal(t, map[string]interface{}{ + "error_mode": "ignore", + "metric_conditions": []interface{}{ + `metric.name == "drop"`, + }, + }, cfg.SREMetrics.FilterConfig) + assert.Equal(t, []string{"sre_metrics_enabled", "custom_label"}, cfg.SREMetrics.CustomerMetricsDropLabels) + }, + }, + { + name: "invalid SRE metrics filter config", + env: map[string]string{ + "NVCF_BACKEND_TYPE": "gfn", + "NVCF_INSTANCE_ID": "test-instance", + "NVCF_NAMESPACE": "test-ns", + "NVCF_WORKLOAD_TYPE": "function", + "NVCT_TASK_ID": "task-123", + "NVCF_ZONE_NAME": "zone-1", + "BYOO_SRE_METRICS_FILTER_CONFIG": "processors: []", + }, + expectErr: true, + }, { name: "negative log exporter batch max size", env: map[string]string{ @@ -202,6 +240,9 @@ func TestGetTemplateConfig(t *testing.T) { "BYOO_LOG_CHUNK_MAX_BODY_BYTES", "BYOO_LOG_CHUNK_DRY_RUN", "BYOO_LOG_EXPORTER_BATCH_MAX_SIZE_BYTES", + "BYOO_SRE_METRICS_ENABLED", + "BYOO_SRE_METRICS_FILTER_CONFIG", + "BYOO_CUSTOMER_METRICS_DROP_LABELS", } backup := map[string]*string{} for _, k := range envKeys { diff --git a/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/render.go b/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/render.go index 111552617..5f9dde95d 100644 --- a/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/render.go +++ b/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/render.go @@ -24,6 +24,7 @@ import ( "fmt" "os" "path/filepath" + "strings" "gopkg.in/yaml.v3" ) @@ -65,6 +66,19 @@ type OpenTelemetryConfig struct { const defaultLogExporterBatchMaxSizeBytes = 1000000 +const ( + sreMetricsExporterID = "prometheus/user-metrics" + sreMetricsFilterProcessorID = "filter/sre_metrics" + sreMetricsBatchProcessorID = "batch/sre_metrics" + customerMetricsDropLabelsProcessorID = "resource/customer_metrics" + defaultSREMetricsPort = 19091 +) + +var defaultCustomerMetricsDropLabels = []string{ + "sre_metrics_enabled", + "sre_enabled_metrics", +} + // Initialize the maps if they are nil func initializeConfigMaps(otelConfig *OpenTelemetryConfig) { if otelConfig.Receivers == nil { @@ -147,6 +161,91 @@ func resolvedLogExporterBatchMaxSizeBytes(configured int) (int, error) { return configured, nil } +func defaultSREMetricsFilterConfig() map[string]interface{} { + return map[string]interface{}{ + "error_mode": "ignore", + "metric_conditions": []string{ + `metric.name != "BpsInstrument" and metric.name != "FpsInstrument" and metric.name != "RtdInstrument" and metric.name != "StageOpenDuration"`, + `resource.attributes["sre_metrics_enabled"] == "false"`, + `resource.attributes["sre_enabled_metrics"] == "false"`, + `datapoint.attributes["sre_metrics_enabled"] == "false"`, + `datapoint.attributes["sre_enabled_metrics"] == "false"`, + }, + } +} + +func resolvedSREMetricsFilterConfig(configured string) (map[string]interface{}, error) { + if strings.TrimSpace(configured) == "" { + return defaultSREMetricsFilterConfig(), nil + } + + filterConfig := map[string]interface{}{} + if err := yaml.Unmarshal([]byte(configured), &filterConfig); err != nil { + return nil, fmt.Errorf("invalid YAML: %w", err) + } + if len(filterConfig) == 0 { + return nil, fmt.Errorf("filter config must not be empty") + } + + return unwrapSREMetricsFilterConfig(filterConfig) +} + +func unwrapSREMetricsFilterConfig(filterConfig map[string]interface{}) (map[string]interface{}, error) { + if rawProcessors, ok := filterConfig["processors"]; ok { + processors, err := mapFromConfigValue(rawProcessors, "processors") + if err != nil { + return nil, err + } + rawFilter, ok := processors[sreMetricsFilterProcessorID] + if !ok { + return nil, fmt.Errorf("processors must include %q", sreMetricsFilterProcessorID) + } + return mapFromConfigValue(rawFilter, sreMetricsFilterProcessorID) + } + + if rawFilter, ok := filterConfig[sreMetricsFilterProcessorID]; ok { + return mapFromConfigValue(rawFilter, sreMetricsFilterProcessorID) + } + + if rawFilter, ok := filterConfig["filter"]; ok && len(filterConfig) == 1 { + return mapFromConfigValue(rawFilter, "filter") + } + + return filterConfig, nil +} + +func mapFromConfigValue(value interface{}, field string) (map[string]interface{}, error) { + configMap, ok := value.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("%s must be a YAML object", field) + } + if len(configMap) == 0 { + return nil, fmt.Errorf("%s must not be empty", field) + } + return configMap, nil +} + +func resolvedCustomerMetricsDropLabels(configured string) []string { + if strings.TrimSpace(configured) == "" { + return append([]string(nil), defaultCustomerMetricsDropLabels...) + } + + seen := map[string]struct{}{} + labels := []string{} + for _, label := range strings.Split(configured, ",") { + label = strings.TrimSpace(label) + if label == "" { + continue + } + if _, ok := seen[label]; ok { + continue + } + seen[label] = struct{}{} + labels = append(labels, label) + } + return labels +} + func logExporterSendingQueue(batchMaxSizeBytes int) map[string]interface{} { return map[string]interface{}{ "enabled": true, @@ -401,6 +500,97 @@ func exporterMetrics(config TelemetryConfig, otelConfig *OpenTelemetryConfig) (e return exporterId, nil } +func addCustomerMetricsDropLabelsProcessor(otelConfig *OpenTelemetryConfig, labels []string) string { + if len(labels) == 0 { + return "" + } + + actions := make([]map[string]interface{}, 0, len(labels)) + for _, label := range labels { + actions = append(actions, map[string]interface{}{ + "key": label, + "action": "delete", + }) + } + otelConfig.Processors[customerMetricsDropLabelsProcessorID] = map[string]interface{}{ + "attributes": actions, + } + return customerMetricsDropLabelsProcessorID +} + +func addSREMetricsExporter(otelConfig *OpenTelemetryConfig) { + otelConfig.Exporters[sreMetricsExporterID] = map[string]interface{}{ + "endpoint": fmt.Sprintf("${env:OTEL_POD_IP:-0.0.0.0}:%d", defaultSREMetricsPort), + "resource_to_telemetry_conversion": map[string]interface{}{ + "enabled": true, + }, + "send_timestamps": true, + "metric_expiration": "5m", + "enable_open_metrics": true, + } +} + +func cloneConfigMap(config map[string]interface{}) map[string]interface{} { + clone := make(map[string]interface{}, len(config)) + for key, value := range config { + clone[key] = cloneConfigValue(value) + } + return clone +} + +func cloneConfigValue(value interface{}) interface{} { + switch typed := value.(type) { + case map[string]interface{}: + return cloneConfigMap(typed) + case []interface{}: + clone := make([]interface{}, 0, len(typed)) + for _, item := range typed { + clone = append(clone, cloneConfigValue(item)) + } + return clone + case []map[string]interface{}: + clone := make([]map[string]interface{}, 0, len(typed)) + for _, item := range typed { + clone = append(clone, cloneConfigMap(item)) + } + return clone + default: + return value + } +} + +func addSREMetricsPipeline(otelConfig *OpenTelemetryConfig, config SREMetricsConfig) { + addSREMetricsExporter(otelConfig) + + filterConfig := config.FilterConfig + if len(filterConfig) == 0 { + filterConfig = defaultSREMetricsFilterConfig() + } + otelConfig.Processors[sreMetricsFilterProcessorID] = cloneConfigMap(filterConfig) + + batchConfig := map[string]interface{}{ + "send_batch_size": 4096, + "timeout": "400ms", + "send_batch_max_size": 8192, + } + if existingBatchConfig, ok := otelConfig.Processors["batch"]; ok { + batchConfig = cloneConfigMap(existingBatchConfig) + } + otelConfig.Processors[sreMetricsBatchProcessorID] = batchConfig + + sreMetricsPipeline := otelConfig.Service.Pipelines["metrics/sre"] + sreMetricsPipeline.Receivers = []string{"otlp"} + sreMetricsPipeline.Exporters = []string{sreMetricsExporterID} + sreMetricsPipeline.Processors = []string{ + "memory_limiter", + sreMetricsFilterProcessorID, + "resource", + "metrics_transform", + sreMetricsBatchProcessorID, + } + otelConfig.Service.Pipelines["metrics/sre"] = sreMetricsPipeline +} + func exporterTraces(config TelemetryConfig, otelConfig *OpenTelemetryConfig) (exporterId string, err error) { var exporterType, exporterName string var exporterCredential interface{} @@ -624,8 +814,18 @@ func generateExportersAndService(config TelemetryConfig, otelConfig *OpenTelemet metricPipeline := otelConfig.Service.Pipelines["metrics"] metricPipeline.Receivers = []string{"otlp", "prometheus"} metricPipeline.Exporters = []string{exporterId} - metricPipeline.Processors = []string{"memory_limiter", "filter/metrics", "resource", "metrics_transform", "batch"} + metricPipeline.Processors = []string{"memory_limiter", "filter/metrics", "resource"} + if tmplConfig.SREMetrics.Enabled { + if processorID := addCustomerMetricsDropLabelsProcessor(otelConfig, tmplConfig.SREMetrics.CustomerMetricsDropLabels); processorID != "" { + metricPipeline.Processors = append(metricPipeline.Processors, processorID) + } + } + metricPipeline.Processors = append(metricPipeline.Processors, "metrics_transform", "batch") otelConfig.Service.Pipelines["metrics"] = metricPipeline + + if tmplConfig.SREMetrics.Enabled { + addSREMetricsPipeline(otelConfig, tmplConfig.SREMetrics) + } } // Process Traces (if present) diff --git a/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/render_test.go b/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/render_test.go index a25e4ac20..aa8eab97f 100644 --- a/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/render_test.go +++ b/src/compute-plane-services/byoo-otel-collector/internal/otelconfig/render_test.go @@ -18,9 +18,9 @@ limitations under the License. package otelconfig import ( - "testing" - "fmt" + "os" + "testing" "github.com/stretchr/testify/assert" "gopkg.in/yaml.v3" @@ -97,6 +97,99 @@ func TestRenderOtelConfig(t *testing.T) { } } +func TestRenderOtelConfigWithSREMetricsPipeline(t *testing.T) { + gotCfg, err := RenderOtelConfigFromBytes( + []byte(`{"telemetries": {"metricsTelemetry": {"protocol": "HTTP", "provider": "PROMETHEUS", "endpoint": "https://metrics.example.invalid/api/v1/write", "name": "example-metrics"}}}`), + TemplateConfig{ + BackendType: K8s, + WorkloadType: Container, + Namespace: "sr-fake-namespace", + FunctionID: "fake-function-id", + FunctionVersionID: "fake-function-version-id", + InstanceID: "fake-instance-id", + ZoneName: "fake-zone-name", + SREMetrics: SREMetricsConfig{ + Enabled: true, + FilterConfig: defaultSREMetricsFilterConfig(), + CustomerMetricsDropLabels: defaultCustomerMetricsDropLabels, + }, + }, + ) + + assert.NoError(t, err) + + otelConfig := &OpenTelemetryConfig{} + err = yaml.Unmarshal(gotCfg, otelConfig) + assert.NoError(t, err) + assert.Contains(t, otelConfig.Exporters, sreMetricsExporterID) + assert.Contains(t, otelConfig.Processors, sreMetricsFilterProcessorID) + assert.Contains(t, otelConfig.Processors, sreMetricsBatchProcessorID) + assert.Equal(t, []string{"otlp"}, otelConfig.Service.Pipelines["metrics/sre"].Receivers) + assert.Equal(t, []string{sreMetricsExporterID}, otelConfig.Service.Pipelines["metrics/sre"].Exporters) + assert.Equal(t, []string{ + "memory_limiter", + sreMetricsFilterProcessorID, + "resource", + "metrics_transform", + sreMetricsBatchProcessorID, + }, otelConfig.Service.Pipelines["metrics/sre"].Processors) +} + +func TestRenderOtelConfigWithSREMetricsPipelineMatchesExample(t *testing.T) { + t.Setenv("ESS_SECRETS_PATH", "") + + gotCfg, err := RenderOtelConfigFromBytes( + []byte(`{"telemetries": {"metricsTelemetry": {"protocol": "HTTP", "provider": "PROMETHEUS", "endpoint": "https://customer-metrics.example.invalid/api/v1/write", "name": "customer-metrics"}}}`), + TemplateConfig{ + BackendType: K8s, + WorkloadType: Container, + Namespace: "sr-fake-namespace", + FunctionID: "fake-function-id", + FunctionVersionID: "fake-function-version-id", + InstanceID: "fake-instance-id", + ZoneName: "fake-zone-name", + SREMetrics: SREMetricsConfig{ + Enabled: true, + FilterConfig: defaultSREMetricsFilterConfig(), + CustomerMetricsDropLabels: defaultCustomerMetricsDropLabels, + }, + }, + ) + if err != nil { + t.Fatalf("failed to render SRE metrics config: %v", err) + } + + const examplePath = "../../examples/otelconfigs/k8s/config_function_container_sre_metrics.yaml" + if os.Getenv("UPDATE_SRE_METRICS_EXAMPLE") == "true" { + if err := os.WriteFile(examplePath, gotCfg, 0o644); err != nil { + t.Fatalf("failed to update SRE metrics example config: %v", err) + } + } + + expectedCfg, err := os.ReadFile(examplePath) + if err != nil { + t.Fatalf("failed to read SRE metrics example config: %v", err) + } + + assertYAMLConfigEqual(t, expectedCfg, gotCfg) +} + +func assertYAMLConfigEqual(t *testing.T, expectedYAML, actualYAML []byte) { + t.Helper() + + var actualMap, expectedMap map[string]interface{} + if err := yaml.Unmarshal(actualYAML, &actualMap); err != nil { + t.Fatalf("failed to unmarshal actual YAML to map: %v", err) + } + if err := yaml.Unmarshal(expectedYAML, &expectedMap); err != nil { + t.Fatalf("failed to unmarshal expected YAML to map: %v", err) + } + + if !assert.Equal(t, expectedMap, actualMap) { + t.Errorf("transformed OtelConfig mismatch:\nExpected OtelConfig YAML:\n%s\n\nActual OtelConfigYAML:\n%s", string(expectedYAML), string(actualYAML)) + } +} + // returns the expected OpenTelemetry YAML configuration as a byte slice for function workloads func createExpectedOtelConfigYAMLForInternalTelemetryFunction(tracesTelemetryName string) []byte { internalTelemetryYAMLString := fmt.Sprintf(`receivers: {} @@ -394,6 +487,113 @@ func TestGenerateExportersAndServiceUsesCustomLogExporterBatchMaxSize(t *testing }, exporter["sending_queue"]) } +func TestGenerateExportersAndServiceAddsSREMetricsPipeline(t *testing.T) { + cfg := TelemetryConfig{ + Telemetries: Telemetries{ + Metrics: &Telemetry{ + Name: "example-metrics", + Protocol: ProtocolHTTP, + Provider: ProviderPrometheus, + Endpoint: "https://metrics.example.invalid/api/v1/write", + }, + }, + } + otelConfig := &OpenTelemetryConfig{} + initializeConfigMaps(otelConfig) + otelConfig.Processors["batch"] = map[string]interface{}{ + "send_batch_size": 4096, + "timeout": "400ms", + "send_batch_max_size": 8192, + } + filterConfig := map[string]interface{}{ + "error_mode": "ignore", + "metric_conditions": []string{ + `metric.name != "RtdInstrument"`, + }, + } + + err := generateExportersAndService(cfg, otelConfig, TemplateConfig{ + Namespace: "test-namespace", + SREMetrics: SREMetricsConfig{ + Enabled: true, + FilterConfig: filterConfig, + CustomerMetricsDropLabels: []string{"sre_metrics_enabled"}, + }, + }) + + assert.NoError(t, err) + assert.Equal(t, map[string]interface{}{ + "endpoint": "${env:OTEL_POD_IP:-0.0.0.0}:19091", + "resource_to_telemetry_conversion": map[string]interface{}{ + "enabled": true, + }, + "send_timestamps": true, + "metric_expiration": "5m", + "enable_open_metrics": true, + }, otelConfig.Exporters[sreMetricsExporterID]) + assert.Equal(t, filterConfig, otelConfig.Processors[sreMetricsFilterProcessorID]) + assert.Equal(t, otelConfig.Processors["batch"], otelConfig.Processors[sreMetricsBatchProcessorID]) + + customerMetricsPipeline := otelConfig.Service.Pipelines["metrics"] + assert.Equal(t, []string{"otlp", "prometheus"}, customerMetricsPipeline.Receivers) + assert.Equal(t, []string{"prometheusremotewrite/PROMETHEUS-example-metrics-metrics"}, customerMetricsPipeline.Exporters) + assert.Equal(t, []string{ + "memory_limiter", + "filter/metrics", + "resource", + customerMetricsDropLabelsProcessorID, + "metrics_transform", + "batch", + }, customerMetricsPipeline.Processors) + assert.NotContains(t, customerMetricsPipeline.Processors, sreMetricsFilterProcessorID) + assert.Equal(t, map[string]interface{}{ + "attributes": []map[string]interface{}{ + { + "key": "sre_metrics_enabled", + "action": "delete", + }, + }, + }, otelConfig.Processors[customerMetricsDropLabelsProcessorID]) + + sreMetricsPipeline := otelConfig.Service.Pipelines["metrics/sre"] + assert.Equal(t, []string{"otlp"}, sreMetricsPipeline.Receivers) + assert.Equal(t, []string{sreMetricsExporterID}, sreMetricsPipeline.Exporters) + assert.Equal(t, []string{ + "memory_limiter", + sreMetricsFilterProcessorID, + "resource", + "metrics_transform", + sreMetricsBatchProcessorID, + }, sreMetricsPipeline.Processors) +} + +func TestGenerateExportersAndServiceDoesNotAddSREMetricsPipelineWithoutCustomerMetrics(t *testing.T) { + cfg := TelemetryConfig{ + Telemetries: Telemetries{ + Logs: &Telemetry{ + Name: "example-logs", + Protocol: ProtocolHTTP, + Provider: ProviderSplunk, + Endpoint: "https://splunk.example.invalid", + }, + }, + } + otelConfig := &OpenTelemetryConfig{} + initializeConfigMaps(otelConfig) + + err := generateExportersAndService(cfg, otelConfig, TemplateConfig{ + Namespace: "test-namespace", + SREMetrics: SREMetricsConfig{ + Enabled: true, + }, + }) + + assert.NoError(t, err) + assert.NotContains(t, otelConfig.Exporters, sreMetricsExporterID) + assert.NotContains(t, otelConfig.Processors, sreMetricsFilterProcessorID) + assert.NotContains(t, otelConfig.Service.Pipelines, "metrics/sre") +} + // Test_exporterMetrics_Datadog_KeepsFirstCumulativeSample is a regression test // for the missing nvct_worker_service_result_total metric in Datadog (task // scenario). Without metrics.sums.initial_cumulative_monotonic_value=keep, the diff --git a/src/compute-plane-services/byoo-otel-collector/otel-collector-build.yaml b/src/compute-plane-services/byoo-otel-collector/otel-collector-build.yaml index 78b2f217e..b09998913 100644 --- a/src/compute-plane-services/byoo-otel-collector/otel-collector-build.yaml +++ b/src/compute-plane-services/byoo-otel-collector/otel-collector-build.yaml @@ -16,6 +16,7 @@ exporters: - gomod: go.opentelemetry.io/collector/exporter/otlpexporter v0.153.0 - gomod: go.opentelemetry.io/collector/exporter/debugexporter v0.153.0 - gomod: go.opentelemetry.io/collector/exporter/otlphttpexporter v0.153.0 + - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter v0.153.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusremotewriteexporter v0.153.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter v0.153.0 - gomod: github.com/open-telemetry/opentelemetry-collector-contrib/exporter/splunkhecexporter v0.153.0 diff --git a/src/compute-plane-services/byoo-otel-collector/otelcol/components.go b/src/compute-plane-services/byoo-otel-collector/otelcol/components.go index 6e22eeba1..ecd7874e9 100644 --- a/src/compute-plane-services/byoo-otel-collector/otelcol/components.go +++ b/src/compute-plane-services/byoo-otel-collector/otelcol/components.go @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT. package main @@ -9,6 +6,7 @@ import ( logchunkprocessor "github.com/NVIDIA/nvcf/src/compute-plane-services/byoo-otel-collector/otelcol/logchunkprocessor" azuremonitorexporter "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/azuremonitorexporter" datadogexporter "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter" + prometheusexporter "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter" prometheusremotewriteexporter "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusremotewriteexporter" splunkhecexporter "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/splunkhecexporter" basicauthextension "github.com/open-telemetry/opentelemetry-collector-contrib/extension/basicauthextension" @@ -100,6 +98,7 @@ func components() (otelcol.Factories, error) { otlpexporter.NewFactory(), debugexporter.NewFactory(), otlphttpexporter.NewFactory(), + prometheusexporter.NewFactory(), prometheusremotewriteexporter.NewFactory(), datadogexporter.NewFactory(), splunkhecexporter.NewFactory(), @@ -112,6 +111,7 @@ func components() (otelcol.Factories, error) { otlpexporter.NewFactory().Type(): "go.opentelemetry.io/collector/exporter/otlpexporter v0.153.0", debugexporter.NewFactory().Type(): "go.opentelemetry.io/collector/exporter/debugexporter v0.153.0", otlphttpexporter.NewFactory().Type(): "go.opentelemetry.io/collector/exporter/otlphttpexporter v0.153.0", + prometheusexporter.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter v0.153.0", prometheusremotewriteexporter.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusremotewriteexporter v0.153.0", datadogexporter.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter v0.153.0", splunkhecexporter.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/splunkhecexporter v0.153.0", diff --git a/src/compute-plane-services/byoo-otel-collector/otelcol/go.mod b/src/compute-plane-services/byoo-otel-collector/otelcol/go.mod index b0e9556b2..e513cfa99 100644 --- a/src/compute-plane-services/byoo-otel-collector/otelcol/go.mod +++ b/src/compute-plane-services/byoo-otel-collector/otelcol/go.mod @@ -7,6 +7,7 @@ go 1.25.0 require ( github.com/open-telemetry/opentelemetry-collector-contrib/exporter/azuremonitorexporter v0.153.0 github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter v0.153.0 + github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter v0.153.0 github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusremotewriteexporter v0.153.0 github.com/open-telemetry/opentelemetry-collector-contrib/exporter/splunkhecexporter v0.153.0 github.com/open-telemetry/opentelemetry-collector-contrib/extension/basicauthextension v0.153.0 diff --git a/src/compute-plane-services/byoo-otel-collector/otelcol/go.sum b/src/compute-plane-services/byoo-otel-collector/otelcol/go.sum index 4091b7bb1..1d75c699d 100644 --- a/src/compute-plane-services/byoo-otel-collector/otelcol/go.sum +++ b/src/compute-plane-services/byoo-otel-collector/otelcol/go.sum @@ -823,6 +823,8 @@ github.com/open-telemetry/opentelemetry-collector-contrib/exporter/azuremonitore github.com/open-telemetry/opentelemetry-collector-contrib/exporter/azuremonitorexporter v0.153.0/go.mod h1:B3DD+QqpXAv7/KelRpJvQS4ZF9lxyPHI4hv/Q42tm0Y= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter v0.153.0 h1:BBmppD58DikPVc4Qbe7LLQGcJ16Garp7eDj2hXciiNY= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter v0.153.0/go.mod h1:qAcTyFamjbP9DB8orjBnn4/1sqNf482+fRi3/aGVlxA= +github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter v0.153.0 h1:f5SoWPkFx0w0ypTWMVhlOZCYQn4LX9/MuiH0nBuFxq0= +github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter v0.153.0/go.mod h1:1tueNSD8qlts25XBria7K+I/boqV0LFGFMGp+JOQubk= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusremotewriteexporter v0.153.0 h1:5SPL5A2wZmNpjgbJLYJs7RwstUjPeF6zLu563XeTYUE= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusremotewriteexporter v0.153.0/go.mod h1:HeB2i3y+yUSJgaxI8xGV2OTykzRM07rXHOCQgZi/+NA= github.com/open-telemetry/opentelemetry-collector-contrib/exporter/splunkhecexporter v0.153.0 h1:fcRUge6lGz8NSFPtmgFPeddaIjxzQaQG1fzCyum9hZg= diff --git a/src/compute-plane-services/byoo-otel-collector/otelcol/main.go b/src/compute-plane-services/byoo-otel-collector/otelcol/main.go index 0a7c5f40b..caed2d84d 100644 --- a/src/compute-plane-services/byoo-otel-collector/otelcol/main.go +++ b/src/compute-plane-services/byoo-otel-collector/otelcol/main.go @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT. // Program otelcol-contrib is an OpenTelemetry Collector binary. diff --git a/src/compute-plane-services/byoo-otel-collector/otelcol/main_others.go b/src/compute-plane-services/byoo-otel-collector/otelcol/main_others.go index fa6e3a10e..3735aecb5 100644 --- a/src/compute-plane-services/byoo-otel-collector/otelcol/main_others.go +++ b/src/compute-plane-services/byoo-otel-collector/otelcol/main_others.go @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT. //go:build !windows diff --git a/src/compute-plane-services/byoo-otel-collector/otelcol/main_windows.go b/src/compute-plane-services/byoo-otel-collector/otelcol/main_windows.go index cf4b13309..a4930afdc 100644 --- a/src/compute-plane-services/byoo-otel-collector/otelcol/main_windows.go +++ b/src/compute-plane-services/byoo-otel-collector/otelcol/main_windows.go @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - // Code generated by "go.opentelemetry.io/collector/cmd/builder". DO NOT EDIT. //go:build windows