From fb1eb17651d741131d00022ea3c372ddfc63a19b Mon Sep 17 00:00:00 2001 From: Francisco Delgado Lopez Date: Mon, 19 Oct 2026 14:23:52 +0000 Subject: [PATCH] feat: refresh exporter reliability and OpenShell 0.1 support Signed-off-by: Francisco Delgado Lopez --- projects/tools/openshell-exporter/Dockerfile | 4 +- projects/tools/openshell-exporter/README.md | 93 ++- .../cmd/healthcheck/main.go | 13 +- .../cmd/healthcheck/status.go | 173 +++++ .../cmd/healthcheck/status_test.go | 102 +++ .../openshell-event-exporter/components.go | 26 +- .../cmd/openshell-event-exporter/main.go | 6 +- projects/tools/openshell-exporter/config.yaml | 62 +- .../acknowledgement_test.go | 48 +- .../cloudeventsexporter/config_test.go | 4 +- .../cloudeventsexporter/exporter_test.go | 2 +- .../exporter/cloudeventsexporter/factory.go | 2 +- .../lifecycle_security_test.go | 2 +- .../exporter/cloudeventsexporter/metrics.go | 16 +- projects/tools/openshell-exporter/go.mod | 265 ++++---- projects/tools/openshell-exporter/go.sum | 596 +++++++++--------- .../processor/openshellprocessor/config.go | 2 + .../processor/openshellprocessor/context.go | 71 +++ .../openshellprocessor/context_test.go | 126 ++++ .../processor/openshellprocessor/envelope.go | 24 +- .../processor/openshellprocessor/factory.go | 33 +- .../openshellprocessor/metrics_test.go | 17 + .../processor/openshellprocessor/processor.go | 6 +- .../openshellprocessor/processor_test.go | 188 +++++- .../openshellprocessor/source_capability.go | 16 +- .../source_capability_test.go | 6 +- .../openshellprocessor/validation.go | 6 +- .../receiver/watchsandboxreceiver/client.go | 78 ++- .../receiver/watchsandboxreceiver/convert.go | 22 +- .../receiver/watchsandboxreceiver/metrics.go | 10 + .../watchsandboxreceiver/pagination_test.go | 135 +++- .../watchsandboxreceiver/policy_convert.go | 24 +- .../receiver/watchsandboxreceiver/receiver.go | 97 ++- .../receiver_lifecycle_test.go | 320 +++++++++- .../watchsandboxreceiver/receiver_test.go | 74 ++- .../watchsandboxreceiver/reconciler.go | 2 +- .../watchsandboxreceiver/reconciler_test.go | 6 +- .../reconciliation_state_test.go | 10 +- projects/tools/openshell-exporter/source.json | 89 +++ .../openshell-exporter/template.config.yaml | 64 +- 40 files changed, 2224 insertions(+), 616 deletions(-) create mode 100644 projects/tools/openshell-exporter/cmd/healthcheck/status.go create mode 100644 projects/tools/openshell-exporter/cmd/healthcheck/status_test.go create mode 100644 projects/tools/openshell-exporter/processor/openshellprocessor/context.go create mode 100644 projects/tools/openshell-exporter/processor/openshellprocessor/context_test.go create mode 100644 projects/tools/openshell-exporter/source.json diff --git a/projects/tools/openshell-exporter/Dockerfile b/projects/tools/openshell-exporter/Dockerfile index 3e2161fe..6a3e7bdb 100644 --- a/projects/tools/openshell-exporter/Dockerfile +++ b/projects/tools/openshell-exporter/Dockerfile @@ -1,5 +1,5 @@ -# syntax=docker/dockerfile:1.19@sha256:b6afd42430b15f2d2a4c5a02b919e98a525b785b1aaff16747d2f623364e39b6 -FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.26.8-bookworm@sha256:9fdc884aacc3bec89b20ffc69f4bb369c78210e3e4f600387b5128b12c199f81 AS builder +# syntax=docker/dockerfile:1.28.0@sha256:bb22d9815c728170f72750f4e5b0d672e06176142e1d602c7e66c050100b7e5b +FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.27.2-bookworm@sha256:5cf287a799e6b94384bad13d16b14904c531f51ba65792237e122ce42b392f61 AS builder ARG TARGETOS ARG TARGETARCH WORKDIR /src diff --git a/projects/tools/openshell-exporter/README.md b/projects/tools/openshell-exporter/README.md index b264cd15..f3aad2c7 100644 --- a/projects/tools/openshell-exporter/README.md +++ b/projects/tools/openshell-exporter/README.md @@ -8,9 +8,12 @@ provided as-is; use at your own risk. For other deployment methods and more advanced features, contact [delgadof@nvidia.com](mailto:delgadof@nvidia.com). +Gateway API collection requires OpenShell >=0.1.0; the current target is v0.1.3. +The first run below uses a sample file and needs no gateway. + ## Quickstart: local process -Use [Go 1.26.8](https://go.dev/doc/install) and a Bash-compatible shell. Get the +Use [Go 1.27.2](https://go.dev/doc/install) and a Bash-compatible shell. Get the source and enter the project directory: ```sh @@ -18,9 +21,8 @@ git clone https://github.com/NVIDIA/OpenShell-Research.git cd OpenShell-Research/projects/tools/openshell-exporter ``` -The build -downloads public dependencies. This first run uses a synthetic OCSF record; it -needs no OpenShell gateway, credentials, or model service. +The build downloads public dependencies. The synthetic sample needs no +credentials or model service. ```sh go build -o bin/openshell-event-exporter ./cmd/openshell-event-exporter @@ -59,15 +61,15 @@ The image health check probes `127.0.0.1:13133`; retain that port inside the container. Its optional `healthcheck --writable DIRECTORY ...` command checks persistence-directory permissions. -Use the same health and output checks. With existing checkpoints the example is -not replayed; append a new record to test more delivery. Stop with +Use the same health and output checks as the local process. Saved checkpoints +prevent replay of the example; append a new record to test more delivery. Stop with `docker stop openshell-exporter`. Build locally; no published image is required. Linux AMD64/ARM64 and native macOS ARM64 are build targets; Docker on Apple Silicon runs the Linux ARM64 image through Docker Desktop. -## Connect real inputs and destinations +## Choose real inputs -For actual OCSF logs, set `receivers.file_log/ocsf.include` in [config.yaml](config.yaml) +For existing OCSF JSONL, set `receivers.file_log/ocsf.include` in [config.yaml](config.yaml) to the readable source file glob. In Docker, mount the source directory read-only and use its container path in the glob. Mount the directory, so rotated files remain visible. Logs inside an OpenShell sandbox must first be made accessible to the @@ -79,11 +81,62 @@ filtering, and delivery. Select the needed pipelines and mount their credentials and persistent storage. The template is a reference, not a ready-to-run deployment. `openshell-event-exporter components` lists the full component set. -For an HTTPS receiver that expects **bare OCSF inside CloudEvents `data`**, use -[http.config.yaml](http.config.yaml). It reads the same input files and sends -CloudEvents batches with a persistent retry queue. This configuration bypasses -normalization and redaction; source content is forwarded as supplied. Provision -`secrets/destination-token` (raw bearer token) and `secrets/destination-ca.pem` +### Gateway and supervisor logs (v0.1.3) + +The default config includes two additional inputs: + +| Source | Path on the host | +|---|---| +| Gateway JSONL | `input/gateways/*/gateway-ocsf.jsonl*` | +| Captured supervisor stream | `input/supervisors/*/stderr.log*` | + +Docker mounts these below `/work/input`. Keep replicas in separate directories, +and retain rotation segments and checkpoints. + +Enable gateway JSONL in its `gateway.toml`, using a writable persistent path: + +```toml +[openshell.gateway.ocsf_log] +path = "/path/to/input/gateways/replica-1/gateway-ocsf.jsonl" +rotation = "daily" +max_files = 7 +``` + +Restart the gateway after changing its configuration. Gateway-wide records may +have no sandbox association. This output does not include supervisor OCSF. + +For supervisor records, enable `ocsf_json_enabled` with an authorized OpenShell +administrator, then capture the raw platform log stream: + +```sh +openshell settings set --global --key ocsf_json_enabled --value true +mkdir -p input/supervisors/sandbox-1 +docker logs --follow SUPERVISOR_CONTAINER > input/supervisors/sandbox-1/stderr.log 2>&1 +``` + +Use `podman logs` in place of `docker logs` when appropriate. This command stays +attached; run the exporter separately. The parser selects `OCSF-JSON` lines, +decodes the payload, and ignores shorthand copies. It expects the unwrapped +platform stream, not Docker JSON/CRI storage wrappers or an extra timestamp +prefix. Collect one structured path per producer; do not also ship that supervisor's JSONL files. +A replayed platform-log capture can duplicate events; `correlation.ocsf_event_uid` +retains the native ID for downstream correlation without changing exporter IDs. + +Keep `ocsf_schema_version` unset: this exporter validates native 1.8.0 and replay +1.7.0, not the lossy 1.1/1.3 downgrade. Both upstream sinks are best-effort; source +queue loss or deleted runtime logs cannot be recovered by exporter checkpoints. + +## Send to an HTTPS receiver + +[http.config.yaml](http.config.yaml) reads the original JSONL inputs and sends +**bare OCSF inside CloudEvents `data`**, using a persistent retry queue. +It bypasses normalization and redaction: source content is forwarded as supplied. +For normalized, redacted delivery, copy `processors.openshell` from `config.yaml` +into `http.config.yaml`, then set `service.pipelines.logs.processors` to +`[memory_limiter, openshell]`. Your receiver must read the OCSF record from +`data.original`. + +Provision `secrets/destination-token` (raw bearer token) and `secrets/destination-ca.pem` (the trusted issuing CA), restrict their access, then run: ```sh @@ -100,11 +153,8 @@ Docker Desktop can reach a host receiver using `host.docker.internal`; Linux Docker Engine can add `--add-host host.docker.internal:host-gateway`. The receiver must listen on a reachable interface. Bearer authentication requires HTTPS. -For normalized, redacted HTTP delivery, add `openshell` from `config.yaml` to that -pipeline after `memory_limiter`. The receiver must then read the redacted OCSF -record from `data.original`. A 2xx acknowledges a batch; retryable failures retry -and may produce duplicates. Consumers should deduplicate by `(source,id)`. -Raw mode hashes the body for identity, so identical source bodies share an ID. +A 2xx acknowledges a batch; retryable failures may produce duplicates. Consumers should deduplicate by `(source,id)`. +In raw mode, identical source bodies share an ID. Append a new input record when switching configurations; saved checkpoints do not replay records already read. Health and local recovery output alone do not establish successful remote delivery. @@ -119,9 +169,8 @@ and exporter logs. The exporter observes evidence; it does not approve policy ch `go install ./cmd/openshell-event-exporter` installs from this checkout. The module path is `github.com/NVIDIA/OpenShell-Research/projects/tools/openshell-exporter`; a remote `go install ...@version` needs a public release tagged -`projects/tools/openshell-exporter/v`. No such release is published by -this change. -Custom Collectors can import the component packages and register their `NewFactory`. +`projects/tools/openshell-exporter/v`. No such release is published by this change. +Custom Collectors can import component packages and register their `NewFactory`. ```sh go mod verify @@ -137,7 +186,7 @@ exporter does not compile those packages: `go list -deps ./...` contains no dependencies change. The source is extracted from exporter snapshot -`6a440f05249ac05aa9b9ef8acada4c909ec86bc8`. This distribution retains the Go +`75a41db6be6cc6ad160e3619ad09270d1cdb5b1d`. This distribution retains the Go implementation and component tests; deployment tooling lives separately. Preserve LICENSE and NOTICE when redistributing. Synthetic local and container checks do not qualify live gateway or external application behavior. diff --git a/projects/tools/openshell-exporter/cmd/healthcheck/main.go b/projects/tools/openshell-exporter/cmd/healthcheck/main.go index 6e3688ae..709363c6 100644 --- a/projects/tools/openshell-exporter/cmd/healthcheck/main.go +++ b/projects/tools/openshell-exporter/cmd/healthcheck/main.go @@ -14,8 +14,19 @@ import ( func main() { if len(os.Args) > 1 { + if os.Args[1] == "--status" && len(os.Args) <= 3 { + endpoint := "http://127.0.0.1:8888/metrics" + if len(os.Args) == 3 { + endpoint = os.Args[2] + } + if err := deliveryStatus(context.Background(), os.Stdout, endpoint); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + return + } if os.Args[1] != "--writable" || len(os.Args) < 3 { - fmt.Fprintln(os.Stderr, "usage: healthcheck [--writable DIRECTORY ...]") + fmt.Fprintln(os.Stderr, "usage: healthcheck [--writable DIRECTORY ... | --status [METRICS_URL]]") os.Exit(2) } for _, directory := range os.Args[2:] { diff --git a/projects/tools/openshell-exporter/cmd/healthcheck/status.go b/projects/tools/openshell-exporter/cmd/healthcheck/status.go new file mode 100644 index 00000000..4b3b1fbe --- /dev/null +++ b/projects/tools/openshell-exporter/cmd/healthcheck/status.go @@ -0,0 +1,173 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "bufio" + "context" + "fmt" + "io" + "math" + "net/http" + "net/url" + "sort" + "strconv" + "strings" + "time" +) + +type statusMetric struct { + name string + label string + timestamp bool +} + +var statusSections = []struct { + name string + metrics []statusMetric +}{ + {"Sources (observation is not destination delivery)", []statusMetric{ + {"openshell_exporter_source_configured", "Configured profile", false}, + {"openshell_exporter_source_enabled", "Enabled receiver", false}, + {"openshell_exporter_source_observed", "Observed profile", false}, + {"openshell_exporter_source_last_success_unixtime", "Last observation (UTC)", true}, + }}, + {"CloudEvents delivery (HTTP acknowledgement only)", []statusMetric{ + {"openshell_exporter_delivery_events", "Acknowledged events", false}, + {"openshell_exporter_destination_last_success_unixtime", "Last acknowledgement (UTC)", true}, + {"openshell_exporter_delivery_retryable_failures", "Retryable failures", false}, + {"openshell_exporter_delivery_permanent_rejections", "Permanently rejected responses", false}, + {"openshell_exporter_events_oversized", "Oversized events", false}, + }}, + {"Collector queues (units follow configured queue sizer; excludes in-flight sends)", []statusMetric{ + {"otelcol_exporter_queue_size", "Backlog", false}, + {"otelcol_exporter_queue_capacity", "Capacity", false}, + {"otelcol_exporter_enqueue_failed_log_records", "Enqueue failures", false}, + {"otelcol_exporter_send_failed_log_records", "Send failures", false}, + }}, + {"WatchSandbox (non-resumable)", []statusMetric{ + {"openshell_exporter_stream_reconnects", "Reconnects", false}, + {"openshell_exporter_stream_gap_warnings", "Gap risks", false}, + {"openshell_exporter_stream_backpressure_active", "Waiting to retry downstream", false}, + {"openshell_exporter_stream_unacknowledged_records", "Unacknowledged source records", false}, + }}, + {"Storage (availability is a probe, not proof of durable delivery)", []statusMetric{ + {"openshell_exporter_storage_configured", "Configured", false}, + {"openshell_exporter_storage_available", "Available (1=yes, 0=no)", false}, + {"openshell_exporter_storage_free_bytes", "Free bytes", false}, + {"openshell_exporter_storage_free_inodes", "Free inodes", false}, + {"openshell_exporter_storage_scan_truncated", "State scan truncated (1=yes)", false}, + }}, +} + +// deliveryStatus is deliberately observational: neither zero backlog nor an HTTP +// acknowledgement proves that every source event reached durable destination storage. +func deliveryStatus(ctx context.Context, output io.Writer, endpoint string) error { + u, err := url.Parse(endpoint) + if err != nil || (u.Scheme != "http" && u.Scheme != "https") || u.Host == "" || u.User != nil { + return fmt.Errorf("status endpoint must be an HTTP(S) metrics URL without embedded credentials") + } + ctx, cancel := context.WithTimeout(ctx, 3*time.Second) + defer cancel() + request, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil) + if err != nil { + return err + } + client := &http.Client{CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }} + response, err := client.Do(request) + if err != nil { + return fmt.Errorf("read metrics: %w", err) + } + defer func() { _ = response.Body.Close() }() + if response.StatusCode != http.StatusOK { + return fmt.Errorf("metrics endpoint returned HTTP %d", response.StatusCode) + } + const maxBytes = 4 << 20 + body, err := io.ReadAll(io.LimitReader(response.Body, maxBytes+1)) + if err != nil { + return fmt.Errorf("read metrics body: %w", err) + } + if len(body) > maxBytes { + return fmt.Errorf("metrics response exceeds %d bytes", maxBytes) + } + return renderStatus(output, string(body)) +} + +func renderStatus(output io.Writer, body string) error { + wanted := map[string]statusMetric{} + for _, section := range statusSections { + for _, m := range section.metrics { + wanted[m.name] = m + } + } + values := map[string][]string{} + scanner := bufio.NewScanner(strings.NewReader(body)) + scanner.Buffer(make([]byte, 4096), 1<<20) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + end := strings.IndexAny(line, "{ \t") + if end < 0 { + continue + } + name := line[:end] + // Accommodate Prometheus exporters that append the conventional counter suffix. + name = strings.TrimSuffix(name, "_total") + m, ok := wanted[name] + if !ok { + continue + } + rest := strings.TrimSpace(line[end:]) + labels := "" + if strings.HasPrefix(rest, "{") { + end = strings.LastIndexByte(rest, '}') + if end < 0 { + return fmt.Errorf("malformed labels for %s", name) + } + labels, rest = rest[:end+1], rest[end+1:] + } + fields := strings.Fields(rest) + if len(fields) < 1 || len(fields) > 2 { + return fmt.Errorf("malformed sample for %s", name) + } + value, err := strconv.ParseFloat(fields[0], 64) + if err != nil { + return fmt.Errorf("invalid value for %s", name) + } + formatted := fields[0] + if math.IsNaN(value) || math.IsInf(value, 0) || value < 0 { + formatted = "unavailable" + } else if m.timestamp { + if value == 0 || value >= float64(math.MaxInt64) { + formatted = "not recorded" + } else { + formatted = time.Unix(int64(value), 0).UTC().Format(time.RFC3339) + } + } + values[name] = append(values[name], fmt.Sprintf(" %s %s: %s\n", m.label, labels, formatted)) + } + if err := scanner.Err(); err != nil { + return fmt.Errorf("parse metrics: %w", err) + } + var result strings.Builder + result.WriteString("Delivery snapshot. Counters are cumulative since process start; compare successive snapshots.\nMissing metrics are unavailable, never assumed zero. This is not a delivery health verdict.\n") + for _, section := range statusSections { + fmt.Fprintf(&result, "\n%s\n", section.name) + for _, m := range section.metrics { + rows := values[m.name] + if len(rows) == 0 { + fmt.Fprintf(&result, " %s: unavailable\n", m.label) + continue + } + sort.Strings(rows) + for _, row := range rows { + result.WriteString(row) + } + } + } + _, err := io.WriteString(output, result.String()) + return err +} diff --git a/projects/tools/openshell-exporter/cmd/healthcheck/status_test.go b/projects/tools/openshell-exporter/cmd/healthcheck/status_test.go new file mode 100644 index 00000000..05bc831c --- /dev/null +++ b/projects/tools/openshell-exporter/cmd/healthcheck/status_test.go @@ -0,0 +1,102 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. +// SPDX-License-Identifier: Apache-2.0 + +package main + +import ( + "bytes" + "context" + "net/http" + "net/http/httptest" + "strings" + "testing" +) + +func TestStatusDistinguishesObservationAcknowledgementAndMissingMetrics(t *testing.T) { + const scrape = `# HELP ignored arbitrary text +openshell_exporter_source_last_success_unixtime{source="ocsf",producer="openshellprocessor"} 1700000000 +openshell_exporter_destination_last_success_unixtime{exporter="cloudevents/a"} 1700000010 +openshell_exporter_delivery_events_total{exporter="cloudevents/a",status_code="202"} 10 +openshell_exporter_delivery_permanent_rejections{exporter="cloudevents/b",status_code="400"} 2 +otelcol_exporter_queue_size{exporter="cloudevents/b"} 7 +otelcol_exporter_queue_capacity{exporter="cloudevents/b"} 100 +openshell_exporter_storage_available{storage="cloudevents_queue"} 0 +openshell_exporter_storage_free_bytes{storage="cloudevents_queue"} NaN +unrelated_metric{secret="not-to-be-printed"} 42 +` + var output bytes.Buffer + if err := renderStatus(&output, scrape); err != nil { + t.Fatal(err) + } + for _, want := range []string{ + "observation is not destination delivery", + "Last observation (UTC) {source=\"ocsf\",producer=\"openshellprocessor\"}: 2023-11-14T22:13:20Z", + "Last acknowledgement (UTC) {exporter=\"cloudevents/a\"}: 2023-11-14T22:13:30Z", + "Acknowledged events {exporter=\"cloudevents/a\",status_code=\"202\"}: 10", + "Permanently rejected responses {exporter=\"cloudevents/b\",status_code=\"400\"}: 2", + "Backlog {exporter=\"cloudevents/b\"}: 7", + "Available (1=yes, 0=no) {storage=\"cloudevents_queue\"}: 0", + "Free bytes {storage=\"cloudevents_queue\"}: unavailable", + "Reconnects: unavailable", + } { + if !strings.Contains(output.String(), want) { + t.Errorf("missing %q in status:\n%s", want, &output) + } + } + if strings.Contains(output.String(), "not-to-be-printed") { + t.Fatal("unrelated metrics reached output") + } +} + +func TestStatusRejectsFailedRedirectedOversizedAndMalformedScrapes(t *testing.T) { + for _, tc := range []struct { + name, body string + code int + }{ + {"unavailable", "", 503}, + {"redirect", "", 302}, + {"oversized", strings.Repeat("x", (4<<20)+1), 200}, + {"bad value", "otelcol_exporter_queue_size nope", 200}, + {"bad labels", "otelcol_exporter_queue_size{ 1", 200}, + } { + t.Run(tc.name, func(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Location", "/redirect") + w.WriteHeader(tc.code) + _, _ = w.Write([]byte(tc.body)) + })) + defer server.Close() + var output bytes.Buffer + if err := deliveryStatus(t.Context(), &output, server.URL); err == nil { + t.Fatal("bad scrape accepted") + } + if output.Len() != 0 { + t.Fatal("partial status emitted after failed scrape") + } + }) + } +} + +func TestStatusFetchAndCancellation(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + _, _ = w.Write([]byte("otelcol_exporter_queue_size{exporter=\"cloudevents\"} 0\n")) + })) + defer server.Close() + var output bytes.Buffer + if err := deliveryStatus(t.Context(), &output, server.URL); err != nil { + t.Fatal(err) + } + if !strings.Contains(output.String(), "Last acknowledgement (UTC): unavailable") { + t.Fatal("missing acknowledgement treated as successful delivery") + } + ctx, cancel := context.WithCancel(t.Context()) + cancel() + if err := deliveryStatus(ctx, &output, server.URL); err == nil { + t.Fatal("cancellation ignored") + } + for _, endpoint := range []string{"file:///etc/passwd", "http://user:password@localhost/metrics", ":bad"} { + if err := deliveryStatus(t.Context(), &output, endpoint); err == nil { + t.Fatal("unsafe endpoint accepted") + } + } +} diff --git a/projects/tools/openshell-exporter/cmd/openshell-event-exporter/components.go b/projects/tools/openshell-exporter/cmd/openshell-event-exporter/components.go index 3d98002a..07a4bf21 100644 --- a/projects/tools/openshell-exporter/cmd/openshell-event-exporter/components.go +++ b/projects/tools/openshell-exporter/cmd/openshell-event-exporter/components.go @@ -63,9 +63,9 @@ func components() (otelcol.Factories, error) { return otelcol.Factories{}, err } factories.ExtensionModules = makeModulesMap(factories.Extensions, map[component.Type]string{ - bearertokenauthextension.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/extension/bearertokenauthextension v0.160.0", - healthcheckextension.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.160.0", - filestorage.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage v0.160.0", + bearertokenauthextension.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/extension/bearertokenauthextension v0.162.0", + healthcheckextension.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.162.0", + filestorage.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage v0.162.0", storagehealthextension.NewFactory().Type(): "github.com/NVIDIA/OpenShell-Research/projects/tools/openshell-exporter v0.0.5-rc.1", }) @@ -79,9 +79,9 @@ func components() (otelcol.Factories, error) { return otelcol.Factories{}, err } factories.ReceiverModules = makeModulesMap(factories.Receivers, map[component.Type]string{ - otlpreceiver.NewFactory().Type(): "go.opentelemetry.io/collector/receiver/otlpreceiver v0.160.0", - filelogreceiver.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.160.0", - k8sobjectsreceiver.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sobjectsreceiver v0.160.0", + otlpreceiver.NewFactory().Type(): "go.opentelemetry.io/collector/receiver/otlpreceiver v0.162.0", + filelogreceiver.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.162.0", + k8sobjectsreceiver.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sobjectsreceiver v0.162.0", watchsandboxreceiver.NewFactory().Type(): "github.com/NVIDIA/OpenShell-Research/projects/tools/openshell-exporter v0.0.5-rc.1", }) @@ -96,10 +96,10 @@ func components() (otelcol.Factories, error) { return otelcol.Factories{}, err } factories.ExporterModules = makeModulesMap(factories.Exporters, map[component.Type]string{ - otlpexporter.NewFactory().Type(): "go.opentelemetry.io/collector/exporter/otlpexporter v0.160.0", - otlphttpexporter.NewFactory().Type(): "go.opentelemetry.io/collector/exporter/otlphttpexporter v0.160.0", - fileexporter.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v0.160.0", - loadbalancingexporter.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/loadbalancingexporter v0.160.0", + otlpexporter.NewFactory().Type(): "go.opentelemetry.io/collector/exporter/otlpexporter v0.162.0", + otlphttpexporter.NewFactory().Type(): "go.opentelemetry.io/collector/exporter/otlphttpexporter v0.162.0", + fileexporter.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v0.162.0", + loadbalancingexporter.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/loadbalancingexporter v0.162.0", cloudeventsexporter.NewFactory().Type(): "github.com/NVIDIA/OpenShell-Research/projects/tools/openshell-exporter v0.0.5-rc.1", }) @@ -115,9 +115,9 @@ func components() (otelcol.Factories, error) { return otelcol.Factories{}, err } factories.ProcessorModules = makeModulesMap(factories.Processors, map[component.Type]string{ - attributesprocessor.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.160.0", - memorylimiterprocessor.NewFactory().Type(): "go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.160.0", - resourceprocessor.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.160.0", + attributesprocessor.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.162.0", + memorylimiterprocessor.NewFactory().Type(): "go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.162.0", + resourceprocessor.NewFactory().Type(): "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.162.0", evidencecontractprocessor.NewFactory().Type(): "github.com/NVIDIA/OpenShell-Research/projects/tools/openshell-exporter v0.0.5-rc.1", openshellprocessor.NewFactory().Type(): "github.com/NVIDIA/OpenShell-Research/projects/tools/openshell-exporter v0.0.5-rc.1", relayprocessor.NewFactory().Type(): "github.com/NVIDIA/OpenShell-Research/projects/tools/openshell-exporter v0.0.5-rc.1", diff --git a/projects/tools/openshell-exporter/cmd/openshell-event-exporter/main.go b/projects/tools/openshell-exporter/cmd/openshell-event-exporter/main.go index 0f7c54a1..cca39691 100644 --- a/projects/tools/openshell-exporter/cmd/openshell-event-exporter/main.go +++ b/projects/tools/openshell-exporter/cmd/openshell-event-exporter/main.go @@ -35,9 +35,9 @@ func main() { }, }, ProviderModules: map[string]string{ - envprovider.NewFactory().Create(confmap.ProviderSettings{}).Scheme(): "go.opentelemetry.io/collector/confmap/provider/envprovider v1.66.0", - fileprovider.NewFactory().Create(confmap.ProviderSettings{}).Scheme(): "go.opentelemetry.io/collector/confmap/provider/fileprovider v1.66.0", - yamlprovider.NewFactory().Create(confmap.ProviderSettings{}).Scheme(): "go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.66.0", + envprovider.NewFactory().Create(confmap.ProviderSettings{}).Scheme(): "go.opentelemetry.io/collector/confmap/provider/envprovider v1.68.0", + fileprovider.NewFactory().Create(confmap.ProviderSettings{}).Scheme(): "go.opentelemetry.io/collector/confmap/provider/fileprovider v1.68.0", + yamlprovider.NewFactory().Create(confmap.ProviderSettings{}).Scheme(): "go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.68.0", }, ConverterModules: []string{}, } diff --git a/projects/tools/openshell-exporter/config.yaml b/projects/tools/openshell-exporter/config.yaml index 3580a32c..981aab72 100644 --- a/projects/tools/openshell-exporter/config.yaml +++ b/projects/tools/openshell-exporter/config.yaml @@ -12,6 +12,64 @@ extensions: endpoint: ${env:EXPORTER_HEALTH_ENDPOINT:-127.0.0.1:13133} receivers: + file_log/gateway_ocsf: + include: [./input/gateways/*/gateway-ocsf.jsonl*] + start_at: beginning + storage: file_storage/checkpoints + retry_on_failure: + enabled: true + initial_interval: 1s + max_interval: 30s + max_elapsed_time: 0s + include_file_path: true + include_file_path_resolved: true + include_file_record_offset: true + include_file_record_number: true + on_truncate: read_whole_file + max_log_size: 8MiB + max_log_size_behavior: split + attributes: + openshell.acquisition.kind: ocsf.gateway + openshell.acquisition.source_instance: gateway-ocsf-jsonl + operators: + - type: json_parser + parse_from: body + parse_to: body + on_error: send + file_log/supervisor_ocsf: + include: [./input/supervisors/*/stderr.log*] + start_at: beginning + storage: file_storage/checkpoints + retry_on_failure: + enabled: true + initial_interval: 1s + max_interval: 30s + max_elapsed_time: 0s + include_file_path: true + include_file_path_resolved: true + include_file_record_offset: true + include_file_record_number: true + on_truncate: read_whole_file + max_log_size: 8MiB + max_log_size_behavior: split + attributes: + openshell.acquisition.kind: ocsf.supervisor + openshell.acquisition.source_instance: supervisor-stderr + operators: + # Input is the unwrapped platform log stream (docker/podman/kubectl logs). + # Select only the structured copy; retain malformed marked payloads. + - type: filter + expr: 'body not matches "^\\S+ OCSF-JSON(?: |$)"' + - type: regex_parser + regex: '^\S+ OCSF-JSON ?(?P.*)$' + on_error: send + - type: move + from: attributes.record + to: body + - type: json_parser + parse_from: body + parse_to: body + on_error: send file_log/ocsf: include: [./input/*.jsonl, ./input/sandboxes/*/openshell-ocsf.*.log] start_at: beginning @@ -41,7 +99,7 @@ processors: limit_mib: 256 spike_limit_mib: 64 openshell: - source_profiles: [ocsf.file] + source_profiles: [ocsf.gateway, ocsf.supervisor, ocsf.file] gateway_id: local-gateway workspace: default source_instance: gateway-ocsf-jsonl @@ -63,6 +121,6 @@ service: extensions: [file_storage/checkpoints, storagehealth, health_check] pipelines: logs: - receivers: [file_log/ocsf] + receivers: [file_log/gateway_ocsf, file_log/supervisor_ocsf, file_log/ocsf] processors: [memory_limiter, openshell] exporters: [file/recovery] diff --git a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/acknowledgement_test.go b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/acknowledgement_test.go index 1488aca6..aeca9ec5 100644 --- a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/acknowledgement_test.go +++ b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/acknowledgement_test.go @@ -36,7 +36,7 @@ func TestAcknowledgementFailuresAreRetryableAndNotCountedDelivered(t *testing.T) }, nil })} implementation := testExporter(client) - implementation.metrics = newExporterMetrics(provider) + implementation.metrics = newExporterMetrics(provider, "cloudevents") err := implementation.pushLogs(context.Background(), oneLog(t, "evidence")) if err == nil || consumererror.IsPermanent(err) { t.Fatalf("acknowledgement error=%v, want retryable", err) @@ -99,3 +99,49 @@ func (body *faultyAcknowledgement) Read([]byte) (int, error) { func (body *faultyAcknowledgement) Close() error { return body.closeErr } + +func TestDeliveryMetricsKeepDestinationsSeparate(t *testing.T) { + reader := sdkmetric.NewManualReader() + provider := sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)) + t.Cleanup(func() { _ = provider.Shutdown(context.Background()) }) + newExporterMetrics(provider, "cloudevents/accepting").recordResponse(t.Context(), 202, 3, 0) + newExporterMetrics(provider, "cloudevents/rejecting").recordResponse(t.Context(), 400, 2, 0) + var result metricdata.ResourceMetrics + if err := reader.Collect(t.Context(), &result); err != nil { + t.Fatal(err) + } + seen := map[string]bool{} + for _, scope := range result.ScopeMetrics { + for _, m := range scope.Metrics { + switch m.Name { + case "openshell.exporter.delivery.events", "openshell.exporter.delivery.permanent_rejections": + points := m.Data.(metricdata.Sum[int64]).DataPoints + if len(points) != 1 { + t.Fatalf("unexpected points for %s: %#v", m.Name, points) + } + id, _ := points[0].Attributes.Value("exporter") + wantID, wantValue := "cloudevents/accepting", int64(3) + if m.Name == "openshell.exporter.delivery.permanent_rejections" { + wantID, wantValue = "cloudevents/rejecting", 1 + } + if id.AsString() != wantID || points[0].Value != wantValue { + t.Fatalf("destination metrics merged: %#v", points) + } + seen[m.Name] = true + case "openshell.exporter.destination.last_success_unixtime": + points := m.Data.(metricdata.Gauge[int64]).DataPoints + if len(points) != 1 { + t.Fatal("rejected destination reported success") + } + id, _ := points[0].Attributes.Value("exporter") + if id.AsString() != "cloudevents/accepting" || points[0].Value <= 0 { + t.Fatal("incorrect acknowledgement time or destination") + } + seen[m.Name] = true + } + } + } + if len(seen) != 3 { + t.Fatalf("missing delivery metrics: %v", seen) + } +} diff --git a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/config_test.go b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/config_test.go index 308e0245..b516b8ac 100644 --- a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/config_test.go +++ b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/config_test.go @@ -34,8 +34,8 @@ func TestConfigUnmarshalPreservesExporterAndHTTPSettings(t *testing.T) { if !cfg.AllowInsecureHTTP || cfg.MaxEvents != 7 || cfg.DefaultSource != "openshell://configured-source" || cfg.QueueConfig.HasValue() { t.Fatalf("exporter settings were lost: %#v", cfg) } - // confighttp normalizes the new section into the effective legacy fields. - if cfg.IdleConnTimeout != 12*time.Second { //nolint:staticcheck // Verify the upstream decoder's documented normalization. + // Collector 0.162 keeps decoded settings in the keepalive section. + if !cfg.Keepalive.HasValue() || cfg.Keepalive.Get().IdleConnTimeout != 12*time.Second { t.Fatal("HTTP keepalive settings were lost") } if err := cfg.Validate(); err != nil { diff --git a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/exporter_test.go b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/exporter_test.go index a23f5e00..e4557134 100644 --- a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/exporter_test.go +++ b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/exporter_test.go @@ -327,7 +327,7 @@ func testExporter(client *http.Client) *cloudEventsExporter { config: config, settings: settings, client: client, - metrics: newExporterMetrics(nil), + metrics: newExporterMetrics(nil, "cloudevents"), } } diff --git a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/factory.go b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/factory.go index f4199f88..b61e2e1c 100644 --- a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/factory.go +++ b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/factory.go @@ -55,7 +55,7 @@ func createLogsExporter( implementation := &cloudEventsExporter{ config: exporterConfig, settings: settings, - metrics: newExporterMetrics(settings.MeterProvider), + metrics: newExporterMetrics(settings.MeterProvider, settings.ID.String()), } return exporterhelper.NewLogs( ctx, diff --git a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/lifecycle_security_test.go b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/lifecycle_security_test.go index b30b201d..ee02e3b5 100644 --- a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/lifecycle_security_test.go +++ b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/lifecycle_security_test.go @@ -131,7 +131,7 @@ func lifecycleExporter(cfg *Config) *cloudEventsExporter { settings: exporter.Settings{TelemetrySettings: component.TelemetrySettings{ Logger: zap.NewNop(), }}, - metrics: newExporterMetrics(nil), + metrics: newExporterMetrics(nil, "cloudevents"), } } diff --git a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/metrics.go b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/metrics.go index 4c54e235..7f61ac7a 100644 --- a/projects/tools/openshell-exporter/exporter/cloudeventsexporter/metrics.go +++ b/projects/tools/openshell-exporter/exporter/cloudeventsexporter/metrics.go @@ -16,6 +16,7 @@ import ( const exporterMeterName = "github.com/NVIDIA-dev/OpenShell-exporter/cloudevents" type exporterMetrics struct { + exporter attribute.KeyValue oversized metric.Int64Counter permanentResponses metric.Int64Counter retryableResponses metric.Int64Counter @@ -25,7 +26,7 @@ type exporterMetrics struct { lastSuccess metric.Int64Gauge } -func newExporterMetrics(provider metric.MeterProvider) *exporterMetrics { +func newExporterMetrics(provider metric.MeterProvider, id string) *exporterMetrics { if provider == nil { provider = noop.NewMeterProvider() } @@ -38,6 +39,7 @@ func newExporterMetrics(provider metric.MeterProvider) *exporterMetrics { latency, _ := meter.Float64Histogram("openshell.exporter.destination.latency", metric.WithUnit("ms")) lastSuccess, _ := meter.Int64Gauge("openshell.exporter.destination.last_success_unixtime", metric.WithUnit("s")) return &exporterMetrics{ + exporter: attribute.String("exporter", id), oversized: oversized, permanentResponses: permanent, retryableResponses: retryable, @@ -51,7 +53,7 @@ func newExporterMetrics(provider metric.MeterProvider) *exporterMetrics { func (m *exporterMetrics) recordOversized(ctx context.Context, count int) { if m.oversized != nil { m.oversized.Add(ctx, int64(count), metric.WithAttributes( - attribute.String("destination", "cloudevents"), + attribute.String("destination", "cloudevents"), m.exporter, )) } } @@ -62,12 +64,12 @@ func (m *exporterMetrics) recordResponse( eventCount int, elapsed time.Duration, ) { - attrs := metric.WithAttributes(attribute.String("status_code", strconv.Itoa(status))) + attrs := metric.WithAttributes(m.exporter, attribute.String("status_code", strconv.Itoa(status))) if status >= 200 && status < 300 { if m.deliveredBatches != nil { m.deliveredBatches.Add(ctx, 1, attrs) m.deliveredEvents.Add(ctx, int64(eventCount), attrs) - m.lastSuccess.Record(ctx, time.Now().Unix()) + m.lastSuccess.Record(ctx, time.Now().Unix(), metric.WithAttributes(m.exporter)) } } else if retryableStatus(status) { if m.retryableResponses != nil { @@ -77,17 +79,17 @@ func (m *exporterMetrics) recordResponse( m.permanentResponses.Add(ctx, 1, attrs) } if m.destinationLatency != nil { - m.destinationLatency.Record(ctx, float64(elapsed.Microseconds())/1000) + m.destinationLatency.Record(ctx, float64(elapsed.Microseconds())/1000, metric.WithAttributes(m.exporter)) } } func (m *exporterMetrics) recordNetworkFailure(ctx context.Context, elapsed time.Duration) { if m.retryableResponses != nil { m.retryableResponses.Add(ctx, 1, metric.WithAttributes( - attribute.String("status_code", "network"), + attribute.String("status_code", "network"), m.exporter, )) } if m.destinationLatency != nil { - m.destinationLatency.Record(ctx, float64(elapsed.Microseconds())/1000) + m.destinationLatency.Record(ctx, float64(elapsed.Microseconds())/1000, metric.WithAttributes(m.exporter)) } } diff --git a/projects/tools/openshell-exporter/go.mod b/projects/tools/openshell-exporter/go.mod index d00b8cce..017b5ff4 100644 --- a/projects/tools/openshell-exporter/go.mod +++ b/projects/tools/openshell-exporter/go.mod @@ -2,54 +2,55 @@ module github.com/NVIDIA/OpenShell-Research/projects/tools/openshell-exporter go 1.26.0 -toolchain go1.26.8 +toolchain go1.27.2 require ( - github.com/NVIDIA/OpenShell/sdk/go v0.0.0-20260825132042-455883905a7a - github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v0.160.0 - github.com/open-telemetry/opentelemetry-collector-contrib/exporter/loadbalancingexporter v0.160.0 - github.com/open-telemetry/opentelemetry-collector-contrib/extension/bearertokenauthextension v0.160.0 - github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.160.0 - github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage v0.160.0 - github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.160.0 - github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.160.0 - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.160.0 - github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sobjectsreceiver v0.160.0 - go.opentelemetry.io/collector/component v1.66.0 - go.opentelemetry.io/collector/config/configauth v1.66.0 - go.opentelemetry.io/collector/config/confighttp v0.160.0 - go.opentelemetry.io/collector/config/configmiddleware v1.66.0 - go.opentelemetry.io/collector/config/configopaque v1.66.0 - go.opentelemetry.io/collector/config/configoptional v1.66.0 - go.opentelemetry.io/collector/config/configretry v1.66.0 - go.opentelemetry.io/collector/confmap v1.66.0 - go.opentelemetry.io/collector/confmap/provider/envprovider v1.66.0 - go.opentelemetry.io/collector/confmap/provider/fileprovider v1.66.0 - go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.66.0 - go.opentelemetry.io/collector/connector v0.160.0 - go.opentelemetry.io/collector/consumer v1.66.0 - go.opentelemetry.io/collector/consumer/consumererror v0.160.0 - go.opentelemetry.io/collector/exporter v1.66.0 - go.opentelemetry.io/collector/exporter/exporterhelper v0.160.0 - go.opentelemetry.io/collector/exporter/otlpexporter v0.160.0 - go.opentelemetry.io/collector/exporter/otlphttpexporter v0.160.0 - go.opentelemetry.io/collector/extension v1.66.0 - go.opentelemetry.io/collector/extension/xextension v0.160.0 - go.opentelemetry.io/collector/otelcol v0.160.0 - go.opentelemetry.io/collector/pdata v1.66.0 - go.opentelemetry.io/collector/processor v1.66.0 - go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.160.0 - go.opentelemetry.io/collector/processor/processorhelper v0.160.0 - go.opentelemetry.io/collector/processor/processortest v0.160.0 - go.opentelemetry.io/collector/receiver v1.66.0 - go.opentelemetry.io/collector/receiver/otlpreceiver v0.160.0 - go.opentelemetry.io/collector/service v0.160.0 - go.opentelemetry.io/otel v1.46.0 - go.opentelemetry.io/otel/metric v1.46.0 - go.opentelemetry.io/otel/sdk/metric v1.46.0 + github.com/NVIDIA/OpenShell/sdk/go v0.0.0-20261009050449-e1f3c82caa3e + github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v0.162.0 + github.com/open-telemetry/opentelemetry-collector-contrib/exporter/loadbalancingexporter v0.162.0 + github.com/open-telemetry/opentelemetry-collector-contrib/extension/bearertokenauthextension v0.162.0 + github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.162.0 + github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage v0.162.0 + github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.162.0 + github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.162.0 + github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.162.0 + github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sobjectsreceiver v0.162.0 + go.opentelemetry.io/collector/component v1.68.0 + go.opentelemetry.io/collector/config/configauth v1.68.0 + go.opentelemetry.io/collector/config/confighttp v0.162.0 + go.opentelemetry.io/collector/config/configmiddleware v1.68.0 + go.opentelemetry.io/collector/config/configopaque v1.68.0 + go.opentelemetry.io/collector/config/configoptional v1.68.0 + go.opentelemetry.io/collector/config/configretry v1.68.0 + go.opentelemetry.io/collector/confmap v1.68.0 + go.opentelemetry.io/collector/confmap/provider/envprovider v1.68.0 + go.opentelemetry.io/collector/confmap/provider/fileprovider v1.68.0 + go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.68.0 + go.opentelemetry.io/collector/connector v0.162.0 + go.opentelemetry.io/collector/consumer v1.68.0 + go.opentelemetry.io/collector/consumer/consumererror v0.162.0 + go.opentelemetry.io/collector/exporter v1.68.0 + go.opentelemetry.io/collector/exporter/exporterhelper v0.162.0 + go.opentelemetry.io/collector/exporter/otlpexporter v0.162.0 + go.opentelemetry.io/collector/exporter/otlphttpexporter v0.162.0 + go.opentelemetry.io/collector/extension v1.68.0 + go.opentelemetry.io/collector/extension/xextension v0.162.0 + go.opentelemetry.io/collector/otelcol v0.162.0 + go.opentelemetry.io/collector/pdata v1.68.0 + go.opentelemetry.io/collector/processor v1.68.0 + go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.162.0 + go.opentelemetry.io/collector/processor/processorhelper v0.162.0 + go.opentelemetry.io/collector/processor/processortest v0.162.0 + go.opentelemetry.io/collector/receiver v1.68.0 + go.opentelemetry.io/collector/receiver/otlpreceiver v0.162.0 + go.opentelemetry.io/collector/service v0.162.0 + go.opentelemetry.io/otel v1.47.0 + go.opentelemetry.io/otel/metric v1.47.0 + go.opentelemetry.io/otel/sdk/metric v1.47.0 go.uber.org/zap v1.28.0 + golang.org/x/mod v0.41.0 golang.org/x/sys v0.49.0 - google.golang.org/grpc v1.83.2 + google.golang.org/grpc v1.84.0 google.golang.org/protobuf v1.36.12 ) @@ -61,27 +62,27 @@ require ( github.com/alecthomas/participle/v2 v2.1.4 // indirect github.com/antchfx/xmlquery v1.5.1 // indirect github.com/antchfx/xpath v1.3.8 // indirect - github.com/aws/aws-sdk-go-v2 v1.45.1 // indirect - github.com/aws/aws-sdk-go-v2/config v1.33.1 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.20.1 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.19.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.8.1 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.5.1 // indirect + github.com/aws/aws-sdk-go-v2 v1.47.0 // indirect + github.com/aws/aws-sdk-go-v2/config v1.33.5 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.20.5 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.20.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.8.3 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.5.3 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.1 // indirect - github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.46.1 // indirect - github.com/aws/aws-sdk-go-v2/service/signin v1.7.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.35.1 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.40.1 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.47.1 // indirect - github.com/aws/smithy-go v1.28.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.3 // indirect + github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.49.0 // indirect + github.com/aws/aws-sdk-go-v2/service/signin v1.10.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.38.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.43.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.51.0 // indirect + github.com/aws/smithy-go v1.28.2 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect + github.com/bmatcuk/doublestar/v4 v4.10.1 // indirect github.com/brunoscheufler/aws-ecs-metadata-go v0.0.0-20221221133751-67e37ae746cd // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect - github.com/cenkalti/backoff/v7 v7.0.0 // indirect + github.com/cenkalti/backoff/v7 v7.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/ebitengine/purego v0.10.2 // indirect @@ -90,7 +91,7 @@ require ( github.com/emicklei/go-restful/v3 v3.13.0 // indirect github.com/expr-lang/expr v1.17.8 // indirect github.com/felixge/httpsnoop v1.1.0 // indirect - github.com/foxboron/go-tpm-keyfiles v0.0.0-20251226215517-609e4778396f // indirect + github.com/foxboron/go-tpm-keyfiles v0.0.0-20260902202739-8c9c2d1005f4 // indirect github.com/fsnotify/fsnotify v1.10.1 // indirect github.com/fxamacker/cbor/v2 v2.9.2 // indirect github.com/go-logr/logr v1.4.4 // indirect @@ -117,7 +118,7 @@ require ( github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/snappy v1.0.0 // indirect github.com/google/gnostic-models v0.7.1 // indirect - github.com/google/go-tpm v0.9.8 // indirect + github.com/google/go-tpm v0.9.9-0.20260124013517-8f8f42cba0de // indirect github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect github.com/hashicorp/go-version v1.9.0 // indirect @@ -127,11 +128,11 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jonboulle/clockwork v0.5.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.19.2 // indirect + github.com/klauspost/compress v1.20.1 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/knadh/koanf/maps v0.1.3 // indirect github.com/knadh/koanf/providers/confmap v1.0.1 // indirect - github.com/knadh/koanf/v2 v2.3.6 // indirect + github.com/knadh/koanf/v2 v2.3.8 // indirect github.com/leodido/go-syslog/v4 v4.6.0 // indirect github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b // indirect github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect @@ -141,29 +142,31 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/extension/internal/credentialsfile v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/extension/k8sleaderelector v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/internal/filter v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/internal/healthcheck v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sinventory v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.160.0 // indirect - github.com/open-telemetry/opentelemetry-collector-contrib/pkg/status v0.160.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/extension/internal/credentialsfile v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/extension/k8sleaderelector v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/filter v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/healthcheck v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sinventory v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/xprofile v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/xottl v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/sampling v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.162.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/status v0.162.0 // indirect github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7 // indirect github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235 // indirect - github.com/pierrec/lz4/v4 v4.1.29 // indirect + github.com/pierrec/lz4/v4 v4.1.33 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/prometheus/client_golang v1.24.1 // indirect github.com/prometheus/client_model v0.6.3 // indirect - github.com/prometheus/common v0.70.1 // indirect + github.com/prometheus/common v0.71.0 // indirect github.com/prometheus/otlptranslator v1.0.0 // indirect github.com/prometheus/procfs v0.21.1 // indirect github.com/rs/cors v1.11.1 // indirect @@ -173,7 +176,7 @@ require ( github.com/stretchr/testify v1.12.1 // indirect github.com/tklauser/go-sysconf v0.4.0 // indirect github.com/tklauser/numcpus v0.12.0 // indirect - github.com/twmb/murmur3 v1.1.8 // indirect + github.com/twmb/murmur3 v1.2.0 // indirect github.com/ua-parser/uap-go v0.0.0-20251207011819-db9adb27a0b8 // indirect github.com/valyala/fastjson v1.6.10 // indirect github.com/x448/float16 v0.8.4 // indirect @@ -181,53 +184,53 @@ require ( github.com/zeebo/xxh3 v1.1.0 // indirect go.etcd.io/bbolt v1.5.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/collector v0.160.0 // indirect - go.opentelemetry.io/collector/client v1.66.0 // indirect - go.opentelemetry.io/collector/component/componentstatus v0.160.0 // indirect - go.opentelemetry.io/collector/component/componenttest v0.160.0 // indirect - go.opentelemetry.io/collector/config/configcompression v1.66.0 // indirect - go.opentelemetry.io/collector/config/configgrpc v1.66.0 // indirect - go.opentelemetry.io/collector/config/confignet v1.66.0 // indirect - go.opentelemetry.io/collector/config/configtelemetry v0.160.0 // indirect - go.opentelemetry.io/collector/config/configtls v1.66.0 // indirect - go.opentelemetry.io/collector/confmap/xconfmap v0.160.0 // indirect - go.opentelemetry.io/collector/connector/connectortest v0.160.0 // indirect - go.opentelemetry.io/collector/connector/xconnector v0.160.0 // indirect - go.opentelemetry.io/collector/consumer/consumererror/xconsumererror v0.160.0 // indirect - go.opentelemetry.io/collector/consumer/consumertest v0.160.0 // indirect - go.opentelemetry.io/collector/consumer/xconsumer v0.160.0 // indirect - go.opentelemetry.io/collector/exporter/exporterhelper/xexporterhelper v0.160.0 // indirect - go.opentelemetry.io/collector/exporter/exportertest v0.160.0 // indirect - go.opentelemetry.io/collector/exporter/xexporter v0.160.0 // indirect - go.opentelemetry.io/collector/extension/extensionauth v1.66.0 // indirect - go.opentelemetry.io/collector/extension/extensioncapabilities v0.160.0 // indirect - go.opentelemetry.io/collector/extension/extensionmiddleware v0.160.0 // indirect - go.opentelemetry.io/collector/extension/extensiontest v0.160.0 // indirect - go.opentelemetry.io/collector/featuregate v1.66.0 // indirect - go.opentelemetry.io/collector/filter v0.160.0 // indirect - go.opentelemetry.io/collector/internal/componentalias v0.160.0 // indirect - go.opentelemetry.io/collector/internal/fanoutconsumer v0.160.0 // indirect - go.opentelemetry.io/collector/internal/memorylimiter v0.160.0 // indirect - go.opentelemetry.io/collector/internal/sharedcomponent v0.160.0 // indirect - go.opentelemetry.io/collector/internal/telemetry v0.160.0 // indirect - go.opentelemetry.io/collector/pdata/pprofile v0.160.0 // indirect - go.opentelemetry.io/collector/pdata/testdata v0.160.0 // indirect - go.opentelemetry.io/collector/pdata/xpdata v0.160.0 // indirect - go.opentelemetry.io/collector/pipeline v1.66.0 // indirect - go.opentelemetry.io/collector/pipeline/xpipeline v0.160.0 // indirect - go.opentelemetry.io/collector/processor/processorhelper/xprocessorhelper v0.160.0 // indirect - go.opentelemetry.io/collector/processor/xprocessor v0.160.0 // indirect - go.opentelemetry.io/collector/receiver/receiverhelper v0.160.0 // indirect - go.opentelemetry.io/collector/receiver/receivertest v0.160.0 // indirect - go.opentelemetry.io/collector/receiver/xreceiver v0.160.0 // indirect - go.opentelemetry.io/collector/service/hostcapabilities v0.160.0 // indirect + go.opentelemetry.io/collector v0.162.0 // indirect + go.opentelemetry.io/collector/client v1.68.0 // indirect + go.opentelemetry.io/collector/component/componentstatus v0.162.0 // indirect + go.opentelemetry.io/collector/component/componenttest v0.162.0 // indirect + go.opentelemetry.io/collector/config/configcompression v1.68.0 // indirect + go.opentelemetry.io/collector/config/configgrpc v1.68.0 // indirect + go.opentelemetry.io/collector/config/confignet v1.68.0 // indirect + go.opentelemetry.io/collector/config/configtelemetry v0.162.0 // indirect + go.opentelemetry.io/collector/config/configtls v1.68.0 // indirect + go.opentelemetry.io/collector/confmap/xconfmap v0.162.0 // indirect + go.opentelemetry.io/collector/connector/connectortest v0.162.0 // indirect + go.opentelemetry.io/collector/connector/xconnector v0.162.0 // indirect + go.opentelemetry.io/collector/consumer/consumererror/xconsumererror v0.162.0 // indirect + go.opentelemetry.io/collector/consumer/consumertest v0.162.0 // indirect + go.opentelemetry.io/collector/consumer/xconsumer v0.162.0 // indirect + go.opentelemetry.io/collector/exporter/exporterhelper/xexporterhelper v0.162.0 // indirect + go.opentelemetry.io/collector/exporter/exportertest v0.162.0 // indirect + go.opentelemetry.io/collector/exporter/xexporter v0.162.0 // indirect + go.opentelemetry.io/collector/extension/extensionauth v1.68.0 // indirect + go.opentelemetry.io/collector/extension/extensioncapabilities v0.162.0 // indirect + go.opentelemetry.io/collector/extension/extensionmiddleware v0.162.0 // indirect + go.opentelemetry.io/collector/extension/extensiontest v0.162.0 // indirect + go.opentelemetry.io/collector/featuregate v1.68.0 // indirect + go.opentelemetry.io/collector/filter v0.162.0 // indirect + go.opentelemetry.io/collector/internal/componentalias v0.162.0 // indirect + go.opentelemetry.io/collector/internal/fanoutconsumer v0.162.0 // indirect + go.opentelemetry.io/collector/internal/memorylimiter v0.162.0 // indirect + go.opentelemetry.io/collector/internal/sharedcomponent v0.162.0 // indirect + go.opentelemetry.io/collector/internal/telemetry v0.162.0 // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.162.0 // indirect + go.opentelemetry.io/collector/pdata/testdata v0.162.0 // indirect + go.opentelemetry.io/collector/pdata/xpdata v0.162.0 // indirect + go.opentelemetry.io/collector/pipeline v1.68.0 // indirect + go.opentelemetry.io/collector/pipeline/xpipeline v0.162.0 // indirect + go.opentelemetry.io/collector/processor/processorhelper/xprocessorhelper v0.162.0 // indirect + go.opentelemetry.io/collector/processor/xprocessor v0.162.0 // indirect + go.opentelemetry.io/collector/receiver/receiverhelper v0.162.0 // indirect + go.opentelemetry.io/collector/receiver/receivertest v0.162.0 // indirect + go.opentelemetry.io/collector/receiver/xreceiver v0.162.0 // indirect + go.opentelemetry.io/collector/service/hostcapabilities v0.162.0 // indirect go.opentelemetry.io/contrib/bridges/otelzap v0.20.0 // indirect go.opentelemetry.io/contrib/detectors/aws/ecs v1.45.0 // indirect go.opentelemetry.io/contrib/detectors/aws/eks v1.45.0 // indirect go.opentelemetry.io/contrib/detectors/azure/azurevm v0.17.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.45.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.70.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 // indirect go.opentelemetry.io/contrib/otelconf v0.25.0 // indirect go.opentelemetry.io/contrib/propagators/autoprop v0.70.0 // indirect go.opentelemetry.io/contrib/propagators/aws v1.45.0 // indirect @@ -245,10 +248,10 @@ require ( go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.21.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.45.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.45.0 // indirect - go.opentelemetry.io/otel/log v0.22.0 // indirect - go.opentelemetry.io/otel/sdk v1.46.0 // indirect + go.opentelemetry.io/otel/log v1.47.0 // indirect + go.opentelemetry.io/otel/sdk v1.47.0 // indirect go.opentelemetry.io/otel/sdk/log v0.21.0 // indirect - go.opentelemetry.io/otel/trace v1.46.0 // indirect + go.opentelemetry.io/otel/trace v1.47.0 // indirect go.opentelemetry.io/proto/otlp v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v2 v2.4.4 // indirect @@ -262,17 +265,17 @@ require ( golang.org/x/time v0.15.0 // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8 // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.36.4 // indirect - k8s.io/apimachinery v0.36.4 // indirect - k8s.io/client-go v0.36.4 // indirect + k8s.io/api v0.37.0 // indirect + k8s.io/apimachinery v0.37.0 // indirect + k8s.io/client-go v0.37.0 // indirect k8s.io/klog/v2 v2.140.0 // indirect k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad // indirect k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 // indirect - sigs.k8s.io/controller-runtime v0.24.1 // indirect + sigs.k8s.io/controller-runtime v0.25.1 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/structured-merge-diff/v6 v6.4.2 // indirect diff --git a/projects/tools/openshell-exporter/go.sum b/projects/tools/openshell-exporter/go.sum index 95945740..42fbaf09 100644 --- a/projects/tools/openshell-exporter/go.sum +++ b/projects/tools/openshell-exporter/go.sum @@ -8,8 +8,8 @@ github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1 github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/NVIDIA/OpenShell/sdk/go v0.0.0-20260825132042-455883905a7a h1:Pl/w+mbbijUg96ktvDBO4OMmXTtgsaPNxhpsGFIqoMk= -github.com/NVIDIA/OpenShell/sdk/go v0.0.0-20260825132042-455883905a7a/go.mod h1:PPbbhH5tmSfoWzVcb5CXurnMkuJOYpesZmUB1itrlFY= +github.com/NVIDIA/OpenShell/sdk/go v0.0.0-20261009050449-e1f3c82caa3e h1:M4VdrEpWfr4D4TxbCTJcScV1C4Oc2jJXLVST6wTEzBs= +github.com/NVIDIA/OpenShell/sdk/go v0.0.0-20261009050449-e1f3c82caa3e/go.mod h1:+wnjuZwBJH2yz8cU1t7FiGK7xPQyxjOY3YZNFcfpL90= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/participle/v2 v2.1.4 h1:W/H79S8Sat/krZ3el6sQMvMaahJ+XcM9WSI2naI7w2U= @@ -21,48 +21,48 @@ github.com/antchfx/xmlquery v1.5.1/go.mod h1:bVqnl7TaDXSReKINrhZz+2E/PbCu2tUahb+ github.com/antchfx/xpath v1.3.6/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= github.com/antchfx/xpath v1.3.8 h1:RQlkLaJDKk1Ew1H6CUPUTKM+IQxm+6HTyOgcrfqOU9c= github.com/antchfx/xpath v1.3.8/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs= -github.com/aws/aws-sdk-go-v2 v1.45.1 h1:iIoG3NaLhV6UZpPXyPXlDj2I9oS8tV/nMcMnITCC6Ks= -github.com/aws/aws-sdk-go-v2 v1.45.1/go.mod h1:bttEH6JqnUL8LepvDVfdrds/fZ5bCIxzpe3abyUrhDU= -github.com/aws/aws-sdk-go-v2/config v1.33.1 h1:bq9jze1hQ5YTCLoVxNnbp0T7rglrlOE7N9YsHqjGkEw= -github.com/aws/aws-sdk-go-v2/config v1.33.1/go.mod h1:2A3HQwG4zaL5Tm80rc6RZj8LmWWv4WYT5v8raSz/L7A= -github.com/aws/aws-sdk-go-v2/credentials v1.20.1 h1:Z8GRNEx0u9sDkZOq4PUnN8mjGwbUQGRzMSXpvt3d8xQ= -github.com/aws/aws-sdk-go-v2/credentials v1.20.1/go.mod h1:uBIK00kFo95dnemqfFMTWx0X8YRqsh6ecIoCjjOkZqM= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.19.1 h1:YIEBqcqRnpi4Pfv0YHImtgi6czGCwKHANC7SwmUAVD0= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.19.1/go.mod h1:imEf0oufgAo8KAkCHhrOdqGEC0YWx1PPBQH82shSxGw= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.1 h1:pc138gM1CW+XPc60rEwUlwwuwWFQK16CI1T7v1F9Oec= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.1/go.mod h1:1+koxpPIbfBdfzP6vojm5/zTpTQ/micYwlxIiNB3TxI= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.8.1 h1:K0JsbZQj+1h208Ro1zHeA4l7bMp0NvRffHQ91q8Ol1s= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.8.1/go.mod h1:W3/vL6EtCIatICGy9ab29QhMuae+cOKPWcMxv02CO+Q= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.5.1 h1:yhw5KD1phVyP9vijxOUzDfEtJx+bt+L63k+VfuiYFAA= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.5.1/go.mod h1:ZW2e0d7DYlRxlS9hEiMXE47gTdX5KRN4byUiNbUpG+Q= +github.com/aws/aws-sdk-go-v2 v1.47.0 h1:0jsHallhJCeaU0Ko48c/3FK1ctOQ7NpzggxriJOQ8MQ= +github.com/aws/aws-sdk-go-v2 v1.47.0/go.mod h1:bttEH6JqnUL8LepvDVfdrds/fZ5bCIxzpe3abyUrhDU= +github.com/aws/aws-sdk-go-v2/config v1.33.5 h1:UA1dmokBFOLFoOyVBhO6HjM6edy0MIk5AZSkJVcksQw= +github.com/aws/aws-sdk-go-v2/config v1.33.5/go.mod h1:Dop8axzz0xx38GExIYWXdeyc8QQ7Cr+nPsxpD/LYy4U= +github.com/aws/aws-sdk-go-v2/credentials v1.20.5 h1:wklUVvHMc9xTQ3rcp49/ISpiMnhbCicJcA6n6S8m7J8= +github.com/aws/aws-sdk-go-v2/credentials v1.20.5/go.mod h1:fyEdrn6ccLFOkoK84j5bQyGTxp9zPt5l2XMhxf4DVZs= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.20.0 h1:AM4hHjww+PSFtt6E+UrBrPlZkWsePCLEt9AjkfQX+yM= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.20.0/go.mod h1:3x/yXezeQjpOvBb4jEMxrS8SXvpdvJ5abv6l5c1gWM8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.3 h1:Hp/VgjP0BysR3OgLlR057Vz2LcbbVnoWeJ+3qWiS/fY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.5.3/go.mod h1:nwGV5qw7F1IZPgxCvA/ph8N2TAuz+BkRG/bXn808qMA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.8.3 h1:MUaM4f+kj1ZIBPZfUS8cxP1GKXXZtHJjAthy93AN7SM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.8.3/go.mod h1:6YmVmEVRI5ZZzRjCSsb9SryKH0hAlMRdgA7kG9aDvBU= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.5.3 h1:fuSCw4Z2qfRCztMPO3GXJNSiEp6Wee+WOLwrHHUMy9c= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.5.3/go.mod h1:6SxcHheD1pPR5+kWm1wGvjlL/YqUsh267sAfEmN4K7A= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19 h1:bAdDl/HkGCcGPoe25ToSHEw23VIxt6CT5fLcg111BKg= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.19/go.mod h1:KaUzbLxv4CeSxh6ZCl9B4m7CuFenS8kUEaDs+f/DQr4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.1 h1:RmmWQPREQdk9U+PfqeHW3MqZaBaNK7TpV9W3RY+b+7g= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.1/go.mod h1:0A3W4F+68ZnNk5XcNL/e9HFMwnP8RlEicFfy6eOEDyw= -github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.46.1 h1:P12LPOpkuH3AGuW3wCAxAb+/wwzHoTQK3e7Jon4oFas= -github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.46.1/go.mod h1:MRyJtazDpGm2aFdt0RkbnF3e90xTZGWdPGBZpjIOJ04= -github.com/aws/aws-sdk-go-v2/service/signin v1.7.1 h1:mdMtSVKdQ3+mzBh+l0ogrFYZVQUCg6pJZOirA2ARsYE= -github.com/aws/aws-sdk-go-v2/service/signin v1.7.1/go.mod h1:9IqUlsJDbUPcg6cgx3WEzXdjrbWzLDQrak0aaSqlTcI= -github.com/aws/aws-sdk-go-v2/service/sso v1.35.1 h1:B6WFn91tobD6gG4724ONHaqrpKsoETGnv98LHe/yIGM= -github.com/aws/aws-sdk-go-v2/service/sso v1.35.1/go.mod h1:tWuiVBUtPBr8/rgRiYS8Uf85sHcAN+G7XS3D3CEoUh8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.40.1 h1:6yeYCWFvgbI2TI3K6jr9LtBNhXgJ7g4xqD+DEiaDDmM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.40.1/go.mod h1:naFe83jSMuYkH+QjQPX8n1MLhBkeCFM5Lsnh5m5wz3c= -github.com/aws/aws-sdk-go-v2/service/sts v1.47.1 h1:Sv2xPnRHlThSUtVujYuUBPI/Il8si6UPHXL8DMiB/F0= -github.com/aws/aws-sdk-go-v2/service/sts v1.47.1/go.mod h1:mKo/CzaCz8qytGW70NG4vIIGAx1HXTlb5lHNkC5k3lk= -github.com/aws/smithy-go v1.28.1 h1:R/nXH00c8qcfCzQVELtRw+eLQWtzv+VAIEFJ1/xxXlQ= -github.com/aws/smithy-go v1.28.1/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.3 h1:bON1rJf67TSTDCKg816AAIE4xSTtoo9tl0XRkO72R+I= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.14.3/go.mod h1:c5BBpjJcQXpfeq9iASyVKA3T6vX6B6LEXY4mL/gklDY= +github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.49.0 h1:rEATW7Z0QxwdgvOJb8dibOe6VFy7n+zz1Zp6PkqfDcU= +github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.49.0/go.mod h1:NOVbSvMPCZxXZW5hsjjMmUT2Iyxr3x9ptZm5RXcVvb8= +github.com/aws/aws-sdk-go-v2/service/signin v1.10.0 h1:ZD5qFpWcaOKdTuhBi431pIDkCgrMkMlMT6jlpSPoIRI= +github.com/aws/aws-sdk-go-v2/service/signin v1.10.0/go.mod h1:8Nuuf+tR346PjJ3MvZPh9pekbLiLQFWJhzMXfwy7alA= +github.com/aws/aws-sdk-go-v2/service/sso v1.38.0 h1:JGeeBcMlhg1xtOXYpeCaTQBZObtXMPQCUqBcmr65NRA= +github.com/aws/aws-sdk-go-v2/service/sso v1.38.0/go.mod h1:XwteswG9EOMRFm73UT0t+MbTwyLxMrEXkU6e+v92Lzo= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.43.0 h1:obhahQXDEdVEv8y5bTKXR30LVaxYe1kyYM0L7l2Iq+k= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.43.0/go.mod h1:6twZZ/aXHNy1vXUO8koUbp++MYzMASkOgEBdkbJYmO0= +github.com/aws/aws-sdk-go-v2/service/sts v1.51.0 h1:Zpnqa6XtrNzXZnwbdCqHOXpXhMsa01ql/pcRQ1sb4hk= +github.com/aws/aws-sdk-go-v2/service/sts v1.51.0/go.mod h1:/8JRcdTt//hG0Q4BTmGbuOplT7ABe+5rdtqUHqXvYIM= +github.com/aws/smithy-go v1.28.2 h1:myhcykQcatTul2B/zITjDk203G7t0awUAs1hVry5Bvg= +github.com/aws/smithy-go v1.28.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs= -github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.10.1 h1:WmIq9zirOet2IiLta/lAAdb7amMCKO+BP4FZXcgU3qY= +github.com/bmatcuk/doublestar/v4 v4.10.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/brunoscheufler/aws-ecs-metadata-go v0.0.0-20221221133751-67e37ae746cd h1:C0dfBzAdNMqxokqWUysk2KTJSMmqvh9cNW1opdy5+0Q= github.com/brunoscheufler/aws-ecs-metadata-go v0.0.0-20221221133751-67e37ae746cd/go.mod h1:CeKhh8xSs3WZAc50xABMxu+FlfAAd5PNumo7NfOv7EE= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= -github.com/cenkalti/backoff/v7 v7.0.0 h1:ZP+QAaaOnVUHo+ufFpZ835hbT3x2fy+h2lecVEosZ6A= -github.com/cenkalti/backoff/v7 v7.0.0/go.mod h1:qcKBGwsu4hpxHtQ8tWYsQ+ifzx2+sS+Xx/3jfe30lI8= +github.com/cenkalti/backoff/v7 v7.0.1 h1:+ulHti5s1d9QnfyOnLWVmQ/SaZ+TJQF9OdOI0i9BGZI= +github.com/cenkalti/backoff/v7 v7.0.1/go.mod h1:qcKBGwsu4hpxHtQ8tWYsQ+ifzx2+sS+Xx/3jfe30lI8= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= @@ -76,8 +76,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/go-connections v0.7.0 h1:6SsRfJddP22WMrCkj19x9WKjEDTB+ahsdiGYf0mN39c= -github.com/docker/go-connections v0.7.0/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= +github.com/docker/go-connections v0.8.1 h1:JibmG5hULs5qXSr/cp/w3Pw5fZuStt4MOHMUExb29/M= +github.com/docker/go-connections v0.8.1/go.mod h1:no1qkHdjq7kLMGUXYAduOhYPSJxxvgWBh7ogVvptn3Q= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/ebitengine/purego v0.10.2 h1:W809HbnvzAxgdm+aOvlSekrM16wGCdT/e76+9tS7gzE= @@ -96,8 +96,8 @@ github.com/felixge/httpsnoop v1.1.0 h1:3YtUj32ZZkqZtt3sZZsClsymw/QDuVfpNhoA31zeO github.com/felixge/httpsnoop v1.1.0/go.mod h1:Zqxgdd+1Rkcz8euOqdr7lqgCRJztwr5hp9vDSi5UZCE= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/foxboron/go-tpm-keyfiles v0.0.0-20251226215517-609e4778396f h1:RJ+BDPLSHQO7cSjKBqjPJSbi1qfk9WcsjQDtZiw3dZw= -github.com/foxboron/go-tpm-keyfiles v0.0.0-20251226215517-609e4778396f/go.mod h1:VHbbch/X4roIY22jL1s3qRbZhCiRIgUAF/PdSUcx2io= +github.com/foxboron/go-tpm-keyfiles v0.0.0-20260902202739-8c9c2d1005f4 h1:zqtQvVnFZ71RsyDMNVAaWf4g2OVEDH5LDs26MZFHy7s= +github.com/foxboron/go-tpm-keyfiles v0.0.0-20260902202739-8c9c2d1005f4/go.mod h1:wxFx38LbEL4RF0JH6PR3lf7ZJ6ZO0yQWQstLCTQQNjA= github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho= github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo= github.com/fxamacker/cbor/v2 v2.9.2 h1:X4Ksno9+x3cz0TZv69ec1hxP/+tymuR8PXQJyDwfh78= @@ -169,8 +169,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= -github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= +github.com/google/go-tpm v0.9.9-0.20260124013517-8f8f42cba0de h1:U6GxkpXnFhR76KyzdJCa3/YopeqiMgKWEGPp5u2mCSQ= +github.com/google/go-tpm v0.9.9-0.20260124013517-8f8f42cba0de/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= github.com/google/go-tpm-tools v0.4.7 h1:J3ycC8umYxM9A4eF73EofRZu4BxY0jjQnUnkhIBbvws= github.com/google/go-tpm-tools v0.4.7/go.mod h1:gSyXTZHe3fgbzb6WEGd90QucmsnT1SRdlye82gH8QjQ= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -198,16 +198,16 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.19.2 h1:hMRETovs/pu/dVWN7zIT1PGG8t509MwT6bO7XSi26R8= -github.com/klauspost/compress v1.19.2/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.20.1 h1:T7kKElXUMXrUJ2E9QhQhxFtcK5rPyLdsGZvdbLMPdiQ= +github.com/klauspost/compress v1.20.1/go.mod h1:LUdAzn7YLVvxLpc7y3V1m40wESHTgc1422pwwBSKYuI= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/knadh/koanf/maps v0.1.3 h1:P1z7EvTqdFBrPYbzSvorvrpib+sjkUMxf0FVvA5NKK4= github.com/knadh/koanf/maps v0.1.3/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/providers/confmap v1.0.1 h1:L15hbvMqlvhwUuCtL9BkL+rqiMAjk6cZc8O9XoDtE3A= github.com/knadh/koanf/providers/confmap v1.0.1/go.mod h1:txHYHiI2hAtF0/0sCmcuol4IDcuQbKTybiB1nOcUo1A= -github.com/knadh/koanf/v2 v2.3.6 h1:JoQPSJmvS4aP0xNc8xMDr5tcrkSEInL23/Il7pITAKo= -github.com/knadh/koanf/v2 v2.3.6/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28= +github.com/knadh/koanf/v2 v2.3.8 h1:NftEOf0Y456FqpLJj31RYYZQnfBQ+DDhsNQPqJ6nuk4= +github.com/knadh/koanf/v2 v2.3.8/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -228,10 +228,10 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/moby/api v1.55.0 h1:2/sexvQyqIWS8pRSCFddBfpW2qE7vR7FCL+vN8pxwMc= -github.com/moby/moby/api v1.55.0/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= -github.com/moby/moby/client v0.5.1 h1:tYNaJno4c0HXz12y5BiqEDy0rVTYkWzI26lGvnTMiJw= -github.com/moby/moby/client v0.5.1/go.mod h1:odLstlZ6uSnfvAgVxMpvgmb8SUdd+siH2T0GBuxVAlM= +github.com/moby/moby/api v1.56.0 h1:GQzua3NA599ASSIICx0iFgiJeO9YkdDARvQsm23ZZuQ= +github.com/moby/moby/api v1.56.0/go.mod h1:sZ+THbVWkjOmBPPfbnzdD/G1LuIexWhqlSHHPTDQ1Uk= +github.com/moby/moby/client v0.6.0 h1:AJjEB21QPbXSXjDsZorFBoDZPhMrfbpaPLgSMAW9Bgs= +github.com/moby/moby/client v0.6.0/go.mod h1:OCo00wNRyA3m4lmJ228W3JbyCN4ZNNYjpOXiJydBdcQ= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -244,68 +244,72 @@ github.com/onsi/ginkgo/v2 v2.27.4 h1:fcEcQW/A++6aZAZQNUmNjvA9PSOzefMJBerHJ4t8v8Y github.com/onsi/ginkgo/v2 v2.27.4/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.39.0 h1:y2ROC3hKFmQZJNFeGAMeHZKkjBL65mIZcvrLQBF9k6Q= github.com/onsi/gomega v1.39.0/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4= -github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v0.160.0 h1:F92t2DB5K/McNoSa0r/kXGWGGsBkoxxYLzt4szCy+YI= -github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v0.160.0/go.mod h1:cnh4/5XUu0szCxQZ8lZWDpQUSTcb9tYc4LZtNH05D1Y= -github.com/open-telemetry/opentelemetry-collector-contrib/exporter/loadbalancingexporter v0.160.0 h1:mCqsd8jq8lsDCgFfR+9xcRN9NfMe7O18XcyvDoZkdXM= -github.com/open-telemetry/opentelemetry-collector-contrib/exporter/loadbalancingexporter v0.160.0/go.mod h1:wN+edayRWl4izkn1+N8y1Qwjam6zboGclooYYaJNrmE= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/bearertokenauthextension v0.160.0 h1:RSPfTdqBuM1ZRjMMcjPCw2oLMl5ybVeqWGf0n8mBM4Y= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/bearertokenauthextension v0.160.0/go.mod h1:7T500+GFY1TfpR5f/RiiRAuDz6dDmN6PB/buAIi5OcY= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding v0.160.0 h1:9DB2aUIid1BjtYOsXU0o9mIEl6u0UE+4MQRgmHDYv/o= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding v0.160.0/go.mod h1:oL61j8Ea1AjFoiKlZmb9f47CcyEAOWXdaFu5NThpXxs= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding/otlpencodingextension v0.160.0 h1:MlEBAzeVv9gmuPJeXHPJRmGrEt2Pe8hhsaoiWoaaQbk= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding/otlpencodingextension v0.160.0/go.mod h1:tQAj2bTjwEmMO1OmddIbeUGmy26PWH2mUJ44aacGgu4= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.160.0 h1:+Wc4w1ubs+fjarbTjuIwEm+mGwtz0h5P3Rx6QKL65cs= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.160.0/go.mod h1:A5vpQ23oRdYwmz+I4Ps9qD8o64IE5XmFtsfik4v4Puw= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/internal/credentialsfile v0.160.0 h1:+Bv4gqVDkjmJ0Na18DNVjKlgvI2s73xU/Ftt5ltYWCw= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/internal/credentialsfile v0.160.0/go.mod h1:ES7NpVsTrG0v/t8k3FOkEtoGQlcif3il2Lc9hwnP9sE= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/k8sleaderelector v0.160.0 h1:GCrsNTYJ3h/EfQDiLhP+FP8hLjWB4C2/JnUN30LlJZw= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/k8sleaderelector v0.160.0/go.mod h1:DFDFs5m4GPBl0VpI2wfWwwHOZ7THFJg6aGZOK2Xmm6Q= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.160.0 h1:mtiXI3I5DVlk/NpDTAP+s4aIWBM2fTEYnderXz1nLSY= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.160.0/go.mod h1:Asls3MkjllqrACUBRGOXaC9Rr3SJ67mkLOOSQgpekPc= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage v0.160.0 h1:1qEz630ZgNwbQXAKLZHNNysnE4d2Qj6FAAO+Q/N4yhs= -github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage v0.160.0/go.mod h1:SH+uFxl3xDCEaSNfk4o9FBRuIfGDWlmxHBpPx73z7OQ= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.160.0 h1:4OHGcs4P5wIaNZzezFBQL1c5FeISZ3WF3yx8cwTrDb0= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.160.0/go.mod h1:sFWqV6HHAg30rwSjwyp1lXqTxhMBYCSVZDeg/IYk8yY= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.160.0 h1:bgUTLilI1DRaRi8wII9aJu0yQZuS/jFu0RBf6EL+Sfw= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.160.0/go.mod h1:PcugtOWj/c+J4hhVBcXfcM4mv+R5vD/mKJW+hW1x8WM= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.160.0 h1:XwC9DyKBx2RYeCkDtu53bz0YyM16tt8nQi4bYAIeJI0= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.160.0/go.mod h1:reZbvAmPMr7JvMBy3P2IqxU0k6/sQTtlr1LiWi3XRVA= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/filter v0.160.0 h1:j0NOlR7a5P6rX9SE812RQqbOn0bFvu56Mkv90Bt4jsc= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/filter v0.160.0/go.mod h1:NRCK83U0dVzSlBxlBIWULhMg4q5yRtnrDU8p0T1+shE= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/healthcheck v0.160.0 h1:SuW/UQn3F3t69saZPcIzpgsRBsOR9JtNhx1jexm9cpY= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/healthcheck v0.160.0/go.mod h1:rH/GP010UQ1N22CRKEF3gwFpqRCcLpoo/u4Fuwe0mCs= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig v0.160.0 h1:d1+wYyM/cWn48IYlSJMsbhw2HkodYS+N4PPB0j0qems= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig v0.160.0/go.mod h1:GmHiRXgv8mYjtKc5Baq1geissS477dhRosMGxqdRBG4= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sinventory v0.160.0 h1:yX6b2VP+r6LC51PXQmGVXUJdc5dtKY+PlX3q10y/HBo= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sinventory v0.160.0/go.mod h1:QP1ZYQQbgyKIB7b1cN58nHGviq5VriAu09wDpL7WFSU= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sleaderelectortest v0.160.0 h1:1BSodp8Q8nn0KDwTsMIETxCvsXHQwVAiwelPNprdzLc= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sleaderelectortest v0.160.0/go.mod h1:Tf+1pVFmvwFHIfgvduMGE/fs76pvrceaGWatdbMfNCw= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.160.0 h1:wUOesc+yVnoX4KTunao/GipC+oHyUiaUaCdZAXL1XK8= -github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.160.0/go.mod h1:3OrP6ISnwJlPSrjpWrSNjo6iQKTPFLl17OvVdQsiflk= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal v0.160.0 h1:awxAhSiiAVADhRoekHAO1jn9CFcnRUx6kngnQOM9GmU= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal v0.160.0/go.mod h1:bOs2XEZDN+j6ptS9O3Fyu2evjdtDxE2VNtxo/V1FbZM= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden v0.160.0 h1:8LfxzGUeTMqi0q01tG31mm66l3PJEGyyAqSLClSeaho= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden v0.160.0/go.mod h1:uVSZcwF4DIM9N/wM2oSNMzVePq2c82gWMudbhb2HLzU= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl v0.160.0 h1:lvjlW4iAohPgInJ0+rYvK5IAqVgeiDiRxssEgwKC2nw= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl v0.160.0/go.mod h1:6TmSQyz5Xe7o/B+QhfS8quWHgpVe6ic2YPNI0GEeqHY= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.160.0 h1:PFqwQnOTTUFrwLYPopdLcK42OeJpJ8EdGzZoVj7JdAY= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.160.0/go.mod h1:x4+nWF854DOMUAzOUOKazQcagdBDXYDVA2tRBlIKyCw= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.160.0 h1:KuAMWLY47aSlhUR45cty6V3vmqPfGtuEWUMWoXLihL8= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.160.0/go.mod h1:m7KYHz7g2nS7G3pLpyVoLFiyKXiVQNSsizqj+Dg1pLo= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.160.0 h1:Gk0qHgeKqPNQYr9unqkkr2yrfwspW6UUnbzMKNmdZ9M= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.160.0/go.mod h1:8QzaC7ITQ6ul4a2YcHoZr0IslPczaJjoxHNIhIEIBiM= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/status v0.160.0 h1:kvrSOaF4BSdjPN7TcqyRbdwShH0Ox87DpxDTeeD5kf0= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/status v0.160.0/go.mod h1:6SbdXJxinPqEg06k8BICRxYtXzit4kKLMlfccFFqyBI= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/xk8stest v0.160.0 h1:8hCo0hU5v1POfFGAge91EJLlzCWnPiFGIkLBlAXLcns= -github.com/open-telemetry/opentelemetry-collector-contrib/pkg/xk8stest v0.160.0/go.mod h1:WCPkU7Re0ks2IcYGyTxwhhxJI1pDM2uGgmI04bxKdNU= -github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.160.0 h1:oar6wasA3bbQgT6QI55lJjK4nKdDe/o3OTFv7ZAfKBs= -github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.160.0/go.mod h1:0JXASqxcKhxU4wuqB/0bSN7YggzIlAMsRSSluERZqSA= -github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.160.0 h1:QKdlb+ZVC1LDGvipUKu909UR/IegA8n4JG0ptbgaRDQ= -github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.160.0/go.mod h1:gIlR9u/lmSvJgy4wENVC2rEyAa+36T6rAvv3pqO/zzc= -github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.160.0 h1:Ns8FjywoPhWf4igyFbDqkhfvnPrc7XmlFsLNo5Si3sE= -github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.160.0/go.mod h1:9hm0b2v7p01Qn3dB7IvQNbR+8XlZFAvZh9bu5xFjNpc= -github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sobjectsreceiver v0.160.0 h1:InxduEfEog086it1Sq+rv8hGGvn4oauAmkF9KllYnaU= -github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sobjectsreceiver v0.160.0/go.mod h1:L/6UHuQ+p2krhthvNKEV1DZeJsWZI/k/ZFWYkQYLx/w= +github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v0.162.0 h1:2yEOlkFgAZ/c/MLaTln8keRG7MaRrucKRXfpCW4Z6Cs= +github.com/open-telemetry/opentelemetry-collector-contrib/exporter/fileexporter v0.162.0/go.mod h1:uqeePmXB9iyHf9nIlcVW5iqQMji5inu69VcHdKgLG0A= +github.com/open-telemetry/opentelemetry-collector-contrib/exporter/loadbalancingexporter v0.162.0 h1:OGqovm6En9AObyuuZax7xwFBYfqqmihgQQC6IlgDs2E= +github.com/open-telemetry/opentelemetry-collector-contrib/exporter/loadbalancingexporter v0.162.0/go.mod h1:IFcEkOlzK9NsM2apKpry7rgkjYcSwZtUiM8dgLO3VIU= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/bearertokenauthextension v0.162.0 h1:FVywFxx8P4iV9zjVBAATk0bymI7wG1JAMGJsbkLdQ8M= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/bearertokenauthextension v0.162.0/go.mod h1:ch1MYCI5AsFgPEaELkgh/1EBDmzk6lNkm1rOFKqAnFg= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding v0.162.0 h1:dwV8XHiPnfsUbsOZzjMtxWCfa4g7DeNvm/UDSnCEdn4= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding v0.162.0/go.mod h1:8uRxMHu6s5as6jHFpsxs6+49hTUatKGH/dtW2b154E8= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding/otlpencodingextension v0.162.0 h1:r6udwENGKz1bfBJDQ6M+g86rHVmCoBuBcgY7zD28ErQ= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/encoding/otlpencodingextension v0.162.0/go.mod h1:YH4Un6FhpsVWAt5lmnaC/5fByOZCE5C4xXFEhjKSupw= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.162.0 h1:zCp8kw9jrxEZIjo9Em9QD5WZ0wRXLS1Up/BuwJYIh8w= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/healthcheckextension v0.162.0/go.mod h1:sU0G4UEHX71eoDBSfck43OjuNNvD5ddiw+vT78CrjXE= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/internal/credentialsfile v0.162.0 h1:JflKSw8a8NlW80tGNEZDH2rJujthvbUFn5SSgelcIiQ= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/internal/credentialsfile v0.162.0/go.mod h1:ES7NpVsTrG0v/t8k3FOkEtoGQlcif3il2Lc9hwnP9sE= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/k8sleaderelector v0.162.0 h1:7CsGdChEOe0yJ4AzHWExuVMNvEuRtJu/LU2lhZK9DeM= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/k8sleaderelector v0.162.0/go.mod h1:JWE6Gv43ielMzTIJfbkS6uHCHw4F+ZIUMoGXbFw5geU= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.162.0 h1:lkSD8URVynwbhT4xxQya94MsXLGeU1mzjh0KmXcCS80= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.162.0/go.mod h1:Akm0ntzyjx5LZ8XFum46od6w7gxme70kNWHDSVun0hA= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage v0.162.0 h1:ixzZw99gPAIrjV2nQ27iVE/lcWz45T3d/3oqSP8l0Dk= +github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage/filestorage v0.162.0/go.mod h1:4ONgk/grSk5ogszvkCfiCICBIt/A+CUQQzy7Uw+vt8c= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.162.0 h1:Zfodm2n7XmFGV7U6gIK8RFPngEo2wTWJoNRa+gEKrYw= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.162.0/go.mod h1:vTWIgJJ0a12tRSswfgQ9ycYK5Kiuuj3zeACtaaWmaTQ= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.162.0 h1:TK03OZhrtC1QZ0hkeJbUt6ZtKXZAVplGBOl5sOHzQVI= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.162.0/go.mod h1:NoEPEE+IlllTE3yfpUmzmzyUMgciY6uinYKhsIqhouI= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.162.0 h1:wvk/1mcAl8flMJfMSBsP4Qo2AdJbEoroKcX03Al1lIU= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/exp/metrics v0.162.0/go.mod h1:1pQJsNJU3b7mvKUc0kqTOWMOb4hxvKPAtoSrMlT6aqM= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/filter v0.162.0 h1:4LjeJSwQ5+uJk7DrWekqQnf0slko+W0Y2de3ifAps2k= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/filter v0.162.0/go.mod h1:rjooA7pQKxJRmDxvt19+mPNaXlQ3BngVzNIEr4+kcsI= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/healthcheck v0.162.0 h1:HDDPjB9Fb3YLWS+OL/28zNnzIz6vogFcparuWxKrMz0= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/healthcheck v0.162.0/go.mod h1:j+JBuRFAhcII2aEzkMYBheevM0235r8J4+AyeQTMQek= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig v0.162.0 h1:eq0EAALfG/mH8TAmynnoJ+K4wE3tp9yPWDHa3EezT/Q= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig v0.162.0/go.mod h1:uk3Df7D6LxBgancylthoR0U011UvgdvOsq940ECiqrg= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sinventory v0.162.0 h1:U8l6ppG4wv/CK1cDyMAvaNhhB9e6sjlXd5Yyckl4I/A= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sinventory v0.162.0/go.mod h1:0fFFcl2AIVFK8qqC1h1Tl5wXpynVMxQN/NJFKV2XMN8= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sleaderelectortest v0.162.0 h1:imAgrqam01RiWX/ha82Q1sUydWdl/bcH7oox88sfo0Q= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sleaderelectortest v0.162.0/go.mod h1:Ot2XUuoYNKlSNUekjQyh1vM0VOm4TSICtKUkpKSoBQE= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.162.0 h1:t1JJXwmGxD0valWPjWGWO3QxA1o2m1JzXrLxzUJ7Z+U= +github.com/open-telemetry/opentelemetry-collector-contrib/internal/sharedcomponent v0.162.0/go.mod h1:eNNa3TBIeNQ4QWoi3mx9XCz/MnJyJMNNDtkK/U2iBlc= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal v0.162.0 h1:oIQszbIDhV4LtWwAzRfRKWqnjc182+Cim/H3sVgLUfk= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal v0.162.0/go.mod h1:4ZijL1b9o4sbj8Dv7lj9c1JukqA0vCwa9YuhS/r3k8A= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden v0.162.0 h1:oG82viE5Q8LpVOy12gD0uxEiK28ayVyfSKIA05KSD24= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden v0.162.0/go.mod h1:Z8sNzsWLjB2HeCgKfphmYLpXIFZzLr3dVcLboZ2jnVA= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl v0.162.0 h1:qHU6Gag2c/VQV5FKD+h2wtjCx9L5L1K28dLtpqHjlfE= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl v0.162.0/go.mod h1:/sLC3QTIuNMzYiTmmXHuw9pP0pxGCDM4Fc2AdIKuH0w= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/xprofile v0.162.0 h1:de6e91R0dL7NMbYgcJGw7jxJdGVYfCub3FNw7C9aHf8= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/contexts/xprofile v0.162.0/go.mod h1:YIo6IaDxhUGpDdSh+lSFQ0uh2h1RBGUu0vEtX8G3VnY= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/xottl v0.162.0 h1:EYVB+wbinrHwTfDfQcq91YC5dWK4OWLfUwho2OThMYo= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/ottl/xottl v0.162.0/go.mod h1:Wy4jZaEuSYBQvPmltjUtIOG+gT3F2uz598U22f/SbPY= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.162.0 h1:Is4v2LutLm9LEC+FgTZ/p6AjJvd0d86j2y0q5WphVBk= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.162.0/go.mod h1:Hc1mqfHFJuCdKgECoNTnIeyfZBVccz39w+J+E2/6bL8= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/sampling v0.162.0 h1:w+LDU4+rQtFwbRPWa5FflgREMfVa17dO2P4QAWWIx3Q= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/sampling v0.162.0/go.mod h1:8BnLLeq8jSHH3VeovpIihWR52u7bC23p0k0cDlFkJMw= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.162.0 h1:rwQtMZwYsnb+CsrIUZU7+x1QTGqtMAUKj6+h2cAjbvw= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.162.0/go.mod h1:n9OsDRjnixA9vuaAphq70saxlAhwkBVRwW8MiezrbYs= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/status v0.162.0 h1:dE0PCmRmezLX1dsSaLU2vUKJq/82agrhiv8Q44dRwRY= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/status v0.162.0/go.mod h1:flu3kE06iQxjJN1ThENWgsNxeL7hSCS5cMaiZBF7qjk= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/xk8stest v0.162.0 h1:qM0sQVCpXqiEC5egcHlTgi+kJeTJpqccl+edd5pUZeU= +github.com/open-telemetry/opentelemetry-collector-contrib/pkg/xk8stest v0.162.0/go.mod h1:hDwYbgMU/xUGzDGTm2vZprOmK6LDh3y6Dw2HYsmL16Y= +github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.162.0 h1:zh6e9eINwChTvbG6zNGlOX0+70Fu0TovTqJKELgWgdM= +github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.162.0/go.mod h1:AWpPNfK/Aa92Xp157nEbN8pGdSnKZJS7+WhVdCzMfaI= +github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.162.0 h1:wlMxjb84JCmK5BXpxa3uqtRA7EBcTvFHhTuAaNR3puw= +github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.162.0/go.mod h1:hFLbtk9avA6o3aUXCVIgBf1+CKCGSpGfkfSWZ1j25X0= +github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.162.0 h1:kRggnR0rxP/XqVPgJHW3uBCRZRBaXzwayFFQ8BqyH5s= +github.com/open-telemetry/opentelemetry-collector-contrib/receiver/filelogreceiver v0.162.0/go.mod h1:Pvn6GNT5CASKLAoNfQ5G8JPoAuconk0W83HQ3FQHcn8= +github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sobjectsreceiver v0.162.0 h1:TJGcUE98WdirWHh5aEBbllWJpfMqSJDvqtv9/znob3s= +github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sobjectsreceiver v0.162.0/go.mod h1:IsX2HQ08welTGCORJIDIvUOklDFZCOU5aIcZr4nzdBg= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= @@ -314,8 +318,8 @@ github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7 h1:Ot2fbEEPmF3WlPQky github.com/openshift/api v0.0.0-20251015095338-264e80a2b6e7/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY= github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235 h1:9JBeIXmnHlpXTQPi7LPmu1jdxznBhAE7bb1K+3D8gxY= github.com/openshift/client-go v0.0.0-20251015124057-db0dee36e235/go.mod h1:L49W6pfrZkfOE5iC1PqEkuLkXG4W0BX4w8b+L2Bv7fM= -github.com/pierrec/lz4/v4 v4.1.29 h1:CDQY6qZOLI4DW0Nx6R1vRrifrCeQHnNXkMb0hZWXFjg= -github.com/pierrec/lz4/v4 v4.1.29/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4= +github.com/pierrec/lz4/v4 v4.1.33 h1:GjG1TJ1V4IzKP8L96muuuDNpTwd7D+l2ccXrjAbe014= +github.com/pierrec/lz4/v4 v4.1.33/go.mod h1:7SE9MC2STkNtL4PIwGhjmyVwvILaGI9/COYQNBhKM/c= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -325,8 +329,8 @@ github.com/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59u github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE= github.com/prometheus/client_model v0.6.3 h1:O0jaTVAYNxTHYInEPFJt5I3+sN8zqBtVMPTB1qyxiEo= github.com/prometheus/client_model v0.6.3/go.mod h1:gpN5P9S7Rr6Yr92PiQ+Ixvhf6JZEkF1dnxsYL2aPBEM= -github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi/PY= -github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc= +github.com/prometheus/common v0.71.0 h1:9KDAKb7Mj3HEVKyFCK6Dc/HIwlBzZIN2l7/lrHl3KK8= +github.com/prometheus/common v0.71.0/go.mod h1:CLJ5H8TEsGX8bl31BdMkfhIZ+QmZ9tBPPotUxUbfcmk= github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI= @@ -356,8 +360,8 @@ github.com/tklauser/go-sysconf v0.4.0 h1:7H0uAN+7RkwWRaxhYXDLqa5V3LPrJeV8wmD9dRU github.com/tklauser/go-sysconf v0.4.0/go.mod h1:8mTNWyog7H+MpKijp4VmKJAd2bbYQ2zuUwkYRbUArPI= github.com/tklauser/numcpus v0.12.0 h1:NR85qdvHA9pFse3x3weVZ0r0ST8R6l5RHbZrlRaqob4= github.com/tklauser/numcpus v0.12.0/go.mod h1:ABHeXzJnr/qqwguhClkZKT1/8VABcYrsyUiUGobwWJg= -github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= -github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= +github.com/twmb/murmur3 v1.2.0 h1:S6p/KHqoqsLveELUoKh6zSm/Kwwgl1pStVBgrrLa5UA= +github.com/twmb/murmur3 v1.2.0/go.mod h1:LVqs/avIy0flspVtmBd4VSbogDepFl6Wkj0i0ToccHE= github.com/ua-parser/uap-go v0.0.0-20251207011819-db9adb27a0b8 h1:yS0rzVnj7Z/ZeHzvv5erQbO2b8gyTL4CeMNodl9SJMQ= github.com/ua-parser/uap-go v0.0.0-20251207011819-db9adb27a0b8/go.mod h1:gwANdYmo9R8LLwGnyDFWK2PMsaXXX2HhAvCnb/UhZsM= github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4= @@ -377,158 +381,158 @@ go.etcd.io/bbolt v1.5.0 h1:S7GAl7Fxv12yohbwFfIbQCGDWbQbtDGPET4P/bD4lxU= go.etcd.io/bbolt v1.5.0/go.mod h1:mkltfYE5aUHQxUct9N9V+Kp7aSjFqjgrhcXIS70Lrdk= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/collector v0.160.0 h1:PnyWUf8vIViBWT8Klg50j0SbmUd5rkDjc2L/3jdRz3Y= -go.opentelemetry.io/collector v0.160.0/go.mod h1:mgavHnQvFpRWacnJ0wo7JTJK8xz1ubGVx6NEEToc8GE= -go.opentelemetry.io/collector/client v1.66.0 h1:uLwmr3QejpA0upn8bBAeDjMofC5kgmoujZAUNxdRpl8= -go.opentelemetry.io/collector/client v1.66.0/go.mod h1:pH/NTKb1jXgUYXvVnRZpYq/kiBse8hJJcQSkCns4dF8= -go.opentelemetry.io/collector/component v1.66.0 h1:JaAwBPug6Wm5V0+4qHpWVcazabgZvEozfcMC8gmgIY4= -go.opentelemetry.io/collector/component v1.66.0/go.mod h1:IIS7ZSCTijjAy5uaCwqAp6RKqOs1rzHl3EmwBZ6B0V4= -go.opentelemetry.io/collector/component/componentstatus v0.160.0 h1:DwFYGAARWGp0TW1LYIGVRgSgLa2L3uOjPmYLK53TApk= -go.opentelemetry.io/collector/component/componentstatus v0.160.0/go.mod h1:qCwO9DZvdlDaSyNjra2FbVxeOYjylS4WHU4XrInjy0M= -go.opentelemetry.io/collector/component/componenttest v0.160.0 h1:vfe7NaNksFjFfsrD1dDTCp/oQmknfI19z7SLyE8XDFo= -go.opentelemetry.io/collector/component/componenttest v0.160.0/go.mod h1:Rp9rk0xkLrfbWGhz78/y7swrC1rLG8nSOVb0tjRW2TI= -go.opentelemetry.io/collector/config/configauth v1.66.0 h1:Sl+8/vCJqZKDuZDojQyex4sqkhUSE/GL2ADl319I0y4= -go.opentelemetry.io/collector/config/configauth v1.66.0/go.mod h1:dYq9Whw9PYaWBlHcSHgCZJ37b4tMbCDQC8rCNHNPI1s= -go.opentelemetry.io/collector/config/configcompression v1.66.0 h1:x+W9FJV/R3gMGAHD1CeWTQvpLpvLUTLLW7urjP/Uiq4= -go.opentelemetry.io/collector/config/configcompression v1.66.0/go.mod h1:SyPEhp8hwY8Yxuxbet2AIFDRYIEKl+tn5/jKnWtV1y0= -go.opentelemetry.io/collector/config/configgrpc v1.66.0 h1:zbOJyYcHSz9e0GweRQUYUSk2QiUd8VRjebPnskAabSc= -go.opentelemetry.io/collector/config/configgrpc v1.66.0/go.mod h1:GNolWxmCZle2VRd3YV3cKhJ88/mbil8oV3K/JAYIH9U= -go.opentelemetry.io/collector/config/confighttp v0.160.0 h1:7Qlql6hwE64gWx1SG/9IgQuEwU3MvJAG5jpe8UjnxD0= -go.opentelemetry.io/collector/config/confighttp v0.160.0/go.mod h1:Kx6kgj4QCQkBP5SceIS5bdoyEGRpNLe4wWC1xX7aL3Y= -go.opentelemetry.io/collector/config/configmiddleware v1.66.0 h1:esvaflMeMFgLStuO948VYVPxHLduH0+kDRqdXNiRtpc= -go.opentelemetry.io/collector/config/configmiddleware v1.66.0/go.mod h1:B4/F68ahOHyrHDBW0vQltq5FRODqBIEvwlWBnzKUACQ= -go.opentelemetry.io/collector/config/confignet v1.66.0 h1:b8iQ2czQuIrRV+OK6DiGUSDbxJ9jY4Q+ZH4J9rH4mNw= -go.opentelemetry.io/collector/config/confignet v1.66.0/go.mod h1:0+gyxP6P/6t0yyX5cjCuban3srMChlzyXXXwgVRtxHA= -go.opentelemetry.io/collector/config/configopaque v1.66.0 h1:pyFA37SPoX7u6RWJX818YMGjHLENAUX5iYJYABqCdYw= -go.opentelemetry.io/collector/config/configopaque v1.66.0/go.mod h1:7KllH8nccvvn7BmrdHlFFYd6hh65a+bfGgn0y67nJ9k= -go.opentelemetry.io/collector/config/configoptional v1.66.0 h1:1DC5zgyfyUDzeaivb9w5bvPwGD/7AjINS3NCPdQWlHY= -go.opentelemetry.io/collector/config/configoptional v1.66.0/go.mod h1:GuJS8LsG5DIfpCYj7OAQxrOmN6SYuWCgwpHnyY7Yh8I= -go.opentelemetry.io/collector/config/configretry v1.66.0 h1:qFuzoYW+TDKJzxJY5v9N8O1w08FMEcvYCwIY83DIJPk= -go.opentelemetry.io/collector/config/configretry v1.66.0/go.mod h1:Y2Kdgd0HFBXYbGqUUUWGDLYviRHgl9aJVSyDfFYY7U8= -go.opentelemetry.io/collector/config/configtelemetry v0.160.0 h1:WlawoDoR1C5vOpWQ+4HOSXLsQEDFKFdQdperFbrbUrw= -go.opentelemetry.io/collector/config/configtelemetry v0.160.0/go.mod h1:dLqioNzNXPjdFPtHWppiKKWPZWHQRS2PKnoSYYAVvGQ= -go.opentelemetry.io/collector/config/configtls v1.66.0 h1:hozBpidIFUMH/q4Vs6au7ILjp/uAfAUJy2B2a1Fx9Rk= -go.opentelemetry.io/collector/config/configtls v1.66.0/go.mod h1:Qn5hjCugrDDssLA+bWqYwZmDQgD9fbTX9OtBfGYs+yY= -go.opentelemetry.io/collector/confmap v1.66.0 h1:9m9ZeZ17Iz0uuks5dK0JwLXwTrqfeCM9WWfqR+SO9C8= -go.opentelemetry.io/collector/confmap v1.66.0/go.mod h1:EsXDabkoH/H4mrfECHNdxE+MGQiBlCvyZ7caoK5xY7Y= -go.opentelemetry.io/collector/confmap/provider/envprovider v1.66.0 h1:P5D6oUJT9AHBZcfRptv1YUmZALCBhzAQK+ElrjGoWVo= -go.opentelemetry.io/collector/confmap/provider/envprovider v1.66.0/go.mod h1:U3l/G2BP8uayX61cZPhN7dNogrHle9j8Ld+a4hgwh+c= -go.opentelemetry.io/collector/confmap/provider/fileprovider v1.66.0 h1:bhK31LuUumquvIoOiWjTtOGyvuTeQE91YwOkbQqlEqo= -go.opentelemetry.io/collector/confmap/provider/fileprovider v1.66.0/go.mod h1:V465/UDMZhKVq/270P7NPM8hBnKgYY2P/I+IWLJLCi0= -go.opentelemetry.io/collector/confmap/provider/httpprovider v1.66.0 h1:2kUPx8Sze7qGAemRSNKFGxo6zgK4Iw+M7VXMZhmxUzk= -go.opentelemetry.io/collector/confmap/provider/httpprovider v1.66.0/go.mod h1:VKNw834NUcVseoF6WC1ifFhdN0dgSkNjL4U3YebL56Q= -go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.66.0 h1:TaIPHkStoxmXa2M+QcrddrjNeYHvfg74n59Vtf8yxqk= -go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.66.0/go.mod h1:gE38bpD2FlvmfrRkE6FywoUhXVs/FbfsZlyhQVXEUzU= -go.opentelemetry.io/collector/confmap/xconfmap v0.160.0 h1:QbS1LpwROwalfGQUub+hb09wvssBSKzKC6ObF9QncoM= -go.opentelemetry.io/collector/confmap/xconfmap v0.160.0/go.mod h1:7XBYTNmwNof7hdag7H/9+437Oy0ZwEslpivDQJQtNWk= -go.opentelemetry.io/collector/connector v0.160.0 h1:MzKdOOdK1J6xALHhN1HTXhRfFXgs+QtFjTeWIrVe4Ig= -go.opentelemetry.io/collector/connector v0.160.0/go.mod h1:8pRubHSt5CB5yN9ArgQl5qQHk5y++ZAcfsRhT0A0cg8= -go.opentelemetry.io/collector/connector/connectortest v0.160.0 h1:arhM/T8m+/KeVJWM3IrJRNkRzLGCryQgcDhNR+G3dGk= -go.opentelemetry.io/collector/connector/connectortest v0.160.0/go.mod h1:BhkNLCNyyGShbtchbNXsWAywtUzGZDdiGJ7LQybrFIo= -go.opentelemetry.io/collector/connector/xconnector v0.160.0 h1:3n14qQ7ARp6b/wTqbXjBMbOqZy3JyEF3HxppGXs/h6g= -go.opentelemetry.io/collector/connector/xconnector v0.160.0/go.mod h1:kByTaYOGl9ydTKQhxLJMAfiXQYzogM1dwtaCHcT86+Q= -go.opentelemetry.io/collector/consumer v1.66.0 h1:YcL8Y7jn0b9ko8hWKHIpilYnKNtp6pxjdrSpKFR9O40= -go.opentelemetry.io/collector/consumer v1.66.0/go.mod h1:CHUqFqerioBLb4usZEiHpzTKpEJH09a0CDyYECwQYFc= -go.opentelemetry.io/collector/consumer/consumererror v0.160.0 h1:MCByq8RbEPzeXcU8DHCJ9QsGxuhyh1A8tNs28Oqx8RY= -go.opentelemetry.io/collector/consumer/consumererror v0.160.0/go.mod h1:3sCDyUj55SUEnuVnPFBCS5mUl/yiB8J78cneqOUIjEQ= -go.opentelemetry.io/collector/consumer/consumererror/xconsumererror v0.160.0 h1:UQtWoxQ6OjGRPfdwQijUOkLvHXoXDnxKZjapz509Z8Q= -go.opentelemetry.io/collector/consumer/consumererror/xconsumererror v0.160.0/go.mod h1:13Hl4bTRKM38ngFBJsRhRY4/qrAHSLWnHQOnOIzZxG8= -go.opentelemetry.io/collector/consumer/consumertest v0.160.0 h1:ClfAK9pW6Hdk1Lks59RcUfodtvOhTSkUJs8XA6NuHUc= -go.opentelemetry.io/collector/consumer/consumertest v0.160.0/go.mod h1:tl5GPf6UdhI3kfonb46xTl7r017AhmvJM2uuJ+Z5NQ0= -go.opentelemetry.io/collector/consumer/xconsumer v0.160.0 h1:pbyjZUlDxLuFDa23cAxtDU6J7tvdXKfuZCe0RlJQV9s= -go.opentelemetry.io/collector/consumer/xconsumer v0.160.0/go.mod h1:GzOE87iaxj3dXiLFiXYMOi5qeps6F8X4jdjTWibwEI8= -go.opentelemetry.io/collector/exporter v1.66.0 h1:D69xYsoX/RBpL2ZOg22LLp3Jb7aBhwSxOCtepTjdWCY= -go.opentelemetry.io/collector/exporter v1.66.0/go.mod h1:jXFly200uQdAoaZQaY4dG/6j4RHCWuZ6vszd/qYSWss= -go.opentelemetry.io/collector/exporter/exporterhelper v0.160.0 h1:RoLOGzNUi930v9JOE9kTJmJdoOd2SlStorg6A7xsjBo= -go.opentelemetry.io/collector/exporter/exporterhelper v0.160.0/go.mod h1:tK8m0cSak6ooXxh2hESBgC5pWtfF83vGEDGtzGtTOAc= -go.opentelemetry.io/collector/exporter/exporterhelper/xexporterhelper v0.160.0 h1:yFXXyO8fXqxnwCmOmjF6/KSfB+q2yv4gE9odpVX7hOc= -go.opentelemetry.io/collector/exporter/exporterhelper/xexporterhelper v0.160.0/go.mod h1:dolEGQfJ5V5WgLKUy74gi5nefBT2xrmmaADVr/z2PO4= -go.opentelemetry.io/collector/exporter/exportertest v0.160.0 h1:hvrPUksoqKPMp0nLLac8puNqos+T6w/IOpnoIAWBuho= -go.opentelemetry.io/collector/exporter/exportertest v0.160.0/go.mod h1:Q4F0vY9nxf35juEs/9p11X839wdmJs3xUCIO8IF/Iho= -go.opentelemetry.io/collector/exporter/otlpexporter v0.160.0 h1:PrA9+i03Rpj6icqTMy2bbSr7KBH8zHykizQTe2xdzsI= -go.opentelemetry.io/collector/exporter/otlpexporter v0.160.0/go.mod h1:SruicBg+JDJfoCb6eXfLeuxT/zEyIkfSsZdxAIA1/E0= -go.opentelemetry.io/collector/exporter/otlphttpexporter v0.160.0 h1:2hXLMeVxC0jDBbT3AM2ELSzCpAhoubkO8KRP+vz1250= -go.opentelemetry.io/collector/exporter/otlphttpexporter v0.160.0/go.mod h1:9u1QO752s3lIJJvA7tsxX1x241WzjASWa+tTT2Wo89k= -go.opentelemetry.io/collector/exporter/xexporter v0.160.0 h1:RHRk4z8fzjH9YOTY2Yb/32sBqwkQPtd1YfxdiiIIaYs= -go.opentelemetry.io/collector/exporter/xexporter v0.160.0/go.mod h1:kJG/JDHTAVEKLGThxUqgoLIIyJvh85nFegiOrU+01eM= -go.opentelemetry.io/collector/extension v1.66.0 h1:aOxN7VEbdoV0uTUdcjTIfBQa3aRNkeNwMinwZP/uXSw= -go.opentelemetry.io/collector/extension v1.66.0/go.mod h1:lA+L69NHrq+FckGLkqIJCBvcVWi4y+BkZCI/qmPitAg= -go.opentelemetry.io/collector/extension/extensionauth v1.66.0 h1:38ydNyw1OKsYu4RzGFA+nEuYoMCvzbO66BS8jNawfPY= -go.opentelemetry.io/collector/extension/extensionauth v1.66.0/go.mod h1:9Et8qOBCXgc7QdN6z0OW/QWMyulHDhu2D8s0/lykKLo= -go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest v0.160.0 h1:sAu5IoXo2VN95Q9b6OziuThA5GW+a5D9hL9PAYaUcyY= -go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest v0.160.0/go.mod h1:RpXZFEFCcw53e2BD7J4hWbMLJtVRp0a4vi4395fRdLg= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.160.0 h1:B1YK2/3bPcaU4e7+zajiSL8UDuOkXGcRnOkK8LrFpxU= -go.opentelemetry.io/collector/extension/extensioncapabilities v0.160.0/go.mod h1:qPblgbz4WDb9qDczFsnsKc34EO+ds22FYn+ArsPANuo= -go.opentelemetry.io/collector/extension/extensionmiddleware v0.160.0 h1:7YleoKcX86Aw/e/UWOx2DM0YF8qEK6dub4HgWlArO+k= -go.opentelemetry.io/collector/extension/extensionmiddleware v0.160.0/go.mod h1:vlTPYcKAadviSXKi2djz8GxT2ryjvqLXVFCWo1bPMWw= -go.opentelemetry.io/collector/extension/extensionmiddleware/extensionmiddlewaretest v0.160.0 h1:14ijqZ4Uqz20XP4y1FzmKwKKNMzoAANzFU+pL1ED4WI= -go.opentelemetry.io/collector/extension/extensionmiddleware/extensionmiddlewaretest v0.160.0/go.mod h1:mXZWQw38xd2pT2kb1fY7vEX87OySW9qZeocBOqpVlmQ= -go.opentelemetry.io/collector/extension/extensiontest v0.160.0 h1:WQkWvcAJwLh/wq+w6p9UqCxAV2K/SMPkGTZ9LD9LNYU= -go.opentelemetry.io/collector/extension/extensiontest v0.160.0/go.mod h1:xViM7+Wa4vNe1eH3DmFC8P4Vy1QlYlXt17sRFvBtXRE= -go.opentelemetry.io/collector/extension/xextension v0.160.0 h1:z7UrTp/2e7g1+UZBSTZ2OYZW6pw5M84imeZ/R67B3QU= -go.opentelemetry.io/collector/extension/xextension v0.160.0/go.mod h1:wuQnAxEgpLNWp3ItlRUvpMensdwivuoeV4o9QYwBPEQ= -go.opentelemetry.io/collector/extension/zpagesextension v0.160.0 h1:a+6Lx/DW3lTUyXEvSN/HC/0eht6tulrdlDqmeAgtQVs= -go.opentelemetry.io/collector/extension/zpagesextension v0.160.0/go.mod h1:DMgfWE8bEVcsGLQDW4VV7f/Uq7tGT5mw4QZH+alnS5Q= -go.opentelemetry.io/collector/featuregate v1.66.0 h1:zy7JvvPanCVexGnZnMWR/htZ1BKWPEo1/vZKMuhZSQ0= -go.opentelemetry.io/collector/featuregate v1.66.0/go.mod h1:dRYifiJa2vQ6LWpPwHny4mL82mnGWsWEVeVWw+DhYJw= -go.opentelemetry.io/collector/filter v0.160.0 h1:Ls2Gk8i1Tr0FBhIGrVm1yMGdqaYlQ6e7c19aESk6c4c= -go.opentelemetry.io/collector/filter v0.160.0/go.mod h1:wrbPwRqUUnGocb+wpgMpPHAwKO+AWYgtO3tONw5ROcw= -go.opentelemetry.io/collector/internal/componentalias v0.160.0 h1:rDRD1s22Z13Q9YzkaTOfkwrLD7Hf7T4tmE6IX0bndlk= -go.opentelemetry.io/collector/internal/componentalias v0.160.0/go.mod h1:vfDgm9skzaGSDWDJgZl3E5/J6MXY3pnWiXnda4NA3/k= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.160.0 h1:L4KoduejWKVMobesmKCjkCNj27M5OuMZInaw01nrQOs= -go.opentelemetry.io/collector/internal/fanoutconsumer v0.160.0/go.mod h1:TWG2ZZy2O2B9usOE4POz5HkIsjB3X0AmcuR8c2Y036g= -go.opentelemetry.io/collector/internal/memorylimiter v0.160.0 h1:OarWHi/5hphIPpPQpoe8JKuFhZfUred5lHcancD0jjc= -go.opentelemetry.io/collector/internal/memorylimiter v0.160.0/go.mod h1:Wm6QiPa/4VrCORnS79I0G0XGEsZhUlNnqygAeK7F8ZQ= -go.opentelemetry.io/collector/internal/sharedcomponent v0.160.0 h1:Dl/jBWtkLzxcvDS8bzG+AUkclIGe4iamuS4idMyBh+0= -go.opentelemetry.io/collector/internal/sharedcomponent v0.160.0/go.mod h1:IXxPebVhnIOw8yGW8mcb9PbdHdQk2C+MSkaR4FIt+20= -go.opentelemetry.io/collector/internal/telemetry v0.160.0 h1:0fGdfaFpbutckKY2wjORLLXpyr6lq1pKuE2CaKwBHtQ= -go.opentelemetry.io/collector/internal/telemetry v0.160.0/go.mod h1:pxJvzK/LVuTjxgeOwzgtXWQaiwYRe7gYlCgxb+EtMsM= -go.opentelemetry.io/collector/internal/testutil v0.160.0 h1:Y6AeI8KjqglQzKYmNoSy9FB2CohuyoYxcLZEXQPW4og= -go.opentelemetry.io/collector/internal/testutil v0.160.0/go.mod h1:FV43FoAsh4fP615Sc5ZSh7iPMgZaSgha6ngavix9OEI= -go.opentelemetry.io/collector/otelcol v0.160.0 h1:pLmS1OVpPJhQqkQbjdkVfc/3DMHh/oWa9DEVmm9C2b4= -go.opentelemetry.io/collector/otelcol v0.160.0/go.mod h1:hYmAcYJ7tqwiabLnqsp1piI7LuHYR7e5qs6NQ6LwyNs= -go.opentelemetry.io/collector/otelcol/otelcoltest v0.160.0 h1:l8JhME/+NJWYT54BMHYoO+soeoO7opcUhRbfF7JeuCw= -go.opentelemetry.io/collector/otelcol/otelcoltest v0.160.0/go.mod h1:tNpfAgSYtitl4C0VkTqJDn9Z1zCkdHmMqcS/4EZksDA= -go.opentelemetry.io/collector/pdata v1.66.0 h1:GvbRMxks0XbmH7UEGvgcauboAgH+DE9xMtgIEGUBENw= -go.opentelemetry.io/collector/pdata v1.66.0/go.mod h1:tdtY5DNoyzgXQmdH7pPNyeM5EiH3dGsKdPC6wUXeigU= -go.opentelemetry.io/collector/pdata/pprofile v0.160.0 h1:+8euxO2GcGN7CRB0wa/ddloU6AWCMjW0vanbwUIQicE= -go.opentelemetry.io/collector/pdata/pprofile v0.160.0/go.mod h1:8lEJ1b9wLMl9nqlGdwXdXEp4a1eGWzkJ85E1HgvdXnE= -go.opentelemetry.io/collector/pdata/testdata v0.160.0 h1:yFq91t7uXtAoa/S6DvWf8RyT67yzrX4tOp9xHiyYftM= -go.opentelemetry.io/collector/pdata/testdata v0.160.0/go.mod h1:GOlN4aeYFhx8Z1d5ujhJlckwcs4L+Iy++2SxDlbWGGE= -go.opentelemetry.io/collector/pdata/xpdata v0.160.0 h1:e+Ou0lVvDjLYTFmFAYAf6l2TjmgH2Dx0s8y8sDYKCPU= -go.opentelemetry.io/collector/pdata/xpdata v0.160.0/go.mod h1:7cVHYDrt9W4nyKHSn7eh0y/1VMgE+8YXWOQAD9c2xPU= -go.opentelemetry.io/collector/pipeline v1.66.0 h1:wh7bydw4VXE/8wkO3Vq7msTSdCWciE5/y/HxXOwjN34= -go.opentelemetry.io/collector/pipeline v1.66.0/go.mod h1:4S7iD/7hGDNXg4yPi+5es5WTvwo/Uie2OoHio79xokI= -go.opentelemetry.io/collector/pipeline/xpipeline v0.160.0 h1:LU9e57Ozxm95wfaiIColv2Nyx+HcPVBYj7pmuCmNxLM= -go.opentelemetry.io/collector/pipeline/xpipeline v0.160.0/go.mod h1:i2/f6k2N1OxmIn8LXRYiE2ZNeHrYat/A99JOTuBwGS4= -go.opentelemetry.io/collector/processor v1.66.0 h1:oNsicM3SYORpR9IzqHD8rnMpasuXIOI2o3Qdv7PHqUA= -go.opentelemetry.io/collector/processor v1.66.0/go.mod h1:L/McJZAaCC1LtkDS9SXd65SL7fGV2MrI8sK6CvisOFY= -go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.160.0 h1:fu4qPOeEaje83SxD+xO0tcuOcA2vlcF/qbjN0LT0T94= -go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.160.0/go.mod h1:0Dg2X+MCpap9W9IG49e+88pPdB3z2BErgHK3eU86NFg= -go.opentelemetry.io/collector/processor/processorhelper v0.160.0 h1:ziKABIE/BEQ9hkivOUEpjKYC5hDPFwylKiBwQqvOfmA= -go.opentelemetry.io/collector/processor/processorhelper v0.160.0/go.mod h1:FIyFZDYU08OcYonDgY9HYYpKOfqqyRZI+jysEr/xegI= -go.opentelemetry.io/collector/processor/processorhelper/xprocessorhelper v0.160.0 h1:3EW51VSdk0tb03qOyE9v/TAUyzNIaFlA9pR9cbjpk2I= -go.opentelemetry.io/collector/processor/processorhelper/xprocessorhelper v0.160.0/go.mod h1:Q+dHxJMKATD30zbry6X/xV9Tp4lFpiSLiHCfNZmZtzU= -go.opentelemetry.io/collector/processor/processortest v0.160.0 h1:UpuV/guqpBd4TD8J3yim7pbOGO4tze1RSfu3/tEq598= -go.opentelemetry.io/collector/processor/processortest v0.160.0/go.mod h1:dZHObCxq4fFslWISI2fGK8vLZ+aQFyQv7h1d+5Wv6nE= -go.opentelemetry.io/collector/processor/xprocessor v0.160.0 h1:3bvK03H90nsPjS/Lh0XDaXm1/vGOxUCdNNZ/HPW4OcI= -go.opentelemetry.io/collector/processor/xprocessor v0.160.0/go.mod h1:21hAhrW9b7fsmqVg3mMPS9knPpjJ/EFMx8sKjPXQ6qU= -go.opentelemetry.io/collector/receiver v1.66.0 h1:H7BSRnT/N3aeCbibDNLGf/onHvIxB5xVfzB8UKNVqEQ= -go.opentelemetry.io/collector/receiver v1.66.0/go.mod h1:IwJHhJvBUShZdKIjMpy0zN4XontHofXNlkaCQOO54m8= -go.opentelemetry.io/collector/receiver/otlpreceiver v0.160.0 h1:Gh0lRFx05mLn1w2FJ4s+zvz+IDGGDL+ft0QTVNUnJR4= -go.opentelemetry.io/collector/receiver/otlpreceiver v0.160.0/go.mod h1:HvMfYAvq4ucAmfPoPrQfsfJb79R4D0Ueh4NNJEVapZw= -go.opentelemetry.io/collector/receiver/receiverhelper v0.160.0 h1:2MZMpojwjbtGgnBBErENw+9FSa+k4jl/CRwyNjfBmhc= -go.opentelemetry.io/collector/receiver/receiverhelper v0.160.0/go.mod h1:51EaCn3C9/7/FBb8zt/Hwh5cHBv/zC1ApglYt9tCkPU= -go.opentelemetry.io/collector/receiver/receivertest v0.160.0 h1:MJn7ty7+ojP704ZCbAm/EblHcPbnsgeK/0sYvJjf+a4= -go.opentelemetry.io/collector/receiver/receivertest v0.160.0/go.mod h1:sAfx7MEXf3tRmiJeoU9ytG8t3aTssdqUutP8lmGWYCQ= -go.opentelemetry.io/collector/receiver/xreceiver v0.160.0 h1:t6waOE3J5K4ay26zOclwzogxYZVkM8o/iAASxIi/UpU= -go.opentelemetry.io/collector/receiver/xreceiver v0.160.0/go.mod h1:D+nmhhnDducIDx1EszxkHIeQ3LfqSUwAGm/UcPniI5s= -go.opentelemetry.io/collector/service v0.160.0 h1:jHbuxxCfxRRimPqkdjQ3UyJgiyukTLZJ9Y8a/H2BAAc= -go.opentelemetry.io/collector/service v0.160.0/go.mod h1:W8vGxjIpTdHEv4xVkQIarKTOJMoXXHqziFLaBQxxqXs= -go.opentelemetry.io/collector/service/hostcapabilities v0.160.0 h1:XgTV+MbgOHdwfoR/AY53n3OmxBAoo6NoRw2FE145QQw= -go.opentelemetry.io/collector/service/hostcapabilities v0.160.0/go.mod h1:AR4zKEimC8dT6qqWIiCcUxk7XL+O7wpIU6rrnhO1nV8= -go.opentelemetry.io/collector/service/telemetry/telemetrytest v0.160.0 h1:cgse3g1EmsjZ2ItYjCV3H45B91xGBDtbA85NqWf4QLc= -go.opentelemetry.io/collector/service/telemetry/telemetrytest v0.160.0/go.mod h1:lA7gscAbNydq2zaMITROoJdBC27G+WLBk3JcgjWA8ro= +go.opentelemetry.io/collector v0.162.0 h1:dJZqd0ma/BW7lgJkMGuBGeEg72WjLfCPv9YKS8Uye2s= +go.opentelemetry.io/collector v0.162.0/go.mod h1:mgavHnQvFpRWacnJ0wo7JTJK8xz1ubGVx6NEEToc8GE= +go.opentelemetry.io/collector/client v1.68.0 h1:KYFToZyfSDQ7CTX5uaE922w4p0vj8KOZc9jXeza3c5g= +go.opentelemetry.io/collector/client v1.68.0/go.mod h1:caDCF8Cigg/4tMwNRme3o/khh80Xq4bjAPeWll8WMaY= +go.opentelemetry.io/collector/component v1.68.0 h1:Qa/K2VSedvBj0/58QfltrAqplAR13cKC33WXvB7y/Qg= +go.opentelemetry.io/collector/component v1.68.0/go.mod h1:bEUVjV9ZS7mF6wf33tAWR0UPgc0ffr0JRqtdBrvkHUQ= +go.opentelemetry.io/collector/component/componentstatus v0.162.0 h1:8m6t1kp3X/FdmgPIDbbiHcLy0m324MOSbW8btQN6rlU= +go.opentelemetry.io/collector/component/componentstatus v0.162.0/go.mod h1:N/V+QXvnT3b0p6fNGJW5qL6zawu5Fyf0EXkcwuKq07I= +go.opentelemetry.io/collector/component/componenttest v0.162.0 h1:1K40jPwGK/InpXuom2liBkBozWG3ldT4U4NSRw3uemg= +go.opentelemetry.io/collector/component/componenttest v0.162.0/go.mod h1:1WbhXC61PxCFr8wGXBJdKUSiZYHHZM/Tg7dZP4E9wd0= +go.opentelemetry.io/collector/config/configauth v1.68.0 h1:47seuYmghupkPjvQ9R8yG/l9pGB6trlfQERopeE77bg= +go.opentelemetry.io/collector/config/configauth v1.68.0/go.mod h1:Y9+7QDuBtqJdHF+5/PLlZu1i1F1J3Kg86oYIaqF1Wh4= +go.opentelemetry.io/collector/config/configcompression v1.68.0 h1:aiMTXkU+gxI0n43n4hlkCjIVQW7q67taE7bRIwwK/r4= +go.opentelemetry.io/collector/config/configcompression v1.68.0/go.mod h1:SyPEhp8hwY8Yxuxbet2AIFDRYIEKl+tn5/jKnWtV1y0= +go.opentelemetry.io/collector/config/configgrpc v1.68.0 h1:wQyEYiSlmGRiRtXxUE+3JmxQ0/OpCAWHy3SmRyA0Av4= +go.opentelemetry.io/collector/config/configgrpc v1.68.0/go.mod h1:pTWh4oFKKvlyxx6BqbnKwkH62O0OEyYEULEcKvvrxXg= +go.opentelemetry.io/collector/config/confighttp v0.162.0 h1:j9G9+KajfXVPbLd9mypk7mcdbJXEjKHLGfx+UMl6900= +go.opentelemetry.io/collector/config/confighttp v0.162.0/go.mod h1:YtSwju57Qq75N0NsATBTaVq0AfRbfwkZqOlG/wr0QmA= +go.opentelemetry.io/collector/config/configmiddleware v1.68.0 h1:genE6Wh6zTSYPU/A4XALzxrZu1FO8BCCVaoQHYTikKw= +go.opentelemetry.io/collector/config/configmiddleware v1.68.0/go.mod h1:kbaEnC1Oank2BQJIhA6UTbr/zpc3Pwm/RrhOGyuonXo= +go.opentelemetry.io/collector/config/confignet v1.68.0 h1:7SpApG8NFh2dSy+e85rf28KjSizp8dA0b/d8gccUY54= +go.opentelemetry.io/collector/config/confignet v1.68.0/go.mod h1:0+gyxP6P/6t0yyX5cjCuban3srMChlzyXXXwgVRtxHA= +go.opentelemetry.io/collector/config/configopaque v1.68.0 h1:MEP+4Fo9sd8xjjJ1xIOlzZZ8yNz4WiNFPbXLWKBHtgY= +go.opentelemetry.io/collector/config/configopaque v1.68.0/go.mod h1:uPd2PCHr/gcRh3ygk3pfocOeIDC0mjNs76C4RjyxFAk= +go.opentelemetry.io/collector/config/configoptional v1.68.0 h1:V3Q48DzsAX18bkNAbJ6R57z21CQ1LgWW92I4oSfr1pk= +go.opentelemetry.io/collector/config/configoptional v1.68.0/go.mod h1:M2GgwtzYbWNs5NLekF1aRfoWeKIQ2smpZY1cc/Xjlg8= +go.opentelemetry.io/collector/config/configretry v1.68.0 h1:8PWKry+Zhh6oOG5xesNjZkkudIm9wydtg9HsyEz+we4= +go.opentelemetry.io/collector/config/configretry v1.68.0/go.mod h1:Y2Kdgd0HFBXYbGqUUUWGDLYviRHgl9aJVSyDfFYY7U8= +go.opentelemetry.io/collector/config/configtelemetry v0.162.0 h1:Fh2wUUH4gkczOcWC5Vpim9G4igg5KaATawKkIPUfmAI= +go.opentelemetry.io/collector/config/configtelemetry v0.162.0/go.mod h1:dLqioNzNXPjdFPtHWppiKKWPZWHQRS2PKnoSYYAVvGQ= +go.opentelemetry.io/collector/config/configtls v1.68.0 h1:DvfkuEBPhx6fhAuNh4FrQGKQ7FJrgxz8vOjRSeXDmng= +go.opentelemetry.io/collector/config/configtls v1.68.0/go.mod h1:XqKoGaoGucLXo+uByioSlLGhu3RoSE2wc13QyU10GQE= +go.opentelemetry.io/collector/confmap v1.68.0 h1:3j2p8KZQwB+niUatzHA/0/YPGgI2RBXuMf6BlkvDwKE= +go.opentelemetry.io/collector/confmap v1.68.0/go.mod h1:e81Mf0/8XWlFz6KlT8Go2K6V9guNbTz7o6zr5X+Xz/4= +go.opentelemetry.io/collector/confmap/provider/envprovider v1.68.0 h1:PsP5wAC9SFnvLsaNZQF1kypeFRDWbxf1TzcUwfoWepU= +go.opentelemetry.io/collector/confmap/provider/envprovider v1.68.0/go.mod h1:SxyXqomok4iFvdaSUmj7QOzLLlzYjUo/dnIne7YVX+Q= +go.opentelemetry.io/collector/confmap/provider/fileprovider v1.68.0 h1:0MJOmc7ft2tST76++zYRfUINN4BFhL6IybAdBMPD//o= +go.opentelemetry.io/collector/confmap/provider/fileprovider v1.68.0/go.mod h1:PLqTzWzZAbI0ZSZpJ5VN1SjRTHpiajvYXxzJFOiEHwk= +go.opentelemetry.io/collector/confmap/provider/httpprovider v1.68.0 h1:Y6pJN8+uZFIA6IKlydfjBCZElEt9CCwVh440r/BGdK4= +go.opentelemetry.io/collector/confmap/provider/httpprovider v1.68.0/go.mod h1:wEgruRsDYV+KY3xoOiNVLsXWBIP/mbC+VHDkIbtFx5E= +go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.68.0 h1:wj7XFV2DdwG44i8ysPIfvkusR51Ic7j4sJFxxB9iSyo= +go.opentelemetry.io/collector/confmap/provider/yamlprovider v1.68.0/go.mod h1:t1baa4ExxG5S9YuBCCT1ImKg1lV4spSFCB/EYPqbK5g= +go.opentelemetry.io/collector/confmap/xconfmap v0.162.0 h1:smR67xRUkNrmvWFes2oxRWpxrOwCerLCg+zbgko4Aes= +go.opentelemetry.io/collector/confmap/xconfmap v0.162.0/go.mod h1:Rw81Pjk600OA1Z8FGspLDXA5kBJbgsPxptEWyzA4Vbo= +go.opentelemetry.io/collector/connector v0.162.0 h1:3Gg37rRVWfrI8Rrnh+Q6GKPek1LhvhJjNl1zIu0V3Ss= +go.opentelemetry.io/collector/connector v0.162.0/go.mod h1:K+p4qnptnaq2RGQjaR5ft/Gr/9kpN5Wl3HlXAKBwgIA= +go.opentelemetry.io/collector/connector/connectortest v0.162.0 h1:xNPeLKQJdg0i4+Fdy+tze035clcN3M6z4NsOEP4Qa78= +go.opentelemetry.io/collector/connector/connectortest v0.162.0/go.mod h1:FlfhU9JqPFvrbLY+YSO17gH4PRwGbL+JYSYQ2heNVFA= +go.opentelemetry.io/collector/connector/xconnector v0.162.0 h1:9QHUPI2P6hXL7o9PnQ4ues3fv+d4ZLwW2wxObaonAB4= +go.opentelemetry.io/collector/connector/xconnector v0.162.0/go.mod h1:W2lmDJvIu/kKgvTbtB9MnKLrRcIXxQ34uRJKwRAHaCI= +go.opentelemetry.io/collector/consumer v1.68.0 h1:c/k97eLSqhe0Fs8RUALs9OwHkZbaXor5aKY5HOVlOM0= +go.opentelemetry.io/collector/consumer v1.68.0/go.mod h1:vwU2MXt7iwMZo+9snzVNKHat6+GixLIAMdH2jKAmN9A= +go.opentelemetry.io/collector/consumer/consumererror v0.162.0 h1:DaUYP4a5kmPeN2Xajiazl1FRlNgB+rLugYT/A46oAXY= +go.opentelemetry.io/collector/consumer/consumererror v0.162.0/go.mod h1:bOe3yweGtthJbm+FlutpVZdr/ZyriE2RcLNoh73awM4= +go.opentelemetry.io/collector/consumer/consumererror/xconsumererror v0.162.0 h1:Ct1iwvQ4PemEV2KLvFNLyJQNjqsgrwni2vnfQ7VIGWE= +go.opentelemetry.io/collector/consumer/consumererror/xconsumererror v0.162.0/go.mod h1:eH1SO15oJBc/BUjjeEFSzhRjVtn73QBFxt1mlGYQ+sU= +go.opentelemetry.io/collector/consumer/consumertest v0.162.0 h1:FMaCabZYARFcLU6L2ERuAj1voodmneiNXJc0jphHNBM= +go.opentelemetry.io/collector/consumer/consumertest v0.162.0/go.mod h1:5TIUTPVAnUkIgz7v7Pu7IAm5nSVIFYh6HFEwPmOzZeE= +go.opentelemetry.io/collector/consumer/xconsumer v0.162.0 h1:pTjIMVMQv4Oo/otMnO79VYAp4UFde4wuELoZK8B3/yI= +go.opentelemetry.io/collector/consumer/xconsumer v0.162.0/go.mod h1:x1R+mMuboKIVXiAjURNwuu0KbH8G/2VZVNnTVKrWhmU= +go.opentelemetry.io/collector/exporter v1.68.0 h1:M+l+mqbISOew3fpNH81k9JbySKjOx4PVaRa6R5AlCxk= +go.opentelemetry.io/collector/exporter v1.68.0/go.mod h1:TQSPB0JvclFnh0R4ANe74hVR9uHAE/6G7eh8+aQN/fg= +go.opentelemetry.io/collector/exporter/exporterhelper v0.162.0 h1:PYOhmghgbrcmaWMUVi3MLMWFkwR9o+J5JdVqO4Vwj1Q= +go.opentelemetry.io/collector/exporter/exporterhelper v0.162.0/go.mod h1:J0/R74LDuZZBPWF/auvtuKyHvYYpYrT5onjrByV2FRA= +go.opentelemetry.io/collector/exporter/exporterhelper/xexporterhelper v0.162.0 h1:hpVXWPgQuXINTyPqjB/Tma6JyCeyKd5MHpjzCMWApfQ= +go.opentelemetry.io/collector/exporter/exporterhelper/xexporterhelper v0.162.0/go.mod h1:pxeyMLAAwJk3vvLPfEeH3LbLqWpj9auDdrM/WU7cotI= +go.opentelemetry.io/collector/exporter/exportertest v0.162.0 h1:JQwIP4jb1znH5cDy5xg+fHBRqP8mx4ZkYiuA3dHw94U= +go.opentelemetry.io/collector/exporter/exportertest v0.162.0/go.mod h1:Xiggw2O5SD5MNhoTgsXSTVyius5GPzPbrvi1FOcChKw= +go.opentelemetry.io/collector/exporter/otlpexporter v0.162.0 h1:mWjgMYx/t13NOa5TTxWWfOK8qIVBucZQudgvFo11uog= +go.opentelemetry.io/collector/exporter/otlpexporter v0.162.0/go.mod h1:YY4ss+i1kijzlXZIOlP47ODFKvDMUxfcSz/jCJgwZg0= +go.opentelemetry.io/collector/exporter/otlphttpexporter v0.162.0 h1:fMNW9zfcRFpytImNJ3KMoZDq27DBmN3AgRnVewa4mRE= +go.opentelemetry.io/collector/exporter/otlphttpexporter v0.162.0/go.mod h1:3KrruUpIUQJhyPm3gpHTUo/4v7zVAECyNPboVF46xgs= +go.opentelemetry.io/collector/exporter/xexporter v0.162.0 h1:AaQ/SxXcnUcWCc9Fi37o1yrg1QkgwkfbUqyv/HCPF6M= +go.opentelemetry.io/collector/exporter/xexporter v0.162.0/go.mod h1:78433YU2lnQdeLyTIH1/eRTE9GTprAI36/jk25NuOUY= +go.opentelemetry.io/collector/extension v1.68.0 h1:u7wf8DYryjL2Hp27Pj43DjJAL4hecNxCZd16ylBmiUA= +go.opentelemetry.io/collector/extension v1.68.0/go.mod h1:THvQvhgqv9jDG9FPpbD4SJL+ZuxmXnatukOg7mFbUEc= +go.opentelemetry.io/collector/extension/extensionauth v1.68.0 h1:KOxf3p8fxW/AxXnRym5MiWNxGFGPy7J/of6hdGl3RRA= +go.opentelemetry.io/collector/extension/extensionauth v1.68.0/go.mod h1:9Et8qOBCXgc7QdN6z0OW/QWMyulHDhu2D8s0/lykKLo= +go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest v0.162.0 h1:FylVj4xMdSl60xTKrHOqL/q48gg3yF1VZqZi/UXKWs8= +go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest v0.162.0/go.mod h1:mXqBPq4+PNYWpuzsJb+Z5yhBnULB+l6EkmMidblse/U= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.162.0 h1:MxEvBaLReQErQ18RPlvITm6HyCEVXIIrvz5z/vOb4I4= +go.opentelemetry.io/collector/extension/extensioncapabilities v0.162.0/go.mod h1:mmVMqg5vQhIEqpAiJeqLpfgEdpJyg7NOXnJ/iTrfAeU= +go.opentelemetry.io/collector/extension/extensionmiddleware v0.162.0 h1:hcTgGSIOAUoyeFqdAHwGdonKvYg2nyOkeaQIMi6mpSM= +go.opentelemetry.io/collector/extension/extensionmiddleware v0.162.0/go.mod h1:vlTPYcKAadviSXKi2djz8GxT2ryjvqLXVFCWo1bPMWw= +go.opentelemetry.io/collector/extension/extensionmiddleware/extensionmiddlewaretest v0.162.0 h1:vpj30jpJ7Dm/Wv9t0TgPQ9EWdW/z/9KXr5hnBzgPld4= +go.opentelemetry.io/collector/extension/extensionmiddleware/extensionmiddlewaretest v0.162.0/go.mod h1:lLuq0JfYX0axjO2+EaYE5m+m2/Pt3ToQ8E54pHrW3qE= +go.opentelemetry.io/collector/extension/extensiontest v0.162.0 h1:l2kYdwTLdHkDIbCVv8OJM+xDUgx0IAhV/QBWHONpuU8= +go.opentelemetry.io/collector/extension/extensiontest v0.162.0/go.mod h1:Jw5xu+2novqrElX/tuSHWm0tZebICqgkB4HFmi3bFOc= +go.opentelemetry.io/collector/extension/xextension v0.162.0 h1:KDpNxY2IQK9hhwNv/wUrYrfqCW+2Aj2HRNdTBN5/muk= +go.opentelemetry.io/collector/extension/xextension v0.162.0/go.mod h1:ldgFIS4X7K/LtT9zg64OuH2TdEbI0oRIwYgiMumCN98= +go.opentelemetry.io/collector/extension/zpagesextension v0.162.0 h1:4uGZK90nssbdkRXbTcg0ciFCu1eptf4g7s51hjUW4vg= +go.opentelemetry.io/collector/extension/zpagesextension v0.162.0/go.mod h1:vk9b9Qq5215abZBGVQ3OrcjVTUGistbpOsk9I+CrAbk= +go.opentelemetry.io/collector/featuregate v1.68.0 h1:zCnq7dk2HP/xXRN9bFX9cBCuKQhX/XRmkGjVQIWEdSc= +go.opentelemetry.io/collector/featuregate v1.68.0/go.mod h1:dRYifiJa2vQ6LWpPwHny4mL82mnGWsWEVeVWw+DhYJw= +go.opentelemetry.io/collector/filter v0.162.0 h1:kUSm4HB4PonuCYWPgf6z3adZo7uWfh+sDLokMWmDGFM= +go.opentelemetry.io/collector/filter v0.162.0/go.mod h1:HHL4vReXZvP3xIilZqA+fGyBwd26y3/elQXXSt+WlS4= +go.opentelemetry.io/collector/internal/componentalias v0.162.0 h1:VTfVHEdcc5kueY6qtd2Z32RKVGEd9aeKrnQGQhXaeF8= +go.opentelemetry.io/collector/internal/componentalias v0.162.0/go.mod h1:mW1LPEHX2xu89beM/l54b8vT2f/fHTeR4ykCupVItgM= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.162.0 h1:gIKDKzKsM8mUTJoC7u7wJIAjF7+1mCti+8GaQ6OuKPo= +go.opentelemetry.io/collector/internal/fanoutconsumer v0.162.0/go.mod h1:sN5LRVNZHoX1atsT9vzFdb9A4TdFFOlGFDz0zbDyefQ= +go.opentelemetry.io/collector/internal/memorylimiter v0.162.0 h1:ZFgbqxBA5LG2DrOHHodQaT7FXcISXlY18wQVyWjP/SQ= +go.opentelemetry.io/collector/internal/memorylimiter v0.162.0/go.mod h1:c6Fi/g5jidUXqmS7DzvLOX87NZJkoTdSYImKGUni84M= +go.opentelemetry.io/collector/internal/sharedcomponent v0.162.0 h1:Wjjd0qQv3OS1dHvBGbpJh2uJvk3242c2g/Kiju4Df/w= +go.opentelemetry.io/collector/internal/sharedcomponent v0.162.0/go.mod h1:kj3D4tGkTVPFD8d0L9dIomSDHqulNnSUsED1DvZwNyM= +go.opentelemetry.io/collector/internal/telemetry v0.162.0 h1:5pgPPirB82Z5lmLodNDlgKOkry+RNOepOMWpZmUYRcc= +go.opentelemetry.io/collector/internal/telemetry v0.162.0/go.mod h1:6RyfH7KxwIFQhbrgZv9s2vV3CfQpEK3eQwuK23jdp8o= +go.opentelemetry.io/collector/internal/testutil v0.162.0 h1:WWliyTnsH6wqwoci9CDgK7jR6rwoW8u4C1dR+yVui1g= +go.opentelemetry.io/collector/internal/testutil v0.162.0/go.mod h1:FV43FoAsh4fP615Sc5ZSh7iPMgZaSgha6ngavix9OEI= +go.opentelemetry.io/collector/otelcol v0.162.0 h1:Md/ZNaxLd3wbnB95jUhzZ52M46U4i8Vl830wraRRqIE= +go.opentelemetry.io/collector/otelcol v0.162.0/go.mod h1:TOGem908Q9Inxy9f8mH1REWpcCeycnboAhPc0TkzATI= +go.opentelemetry.io/collector/otelcol/otelcoltest v0.162.0 h1:dqcM23JiwqlmJOXHGugotncho557U4w72pU/o/7y0JU= +go.opentelemetry.io/collector/otelcol/otelcoltest v0.162.0/go.mod h1:StLKN/8It0GFnIGy3fxjYzDjSxOTm79w3QuGcTb9+xg= +go.opentelemetry.io/collector/pdata v1.68.0 h1:4DSmBeDLemwDFJ8pY6Kfv4P1z4uVhLsvRhs1tzrvbCA= +go.opentelemetry.io/collector/pdata v1.68.0/go.mod h1:pSGMfds15rCzZZvg7gCVNVgrLVqE2+0kuCoAHcaAIAw= +go.opentelemetry.io/collector/pdata/pprofile v0.162.0 h1:NM9ylAma4aPnzzcchmLk8Ax79V2s1ZfO3CiSlL/jW9s= +go.opentelemetry.io/collector/pdata/pprofile v0.162.0/go.mod h1:2RrZ8FmRiw8RdwT85YE7o126vDlmVlvqZJe1BbrKhMs= +go.opentelemetry.io/collector/pdata/testdata v0.162.0 h1:zG4fXJKpAUq18IE3lw1I9MgLf2Dp7bS/DobC4lv1kjc= +go.opentelemetry.io/collector/pdata/testdata v0.162.0/go.mod h1:1RiZpM1tG2RLOCaT2Y6GsFDqTnyU3q8LcCQKcPch9R8= +go.opentelemetry.io/collector/pdata/xpdata v0.162.0 h1:Rvojx0v5KnEv5bZMdw02z0R+gTdMlYl1idvVnUx4W9Y= +go.opentelemetry.io/collector/pdata/xpdata v0.162.0/go.mod h1:WIvy4sI7e6nyH49Xf4mafs9QUyjLiw5TO52CrKcOVYk= +go.opentelemetry.io/collector/pipeline v1.68.0 h1:tWHA5pZUYwOPmta1a6C5VoJx2cAztPyHc2wptkuFhVg= +go.opentelemetry.io/collector/pipeline v1.68.0/go.mod h1:4S7iD/7hGDNXg4yPi+5es5WTvwo/Uie2OoHio79xokI= +go.opentelemetry.io/collector/pipeline/xpipeline v0.162.0 h1:WyHUpcXe4Q6pe417UgzDU5ZVi0YpHz7+s7w0KjfwZjQ= +go.opentelemetry.io/collector/pipeline/xpipeline v0.162.0/go.mod h1:qkDHIj0rxYawSOSPEsuQw03/xCQ/WBIitI2/20kwHp8= +go.opentelemetry.io/collector/processor v1.68.0 h1:LxCsYmkvhJ2CZXrYma06OY3gDBNAf6Gr2O+v7W6iJ20= +go.opentelemetry.io/collector/processor v1.68.0/go.mod h1:k3UfAJSt8lnB508ngNMNlvaeLAl9zubpLYEbT91KfMw= +go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.162.0 h1:uQO3rprlGDg1IaHtDcmg7RMoDbInYFO+FyLzd1u75ZE= +go.opentelemetry.io/collector/processor/memorylimiterprocessor v0.162.0/go.mod h1:ey6zHMqc/kMtPM2gcsdUYI9RwpbMeCABdyakyOeM/4o= +go.opentelemetry.io/collector/processor/processorhelper v0.162.0 h1:ljWeYqOqoITm2n/RkUj1GVLrMR1Y+lEp0fHlaEP6g50= +go.opentelemetry.io/collector/processor/processorhelper v0.162.0/go.mod h1:f4Xm+DOCBzG1LTva344kipzBlU3ZpUeEGsVVayW6qB4= +go.opentelemetry.io/collector/processor/processorhelper/xprocessorhelper v0.162.0 h1:MiWRCfi51OXXS46NSL5zr5zWAkEth1+x91ycXEIVgjA= +go.opentelemetry.io/collector/processor/processorhelper/xprocessorhelper v0.162.0/go.mod h1:bM9bkxiKul2j7toG+qpdWhG4cs5EKlqJZ+23eoyzYjE= +go.opentelemetry.io/collector/processor/processortest v0.162.0 h1:g0SIBikwHtef5iLcgA/LVM5MBTwKt++PTiV+N3FXt4w= +go.opentelemetry.io/collector/processor/processortest v0.162.0/go.mod h1:GP5NXAzjn6BYhRwlXeLV00honI5fGZXo9sEUyAK9khk= +go.opentelemetry.io/collector/processor/xprocessor v0.162.0 h1:QoufkdyslKxsyRa01feBG7RoeytyipWK2YN5ilAJgJc= +go.opentelemetry.io/collector/processor/xprocessor v0.162.0/go.mod h1:oZc1ehka+zY6Bl8uK2eIR/83I7ZyhtuCHzLauVzuCAw= +go.opentelemetry.io/collector/receiver v1.68.0 h1:JMzaLLb89KhqmT8GlKt9mCArjpa6UYh8a5fDgMz7NkI= +go.opentelemetry.io/collector/receiver v1.68.0/go.mod h1:AXQny//rP11HDDUTKIR0ZsiKgK9OGoXniAadRV2I7B0= +go.opentelemetry.io/collector/receiver/otlpreceiver v0.162.0 h1:hPeVt49TDisJPffIoCnOj3O/5y2UKEvclMdwDTRo5d0= +go.opentelemetry.io/collector/receiver/otlpreceiver v0.162.0/go.mod h1:LkKNflqdGzMEAF6hXQZKY9yFcecOTk5F8qp29+P4zQY= +go.opentelemetry.io/collector/receiver/receiverhelper v0.162.0 h1:70GfEpHM4gebjN9fpzDVm1oOTpH4TtzBcEFMMVZoOec= +go.opentelemetry.io/collector/receiver/receiverhelper v0.162.0/go.mod h1:TXRPj4zyC5RmJumd8utt4S8ILlsUg2efldVTPFM10jI= +go.opentelemetry.io/collector/receiver/receivertest v0.162.0 h1:OkbnK5Hk4LYHyWEaxs8KRxX453cDOGLyvJTD5jdmW0Y= +go.opentelemetry.io/collector/receiver/receivertest v0.162.0/go.mod h1:CuVbRp5y8s+PmwUFjwID4IxBE6qC32yifK1ZYIwK6sE= +go.opentelemetry.io/collector/receiver/xreceiver v0.162.0 h1:fnL7douhKynIGsxGmm3aRIXrdvK+HMQudasJNC6+Kvw= +go.opentelemetry.io/collector/receiver/xreceiver v0.162.0/go.mod h1:P46JupRLm9Y4fQ6129DWR1wKgLo3vTQShQ0IMYeXiGw= +go.opentelemetry.io/collector/service v0.162.0 h1:6wPK00EXxMBPKO+LxmwpnrWcTPDZhSyEeo/KQej70a8= +go.opentelemetry.io/collector/service v0.162.0/go.mod h1:tljDP2lnan/NNGzZDJk2zNEdTf3tVXWeV/ebAZPqxd0= +go.opentelemetry.io/collector/service/hostcapabilities v0.162.0 h1:14OsgkD/AC17Q3MpP4Qabgj3Y7nfXCaxDgmWbY3NwRY= +go.opentelemetry.io/collector/service/hostcapabilities v0.162.0/go.mod h1:/uISwTqaKJ+8KSMAmhyFLq3WklEVbsJyIVNv14MGOXo= +go.opentelemetry.io/collector/service/telemetry/telemetrytest v0.162.0 h1:6BKkAruvvmBCU75B19BGbVbpZAD5WMGKrMkzhd3J+NQ= +go.opentelemetry.io/collector/service/telemetry/telemetrytest v0.162.0/go.mod h1:DuqFmghwb/BruAEpK5WztZefBseOtcq/BTkR02EL6c8= go.opentelemetry.io/contrib/bridges/otelzap v0.20.0 h1:wgsHT2HLf1KEZtCkd6ZGynPdeIyFsCSKsHyDBW9vEJk= go.opentelemetry.io/contrib/bridges/otelzap v0.20.0/go.mod h1:NZCU/Hi3EdSS6LxcNJOO39Y5z95R9QY5iQ2Ym6IOFTU= go.opentelemetry.io/contrib/detectors/aws/ecs v1.45.0 h1:SIHXqRfox1Uz20yN0mtAidKU7SpMY1F08Kne52W5lIs= @@ -541,8 +545,8 @@ go.opentelemetry.io/contrib/detectors/gcp v1.45.0 h1:9jR0ZPRok9ryaOQ2Wx8rg5F7Aon go.opentelemetry.io/contrib/detectors/gcp v1.45.0/go.mod h1:VSme3o2fvSg5bVg0dRzyHaj4Z5EVhG+g2Fde6LKzmQA= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.70.0 h1:oECp5f+hN7nkwjU/8BxQ/q23bGPb8FIrD839owX222E= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.70.0/go.mod h1:DqEFwLumhzMBDQv9PcWbyoDxHI/4lAk6CM4nJBH39sc= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0 h1:LMuyCAyfalSjDyjdC65nK6N0zoTT63+E/u95X0JovZI= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.70.0/go.mod h1:085m8qbm4hgc8rZWGDEa4vmyyo2c3nPxUslYUKUIU04= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0 h1:LxwW/9ctSCv+QkE/cLR7M91ZIkXNMqJtEMi1vCw9U8s= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.72.0/go.mod h1:tOsftB4SslBwwErVEPaenU2RpThXWPIU8DoJHEC4dyw= go.opentelemetry.io/contrib/otelconf v0.25.0 h1:rbVGzm5OsVQhdnjqv2hvKuJhVTVHux9Ltra+N4FKy7M= go.opentelemetry.io/contrib/otelconf v0.25.0/go.mod h1:2Pf2b8pJDpLtymJ9Sv0z0ANPAxDpZ7QLezLdIKNusww= go.opentelemetry.io/contrib/propagators/autoprop v0.70.0 h1:yNNN177cOlxAJ5F8l1YKiD6rJk9GOUi/HnRQbI83DeQ= @@ -557,8 +561,8 @@ go.opentelemetry.io/contrib/propagators/ot v1.45.0 h1:BLFjHG1OjCEDaBk4os2+X1D6/u go.opentelemetry.io/contrib/propagators/ot v1.45.0/go.mod h1:mGksO7kOmOSsRGbVA28x7kHNL4YrH5uJoTNuws70NDU= go.opentelemetry.io/contrib/zpages v0.70.0 h1:uBcclHekIrCRLO4KZfXiebDcWB52QQXaHGgvhUJ1K5I= go.opentelemetry.io/contrib/zpages v0.70.0/go.mod h1:Nz9A1+68HVoJrk+cg92zJbcbHFAa+Jbl1uINwAlcK94= -go.opentelemetry.io/otel v1.46.0 h1:FHt5/CDyVxi/8IM1CH7VE/rRgq3kLHa2mSTVMO8AWyc= -go.opentelemetry.io/otel v1.46.0/go.mod h1:Gj3SEScelsNC45tp4nSxRYlS+f5iez7W8XPMCt905kE= +go.opentelemetry.io/otel v1.47.0 h1:j7ALJ/zgkS7Z6aeJW09p8VC9804bC+PpeTfCD4XPnOM= +go.opentelemetry.io/otel v1.47.0/go.mod h1:8wS9O2qfXrYrzp6hIF/HOYJJf/wIhFPhR2xLuP+iXQU= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.21.0 h1:WseeVYf5dJZTsyPiyW5L14k5qsSibqXAMTSiFEDiWr0= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.21.0/go.mod h1:SiLZnQS6Qk2eCpvr2CH/XMAOa64TWGXxEZJZCpD2Lmc= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.21.0 h1:fvNHGyo3CdRv/DQveXqhqBxnKTDyRaC5sMSQxilX/A0= @@ -581,24 +585,24 @@ go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.45.0 h1:dm9iyzn6tioYZt go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.45.0/go.mod h1:xAvxYjYK28qvt+yu4BYZ/zMmAjwMXINXD6JiMyeB8iI= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.45.0 h1:lsA/S1bxgdbyFGkTj+3meEdJ6ADVU7QoFstV6MXgE68= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.45.0/go.mod h1:L7u+MirGoB1bjeLH66+xDykF4RC8C3RN7lIFpBiewUo= -go.opentelemetry.io/otel/log v0.22.0 h1:5DBNnfvaJ6CVdkJ+Jle8Tzs50aSSv49TXGj9XRsEYw0= -go.opentelemetry.io/otel/log v0.22.0/go.mod h1:gzOt/R67vF2GniAqWu8Qv0SXy89f71muHcrkz76PCdc= +go.opentelemetry.io/otel/log v1.47.0 h1:cOTS1CcLbSQeZKanGJ+0JpF/+t4PELi3O3bbl2lqCcI= +go.opentelemetry.io/otel/log v1.47.0/go.mod h1:9byitSQ5pLC6PpqwGXjqdMKya6ZTswHRZh2vvXT33nw= go.opentelemetry.io/otel/log/logtest v0.21.0 h1:/Zr/0DoraAjiX91pZMn72uSDkd7hA+jn3CPU2y+2rWY= go.opentelemetry.io/otel/log/logtest v0.21.0/go.mod h1:dyswW/l7aXiiCAmbKlt+Eg2NUnN6p1YrHQPBiV7QrLU= -go.opentelemetry.io/otel/metric v1.46.0 h1:yBnkXvgV7AXFILZc5K6IZe/CBFF3OS7BJ8ov6/lj0K8= -go.opentelemetry.io/otel/metric v1.46.0/go.mod h1:iPmdWqifKUdzziPkvvzIJXITl56fQx2mGM/DHLB3/2o= -go.opentelemetry.io/otel/metric/x v0.68.0 h1:TA/cBT23D3MnxYPwHL7YFOdYGdx0A0v+s7Mzotpd1dU= -go.opentelemetry.io/otel/metric/x v0.68.0/go.mod h1:agudOmvWhwUTjgibWDzxD2PoWYnpw5Ht5jISYOD2Hd4= -go.opentelemetry.io/otel/sdk v1.46.0 h1:h5CNQQjEbuQXY/JfZtgt3i7HVFV3aHPO2OAwO2eTYPI= -go.opentelemetry.io/otel/sdk v1.46.0/go.mod h1:GAERFXFt5SYCEB+YiKUbMBeza6UaDH7GmGOZEfh2gSM= +go.opentelemetry.io/otel/metric v1.47.0 h1:4PptaldXx3Eat1XjMZ68pPJEs5wrhlemctZE9a3UdWY= +go.opentelemetry.io/otel/metric v1.47.0/go.mod h1:ADGSXxRrXM6bjbvLo535EstVFlPpPYZm4LBKixjDHwU= +go.opentelemetry.io/otel/metric/x v0.69.0 h1:DjRLr15H83v+hCW7JA9NoJvOkYTtmq5YoDRbe9deYpM= +go.opentelemetry.io/otel/metric/x v0.69.0/go.mod h1:uVvsMPMFFyj/HUQfrUnH3JjnOQ1dwFDorgFLRBasM0k= +go.opentelemetry.io/otel/sdk v1.47.0 h1:zWXEr4j2lFefG87TU6Yg8a7ngfohIKFZHKp0Hf5hC6I= +go.opentelemetry.io/otel/sdk v1.47.0/go.mod h1:VUc24kiOeoGsxG8G9ULx3fWKvB7jMhnGE8Oi607lgR0= go.opentelemetry.io/otel/sdk/log v0.21.0 h1:QsE7XSR0ktQdKmRKGnR+f1ObGF32WG+7MER/P9KgmYc= go.opentelemetry.io/otel/sdk/log v0.21.0/go.mod h1:m9mApjCoD2/1QuKCAptjv+BrG9WKOvQLVdNx+iBldTo= go.opentelemetry.io/otel/sdk/log/logtest v0.21.0 h1:X+JBBgKlswCGYsmgL0CnoUUtlE//VB345c84jYAYkdQ= go.opentelemetry.io/otel/sdk/log/logtest v0.21.0/go.mod h1:HD1575K8e6sIFBBDd5tZB3t9DlMytWXq9FuR+Y4rfjE= -go.opentelemetry.io/otel/sdk/metric v1.46.0 h1:0piZ26EG4RBfebb2jhDH6ERCYHoVWduc3kLgPCwSnSE= -go.opentelemetry.io/otel/sdk/metric v1.46.0/go.mod h1:I1PbKrdVc8Qu8HYVDNtqVIwLwjNrhsV/uFuxfwg8mO4= -go.opentelemetry.io/otel/trace v1.46.0 h1:OULy7ccdJnZtJ0UDYFOIGaCmiWzJ8Vi2G/Rsu60qs1c= -go.opentelemetry.io/otel/trace v1.46.0/go.mod h1:J7GAXweO77XSFkB/rmAqk9D6ihszhFjLU+d9WuUxDLI= +go.opentelemetry.io/otel/sdk/metric v1.47.0 h1:lfISg2j93VT6yqdk9OfUaZmw/GfcZqCCV3jdXtsPnKw= +go.opentelemetry.io/otel/sdk/metric v1.47.0/go.mod h1:ypLp+mW1Nt2x+Szt3b5/i1syodyts49lMOwxpDI3VGw= +go.opentelemetry.io/otel/trace v1.47.0 h1:JOjX/Oci8K94QHddo+bbfya/Ai/nf6/dt9ZfrFNWSrM= +go.opentelemetry.io/otel/trace v1.47.0/go.mod h1:jNaSLa2PZEYFG6fRjJABAu+bw4FS08uDmPg28lTghu0= go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk= go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E= go.opentelemetry.io/proto/slim/otlp v1.11.0 h1:zB37f+f99+y6UIZR4h7UpwbXd5kFNyip35U7GaJ/Jik= @@ -726,10 +730,10 @@ gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= -google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8 h1:0SXBqli5dnuCKMjI/X3FM226zEaEa0GUcSCJtN1vL2o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20261005182115-fad411399dd8/go.mod h1:OaIUM3+LpYcK2GXM4FTmhWoIq371Owdr+Cc7/BsYHHc= +google.golang.org/grpc v1.84.0 h1:soMyaPJ8pAak5PIQ0DGBUir0XRo2fRoMqhNWMLlLxO0= +google.golang.org/grpc v1.84.0/go.mod h1:ljCht0DrxQrXBDRTZp52Qxh3Ffk8CdYm2sj4O2QN2C0= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -742,20 +746,20 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.36.4 h1:RxrvqCL6vgH5/+UnTeu1IIFqYmGfy0hnyrod1rn35Oo= -k8s.io/api v0.36.4/go.mod h1:S2B3orCFBDhrgyWbLeuKcT2QdHIpQesBkCYSlWtwUOw= -k8s.io/apimachinery v0.36.4 h1:PT2UzkupGuAx/+xT5XjiMJ1WGpY3fn9/hdAvjweRet4= -k8s.io/apimachinery v0.36.4/go.mod h1:p2I2dipt7JHG+quVwQ1d02d28O4GdDi77RByQ13MTpk= -k8s.io/client-go v0.36.4 h1:MDvfDNvMSt0Br94SK8neviVlwL9qifw9B26hJCpD1K0= -k8s.io/client-go v0.36.4/go.mod h1:pNK4WKELbwlEDvtbE8l22lEZL5THYF61H5EealokZmA= +k8s.io/api v0.37.0 h1:Z//Vj9N7RA/yS2sDmxyeo7h+RR4zbUrd2vrd3Z0TbB4= +k8s.io/api v0.37.0/go.mod h1:LKXgcJWMc+f4OLbP5SFR8rulEg07zZhpi/zMULiBImk= +k8s.io/apimachinery v0.37.0 h1:Np2AbDtf8x6RDHiD8T9LbKJ9gaegeVNa8yNm5FuGKm0= +k8s.io/apimachinery v0.37.0/go.mod h1:RN3nhprFSCxOi5Selxd7oMTXOe/c+ZbcE7Im+TS2zkE= +k8s.io/client-go v0.37.0 h1:nsN31fy8wBySuZ+QRnKmrjRSQLOG2rvoGN0tKd12zhQ= +k8s.io/client-go v0.37.0/go.mod h1:FcGqw+Ll/gNQiq+nPGY1Oyt9y7SgDh1d3MW3RFDEbn0= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad h1:oXImqH8mQNk7PmvzKhmN3ddJoY6OnyM225MXwGHPm0A= k8s.io/kube-openapi v0.0.0-20260721132016-d427ff9ee9ad/go.mod h1:0/mqHCVhlumdJ3BhCfnjSZQE037nAhNodh1/hK0T8/I= k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 h1:jVkFFVfXdXP74B/zbO3hM3hpSFD0xvhQ5U686DPurkE= k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3/go.mod h1:M2s5JB1lIYP3jzZdorPLHXIPJzt9vv2muW5a6L9DtNM= -sigs.k8s.io/controller-runtime v0.24.1 h1:miPEwrmirImAvgME1L9qebGHrOnGJoVmVdtOU9fRfo4= -sigs.k8s.io/controller-runtime v0.24.1/go.mod h1:vFkfY5fGt5xAC/sKb8IBFKgWPNKG9OUG29dR8Y2wImw= +sigs.k8s.io/controller-runtime v0.25.1 h1:BKgU9OeE8xv8EbbM8cY0NVzTQs35rokkdq1jh12fMb4= +sigs.k8s.io/controller-runtime v0.25.1/go.mod h1:4QqLdT6z/L6Olj8JJCtvztid4/fnIiYsfaTFScegctc= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= diff --git a/projects/tools/openshell-exporter/processor/openshellprocessor/config.go b/projects/tools/openshell-exporter/processor/openshellprocessor/config.go index 19bbe1f7..a9e4490d 100644 --- a/projects/tools/openshell-exporter/processor/openshellprocessor/config.go +++ b/projects/tools/openshell-exporter/processor/openshellprocessor/config.go @@ -25,6 +25,8 @@ type ValidationConfig struct { var supportedSourceProfiles = []string{ "ocsf.file", + "ocsf.gateway", + "ocsf.supervisor", "ocsf.forwarded", "openshell.log", "openshell.log.forwarded", diff --git a/projects/tools/openshell-exporter/processor/openshellprocessor/context.go b/projects/tools/openshell-exporter/processor/openshellprocessor/context.go new file mode 100644 index 00000000..b9b170a2 --- /dev/null +++ b/projects/tools/openshell-exporter/processor/openshellprocessor/context.go @@ -0,0 +1,71 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. +// SPDX-License-Identifier: Apache-2.0 + +package openshellprocessor + +// These projections are source facts, not decisions inferred from messages or +// numeric codes. Read the redacted original so renamed fields cannot bypass +// key-based redaction. Unknown and malformed values remain in original. +var ocsfContextFields = []struct { + group, name string + path []string + number bool +}{ + {"actor", "process_name", []string{"actor", "process", "name"}, false}, + {"actor", "process_pid", []string{"actor", "process", "pid"}, true}, + {"actor", "process_uid", []string{"actor", "process", "uid"}, false}, + {"actor", "user_name", []string{"actor", "user", "name"}, false}, + {"actor", "user_uid", []string{"actor", "user", "uid"}, false}, + {"action", "activity_id", []string{"activity_id"}, true}, + {"action", "activity_name", []string{"activity_name"}, false}, + {"action", "api_operation", []string{"api", "operation"}, false}, + {"target", "domain", []string{"dst_endpoint", "domain"}, false}, + {"target", "ip", []string{"dst_endpoint", "ip"}, false}, + {"target", "port", []string{"dst_endpoint", "port"}, true}, + {"target", "file_name", []string{"file", "name"}, false}, + {"target", "file_path", []string{"file", "path"}, false}, + {"target", "file_uid", []string{"file", "uid"}, false}, + {"target", "api_service", []string{"api", "service", "name"}, false}, + {"outcome", "status_id", []string{"status_id"}, true}, + {"outcome", "status", []string{"status"}, false}, + {"outcome", "status_detail", []string{"status_detail"}, false}, + {"outcome", "action_id", []string{"action_id"}, true}, + {"outcome", "action", []string{"action"}, false}, + {"outcome", "disposition_id", []string{"disposition_id"}, true}, + {"outcome", "disposition", []string{"disposition"}, false}, + {"policy", "rule_name", []string{"firewall_rule", "name"}, false}, + {"policy", "rule_type", []string{"firewall_rule", "type"}, false}, + {"policy", "rule_uid", []string{"firewall_rule", "uid"}, false}, +} + +func addOCSFContext(envelope map[string]any, original any) { + for _, field := range ocsfContextFields { + value := original + for _, segment := range field.path { + object, ok := value.(map[string]any) + if !ok { + value = nil + break + } + value = object[segment] + } + if field.number { + integer, ok := exactInteger(value) + if !ok || integer < 0 { + continue + } + value = integer + } else { + text, ok := value.(string) + if !ok || text == "" { + continue + } + } + group, ok := envelope[field.group].(map[string]any) + if !ok { + group = map[string]any{} + envelope[field.group] = group + } + group[field.name] = value + } +} diff --git a/projects/tools/openshell-exporter/processor/openshellprocessor/context_test.go b/projects/tools/openshell-exporter/processor/openshellprocessor/context_test.go new file mode 100644 index 00000000..b43a0ccb --- /dev/null +++ b/projects/tools/openshell-exporter/processor/openshellprocessor/context_test.go @@ -0,0 +1,126 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. +// SPDX-License-Identifier: Apache-2.0 + +package openshellprocessor + +import ( + "reflect" + "strings" + "testing" + + "go.uber.org/zap" +) + +func TestSearchableOCSFContextPreservesFactsAndPrivacy(t *testing.T) { + for _, kind := range []string{"ocsf.file", "ocsf.forwarded", "ocsf.gateway", "ocsf.supervisor"} { + t.Run(kind, func(t *testing.T) { + input := validOCSF() + input["actor"] = map[string]any{"process": map[string]any{"name": "agent", "pid": int64(42), "uid": "proc-1", "cmd_line": "authorization=Bearer private-value"}, "user": map[string]any{"name": "operator", "uid": "user-1"}} + input["api"] = map[string]any{"operation": "Connect", "service": map[string]any{"name": "inference"}} + input["dst_endpoint"] = map[string]any{"domain": "private-host", "ip": "192.0.2.1", "port": int64(443)} + input["file"] = map[string]any{"name": "audit.json", "path": "/audit.json", "uid": "file-1"} + input["activity_name"] = "Open" + input["status_id"], input["status"], input["status_detail"] = int64(2), "Failure", "source reason" + input["action_id"], input["action"] = int64(2), "Denied" + input["disposition_id"], input["disposition"] = int64(2), "Blocked" + input["firewall_rule"] = map[string]any{"name": "network-egress", "type": "policy", "uid": "rule-1"} + input["future_field"] = map[string]any{"keep": true, "password": "private-value"} + cfg := createDefaultConfig().(*Config) + cfg.Redaction.Keys = append(cfg.Redaction.Keys, "domain") + p, err := newProcessor(cfg, zap.NewNop()) + if err != nil { + t.Fatal(err) + } + logs := testLogs(t, input) + record := onlyRecord(logs) + record.Attributes().PutStr("openshell.acquisition.kind", kind) + beforeID := stableID(cfg, record, kind, record.Body().AsRaw()) + if _, err := p.processLogs(t.Context(), logs); err != nil { + t.Fatal(err) + } + got := record.Body().Map().AsRaw() + want := map[string]any{ + "actor": map[string]any{"process_name": "agent", "process_pid": int64(42), "process_uid": "proc-1", "user_name": "operator", "user_uid": "user-1"}, + "action": map[string]any{"activity_id": input["activity_id"], "activity_name": "Open", "api_operation": "Connect"}, + "target": map[string]any{"domain": redacted, "ip": "192.0.2.1", "port": int64(443), "file_name": "audit.json", "file_path": "/audit.json", "file_uid": "file-1", "api_service": "inference"}, + "outcome": map[string]any{"status_id": int64(2), "status": "Failure", "status_detail": "source reason", "action_id": int64(2), "action": "Denied", "disposition_id": int64(2), "disposition": "Blocked"}, + "policy": map[string]any{"rule_name": "network-egress", "rule_type": "policy", "rule_uid": "rule-1"}, + } + for key, expected := range want { + if !reflect.DeepEqual(got[key], expected) { + t.Fatalf("%s=%#v, want %#v", key, got[key], expected) + } + } + original := got["original"].(map[string]any) + if !reflect.DeepEqual(original["future_field"], map[string]any{"keep": true, "password": redacted}) { + t.Fatalf("unknown source changed: %#v", original) + } + if original["actor"].(map[string]any)["process"].(map[string]any)["cmd_line"] == input["actor"].(map[string]any)["process"].(map[string]any)["cmd_line"] { + t.Fatal("command line not redacted") + } + id, _ := record.Attributes().Get("event.id") + if id.Str() != beforeID { + t.Fatal("projection changed identity") + } + }) + } +} + +func TestOCSFContextDoesNotInventOrCoerceFacts(t *testing.T) { + for _, input := range []any{ + nil, "CONNECT denied", map[string]any{"message": "denied by policy"}, + map[string]any{"actor": []any{"agent"}, "dst_endpoint": map[string]any{"domain": true, "port": "443"}, "status_id": 1.5, "action": map[string]any{"value": "Denied"}, "firewall_rule": false}, + map[string]any{"actor": map[string]any{"process": map[string]any{"pid": int64(-1), "name": ""}}, "file": map[string]any{"path": []any{"/secret"}}}, + } { + got := map[string]any{} + addOCSFContext(got, input) + if len(got) != 0 { + t.Fatalf("invented context for %#v: %#v", input, got) + } + } + logs := testLogs(t, map[string]any{"action": "Denied", "status": "Failure"}) + onlyRecord(logs).Attributes().PutStr("openshell.acquisition.kind", "sandbox.lifecycle") + p, err := newProcessor(createDefaultConfig().(*Config), zap.NewNop()) + if err != nil { + t.Fatal(err) + } + if _, err = p.processLogs(t.Context(), logs); err != nil { + t.Fatal(err) + } + if _, ok := onlyRecord(logs).Body().Map().Get("outcome"); ok { + t.Fatal("OCSF semantics applied to another source") + } +} + +func TestRelayCorrelationAliasesAndPrecedence(t *testing.T) { + for _, sessionKey := range []string{"session.id", "nemo_relay.session.instance_id", "nemo_relay.session_id"} { + input := map[string]any{"unmapped": map[string]any{sessionKey: "session-1", "nemo_relay.request_id": "request-1", "nemo_relay.tool_call_id": "tool-1"}} + got := correlations(input, nil) + for key, want := range map[string]string{"agent_session_id": "session-1", "request_id": "request-1", "tool_call_id": "tool-1"} { + if got[key] != want { + t.Fatalf("%s: %s=%#v", sessionKey, key, got[key]) + } + } + } + got := correlations(map[string]any{"agent.session.id": "canonical", "nemo_relay.session_id": "alias", "unmapped": map[string]any{"agent.session.id": "nested"}}, nil) + if got["agent_session_id"] != "canonical" { + t.Fatalf("precedence: %#v", got) + } + got = correlations(map[string]any{"nemo_relay.session_id": []any{"invalid"}, "nemo_relay.request_id": map[string]any{"invalid": true}}, nil) + if len(got) != 0 { + t.Fatalf("non-scalar identifiers: %#v", got) + } + logs := testLogs(t, map[string]any{"nemo_relay.session_id": "private-session"}) + cfg := createDefaultConfig().(*Config) + cfg.Redaction.Patterns = append(cfg.Redaction.Patterns, "private-session") + p, err := newProcessor(cfg, zap.NewNop()) + if err != nil { + t.Fatal(err) + } + if _, err = p.processLogs(t.Context(), logs); err != nil { + t.Fatal(err) + } + if strings.Contains(onlyRecord(logs).Body().AsString(), "private-session") { + t.Fatal("alias bypassed redaction") + } +} diff --git a/projects/tools/openshell-exporter/processor/openshellprocessor/envelope.go b/projects/tools/openshell-exporter/processor/openshellprocessor/envelope.go index 65f7ed85..85b61b0a 100644 --- a/projects/tools/openshell-exporter/processor/openshellprocessor/envelope.go +++ b/projects/tools/openshell-exporter/processor/openshellprocessor/envelope.go @@ -145,6 +145,9 @@ func buildEnvelope( "correlation": correlation, "original": original, } + if isOCSFEvidence(kind) { + addOCSFContext(envelope, original) + } if attributes, ok := sourceAttributes.(map[string]any); ok && len(attributes) > 0 { envelope["source_attributes"] = attributes } @@ -232,7 +235,7 @@ func (p *processorImpl) setCloudEventAttributes( func eventType(kind string, original any) string { if isOCSFEvidence(kind) { if object, ok := original.(map[string]any); ok { - if classUID, ok := exactInteger(object["class_uid"]); ok && classUID > 0 { + if classUID, ok := exactInteger(object["class_uid"]); ok && classUID >= 0 { return "com.nvidia.openshell.ocsf." + strconv.FormatInt(classUID, 10) + ".v1" @@ -317,10 +320,10 @@ func correlations(original any, configured []string) map[string]any { {name: "span_id", aliases: []string{"span_id", "span.id"}}, {name: "parent_span_id", aliases: []string{"parent_span_id", "parent.span.id"}}, {name: "transaction_id", aliases: []string{"transaction_id", "transaction.id"}}, - {name: "request_id", aliases: []string{"request_id", "request.id", "gen_ai.request.id"}}, + {name: "request_id", aliases: []string{"request_id", "request.id", "gen_ai.request.id", "nemo_relay.request_id"}}, {name: "session_id", aliases: []string{"session_id", "session.id", "gen_ai.conversation.id"}}, - {name: "agent_session_id", aliases: []string{"agent_session_id", "agent.session.id"}}, - {name: "tool_call_id", aliases: []string{"tool_call_id", "tool.call.id", "gen_ai.tool.call.id"}}, + {name: "agent_session_id", aliases: []string{"agent_session_id", "agent.session.id", "session.id", "nemo_relay.session.instance_id", "nemo_relay.session_id"}}, + {name: "tool_call_id", aliases: []string{"tool_call_id", "tool.call.id", "gen_ai.tool.call.id", "nemo_relay.tool_call_id"}}, {name: "correlation_id", aliases: []string{"correlation_id", "correlation.id"}}, {name: "policy_chunk_id", aliases: []string{"policy_chunk_id", "policy.chunk.id"}}, {name: "operation_id", aliases: []string{"operation_id", "operation.id"}}, @@ -457,7 +460,7 @@ func lookupPath(root any, path string) (any, bool) { } func sandboxIDFrom(original any, fallback string) string { - for _, path := range []string{"sandbox.id", "sandbox_id", "unmapped.sandbox_id"} { + for _, path := range []string{"container.uid", "sandbox.id", "sandbox_id", "unmapped.sandbox_id"} { if value, ok := lookupPath(original, path); ok && fmt.Sprint(value) != "" { return fmt.Sprint(value) } @@ -469,7 +472,7 @@ func sandboxIDFrom(original any, fallback string) string { } func isCheckpointedFile(kind string) bool { - return kind == "ocsf.file" || + return kind == "ocsf.gateway" || kind == "ocsf.supervisor" || kind == "ocsf.file" || kind == "sandbox.file_log" || kind == "nemo_relay.log" } @@ -483,7 +486,7 @@ func isForwardedFile(kind string) bool { } func isOCSFEvidence(kind string) bool { - return kind == "ocsf.file" || kind == "ocsf.forwarded" + return kind == "ocsf.gateway" || kind == "ocsf.supervisor" || kind == "ocsf.file" || kind == "ocsf.forwarded" } func isKubernetesContext(kind string) bool { @@ -533,6 +536,9 @@ func acquisitionCoverage(kind string, attributes pcommon.Map) map[string]any { coverage["known_limitations"] = []any{ "durability_requires_persistent_upstream_file_and_checkpoint_storage", } + if kind == "ocsf.gateway" || kind == "ocsf.supervisor" { + coverage["known_limitations"] = append(coverage["known_limitations"].([]any), "upstream_best_effort_queue_and_retention") + } if isForwardedFile(kind) { coverage["known_limitations"] = []any{ "forwarder_owns_file_checkpoint_and_retry_state", @@ -581,8 +587,8 @@ func acquisitionCoverage(kind string, attributes pcommon.Map) map[string]any { func sourceProfile(kind string) string { switch { - case kind == "ocsf.file": - return "ocsf.file" + case kind == "ocsf.file" || kind == "ocsf.gateway" || kind == "ocsf.supervisor": + return kind case kind == "ocsf.forwarded": return "ocsf.forwarded" case kind == "openshell.log.forwarded": diff --git a/projects/tools/openshell-exporter/processor/openshellprocessor/factory.go b/projects/tools/openshell-exporter/processor/openshellprocessor/factory.go index 6d39ca19..81573c49 100644 --- a/projects/tools/openshell-exporter/processor/openshellprocessor/factory.go +++ b/projects/tools/openshell-exporter/processor/openshellprocessor/factory.go @@ -5,9 +5,12 @@ package openshellprocessor import ( "context" + "errors" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumererror" + "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/processor" "go.opentelemetry.io/collector/processor/processorhelper" ) @@ -72,7 +75,7 @@ func createLogsProcessor( if err != nil { return nil, err } - return processorhelper.NewLogs( + inner, err := processorhelper.NewLogs( ctx, settings, cfg, @@ -81,4 +84,32 @@ func createLogsProcessor( processorhelper.WithStart(implementation.start), processorhelper.WithCapabilities(consumer.Capabilities{MutatesData: true}), ) + if err != nil { + return nil, err + } + return &retrySafeProcessor{Logs: inner}, nil +} + +// File receivers can retry the same input after a downstream enqueue failure. +// Keep their source intact: re-normalizing an already redacted envelope changes +// both validation and identity. The inner pipeline owns each attempt's copy. +type retrySafeProcessor struct { + processor.Logs +} + +func (*retrySafeProcessor) Capabilities() consumer.Capabilities { + return consumer.Capabilities{MutatesData: false} +} + +func (p *retrySafeProcessor) ConsumeLogs(ctx context.Context, logs plog.Logs) error { + attempt := plog.NewLogs() + logs.CopyTo(attempt) + err := p.Logs.ConsumeLogs(ctx, attempt) + var partial consumererror.Logs + if errors.As(err, &partial) { + // Partial failures carry normalized data. Retry the original source batch + // instead; accepted records may repeat with the same source/ID. + return consumererror.NewLogs(err, logs) + } + return err } diff --git a/projects/tools/openshell-exporter/processor/openshellprocessor/metrics_test.go b/projects/tools/openshell-exporter/processor/openshellprocessor/metrics_test.go index e471ba48..5be87359 100644 --- a/projects/tools/openshell-exporter/processor/openshellprocessor/metrics_test.go +++ b/projects/tools/openshell-exporter/processor/openshellprocessor/metrics_test.go @@ -28,6 +28,7 @@ func TestSourceCapabilityMetricsDescribeEveryBoundedLane(t *testing.T) { collected := collectInt64Metrics(t, reader) wantSources := []string{ "driver_otlp", + "gateway_ocsf", "gateway_otlp", "kubernetes_context", "ocsf_files", @@ -35,6 +36,7 @@ func TestSourceCapabilityMetricsDescribeEveryBoundedLane(t *testing.T) { "policy_reconciliation", "relay_files", "relay_otlp", + "supervisor_ocsf", "watch_events", "watchsandbox", } @@ -194,3 +196,18 @@ func equalStrings(got, want []string) bool { } return true } + +func TestNewOCSFSourcesBecomeObservedIndependently(t *testing.T) { + reader := sdkmetric.NewManualReader() + provider := sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)) + metrics, err := newProcessorMetrics(provider) + if err != nil { + t.Fatal(err) + } + metrics.capabilitiesConfigured(context.Background(), []string{"ocsf.gateway", "ocsf.supervisor"}, sourceCapabilitySummaries([]string{"ocsf.gateway", "ocsf.supervisor"})) + metrics.observeSource(context.Background(), "ocsf.gateway") + values := collectInt64Metrics(t, reader) + assertMetricPointValue(t, values["openshell.exporter.source.observed"], "gateway_ocsf", 1) + assertMetricPointValue(t, values["openshell.exporter.source.observed"], "supervisor_ocsf", 0) + assertMetricPointValue(t, values["openshell.exporter.source.health_class"], "gateway_ocsf", sourceHealthClassHealthy) +} diff --git a/projects/tools/openshell-exporter/processor/openshellprocessor/processor.go b/projects/tools/openshell-exporter/processor/openshellprocessor/processor.go index 2d6f081b..b89fca07 100644 --- a/projects/tools/openshell-exporter/processor/openshellprocessor/processor.go +++ b/projects/tools/openshell-exporter/processor/openshellprocessor/processor.go @@ -77,7 +77,6 @@ func (p *processorImpl) start(ctx context.Context, _ component.Host) error { } var unavailableSourceCapabilities = []string{ - "gateway_structured_ocsf_export", "watch_events", } @@ -148,6 +147,11 @@ func (p *processorImpl) normalize(ctx context.Context, record plog.LogRecord) { redactedSourceAttributes, attributeRedactionCount := p.redactRaw(sourceAttributes) redactionCount := bodyRedactionCount + attributeRedactionCount correlation := correlations(original, p.config.CorrelationFields) + if isOCSFEvidence(kind) { + if value, ok := lookupPath(original, "metadata.uid"); ok { + correlation["ocsf_event_uid"] = value + } + } mergeMissingCorrelations(correlation, correlations(sourceAttributes, p.config.CorrelationFields)) envelope := buildEnvelope( p.config, diff --git a/projects/tools/openshell-exporter/processor/openshellprocessor/processor_test.go b/projects/tools/openshell-exporter/processor/openshellprocessor/processor_test.go index e83f88f2..24267aa7 100644 --- a/projects/tools/openshell-exporter/processor/openshellprocessor/processor_test.go +++ b/projects/tools/openshell-exporter/processor/openshellprocessor/processor_test.go @@ -5,11 +5,17 @@ package openshellprocessor import ( "context" + "errors" + "fmt" + "reflect" "strings" "testing" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/processor/processortest" "go.uber.org/zap" ) @@ -28,7 +34,7 @@ func TestConfigRejectsUnknownOrEmptySourceProfiles(t *testing.T) { func TestSourceCapabilitySetsDistinguishDisabledAndUnobserved(t *testing.T) { disabled, declaredUnobserved := sourceCapabilitySets([]string{"openshell.log"}) if strings.Join(disabled, ",") != - "ocsf.file,ocsf.forwarded,openshell.log.forwarded,watchsandbox,policy.reconciliation,kubernetes.context,nemo_relay.log,nemo_relay.trace,openshell.trace" { + "ocsf.file,ocsf.gateway,ocsf.supervisor,ocsf.forwarded,openshell.log.forwarded,watchsandbox,policy.reconciliation,kubernetes.context,nemo_relay.log,nemo_relay.trace,openshell.trace" { t.Fatalf("disabled profiles=%v", disabled) } if len(declaredUnobserved) != 0 { @@ -45,9 +51,9 @@ func TestSourceCapabilitySetsDistinguishDisabledAndUnobserved(t *testing.T) { } } -func TestUnavailableCapabilitiesIncludeUpstreamGatewayOCSFGate(t *testing.T) { +func TestUnavailableCapabilitiesExcludeAvailableGatewayOCSF(t *testing.T) { if strings.Join(unavailableSourceCapabilities, ",") != - "gateway_structured_ocsf_export,watch_events" { + "watch_events" { t.Fatalf("unavailable capabilities=%v", unavailableSourceCapabilities) } } @@ -613,7 +619,12 @@ func FuzzMalformedEvidenceIsRetained(f *testing.F) { } func BenchmarkOCSFNormalization(b *testing.B) { - processor, err := newProcessor(createDefaultConfig().(*Config), zap.NewNop()) + sink, err := consumer.NewLogs(func(context.Context, plog.Logs) error { return nil }) + if err != nil { + b.Fatal(err) + } + factory := NewFactory() + processor, err := factory.CreateLogs(context.Background(), processortest.NewNopSettings(factory.Type()), factory.CreateDefaultConfig(), sink) if err != nil { b.Fatal(err) } @@ -627,7 +638,7 @@ func BenchmarkOCSFNormalization(b *testing.B) { record.Attributes().PutStr("openshell.acquisition.kind", "ocsf.file") record.Attributes().PutStr("log.file.path", "/var/log/openshell-ocsf.jsonl") record.Attributes().PutInt("log.file.record_offset", 128) - if _, err := processor.processLogs(context.Background(), logs); err != nil { + if err := processor.ConsumeLogs(context.Background(), logs); err != nil { b.Fatal(err) } } @@ -714,3 +725,170 @@ func TestCanonicalCorrelationContextAddsTrustedIdentity(t *testing.T) { t.Fatal("source-compatible agent_session_id was removed") } } + +func TestBaseEventValidationAndRouting(t *testing.T) { + for _, kind := range []string{"ocsf.file", "ocsf.forwarded", "ocsf.gateway", "ocsf.supervisor"} { + event := validOCSF() + event["class_uid"], event["category_uid"], event["activity_id"], event["type_uid"] = 0, 0, 99, 99 + if result := validateSource(kind, event); result.Status != validationValid { + t.Fatalf("%s: %v", kind, result) + } + if got := eventType(kind, event); got != "com.nvidia.openshell.ocsf.0.v1" { + t.Fatal(got) + } + for _, invalid := range []any{-1, 0.5, "0", nil} { + event["class_uid"] = invalid + if result := validateSource(kind, event); result.Status != validationInvalid { + t.Fatalf("accepted class %v", invalid) + } + } + event["class_uid"], event["category_uid"] = 4001, 0 + if result := validateSource(kind, event); result.Status != validationInvalid { + t.Fatal("accepted zero category for non-base event") + } + event["class_uid"], event["category_uid"] = 0, 4 + if result := validateSource(kind, event); result.Status != validationInvalid { + t.Fatal("accepted base class with non-base category") + } + } +} + +func TestOCSFNativeIdentityKeepsGatewayAndSandboxSeparate(t *testing.T) { + event := validOCSF() + event["metadata"].(map[string]any)["uid"] = "native-event-123" + delete(event, "unmapped") + delete(event, "sandbox_id") + delete(event, "unmapped") + delete(event, "sandbox_id") + event["device"] = map[string]any{"uid": "gateway-prod", "hostname": "replica-2"} + if got := sandboxIDFrom(event, "unknown"); got != "unknown" { + t.Fatalf("gateway used as sandbox: %s", got) + } + event["container"] = map[string]any{"uid": "sandbox-123"} + if got := sandboxIDFrom(event, "unknown"); got != "sandbox-123" { + t.Fatalf("sandbox=%s", got) + } + config := createDefaultConfig().(*Config) + processor, err := newProcessor(config, zap.NewNop()) + if err != nil { + t.Fatal(err) + } + logs := plog.NewLogs() + recordBody := logs.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() + if err := recordBody.Body().FromRaw(event); err != nil { + t.Fatal(err) + } + record := logs.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().At(0) + record.Attributes().PutStr("openshell.acquisition.kind", "ocsf.gateway") + before := stableID(config, record, "ocsf.gateway", record.Body().AsRaw()) + if _, err := processor.processLogs(context.Background(), logs); err != nil { + t.Fatal(err) + } + id, _ := record.Attributes().Get("event.id") + if id.Str() != before { + t.Fatal("native uid changed the identity contract") + } + body := record.Body().AsRaw().(map[string]any) + if got := body["correlation"].(map[string]any)["ocsf_event_uid"]; got != "native-event-123" { + t.Fatalf("native uid=%v", got) + } + if got := body["openshell"].(map[string]any)["sandbox_id"]; got != "sandbox-123" { + t.Fatalf("envelope sandbox=%v", got) + } +} + +func TestNonOCSFMetadataUIDIsNotAnOCSFEventID(t *testing.T) { + config := createDefaultConfig().(*Config) + p, err := newProcessor(config, zap.NewNop()) + if err != nil { + t.Fatal(err) + } + logs := plog.NewLogs() + record := logs.ResourceLogs().AppendEmpty().ScopeLogs().AppendEmpty().LogRecords().AppendEmpty() + record.Attributes().PutStr("openshell.acquisition.kind", "kubernetes.context") + if err := record.Body().FromRaw(map[string]any{"metadata": map[string]any{"uid": "pod-uid"}}); err != nil { + t.Fatal(err) + } + if _, err := p.processLogs(context.Background(), logs); err != nil { + t.Fatal(err) + } + body := record.Body().AsRaw().(map[string]any) + if _, ok := body["correlation"].(map[string]any)["ocsf_event_uid"]; ok { + t.Fatal("Kubernetes object UID mislabeled as OCSF event identity") + } +} + +func TestReceiverRetryPreservesSourceAndNormalizedIdentity(t *testing.T) { + for _, partial := range []bool{false, true} { + t.Run(fmt.Sprintf("partial=%t", partial), func(t *testing.T) { + var attempts []plog.Logs + sink, err := consumer.NewLogs(func(_ context.Context, logs plog.Logs) error { + retained := plog.NewLogs() + logs.CopyTo(retained) + attempts = append(attempts, retained) + if len(attempts) == 1 { + if partial { + return consumererror.NewLogs(errors.New("queue storage full"), logs) + } + return errors.New("queue storage full") + } + return nil + }) + if err != nil { + t.Fatal(err) + } + factory := NewFactory() + p, err := factory.CreateLogs(t.Context(), processortest.NewNopSettings(factory.Type()), factory.CreateDefaultConfig(), sink) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = p.Shutdown(context.Background()) }) + if p.Capabilities().MutatesData { + t.Fatal("retry-safe processor declares source mutation") + } + input := validOCSF() + input["authorization"] = "Bearer test-only-secret" + input["container"] = map[string]any{"uid": "sandbox-1"} + input["actor"] = map[string]any{"process": map[string]any{"name": "agent", "pid": int64(42)}} + input["action"] = "Denied" + input["nemo_relay.session_id"] = "session-1" + logs := testLogs(t, input) + onlyRecord(logs).SetObservedTimestamp(pcommon.Timestamp(123456789)) + onlyRecord(logs).Attributes().PutInt("log.file.record_offset", 128) + original := plog.NewLogs() + logs.CopyTo(original) + // Also exercise the Collector's fanout contract for non-mutating consumers. + logs.MarkReadOnly() + err = p.ConsumeLogs(t.Context(), logs) + if err == nil { + t.Fatal("downstream failure was swallowed") + } + var failed consumererror.Logs + if errors.As(err, &failed) { + logs = failed.Data() + } + if !reflect.DeepEqual(onlyRecord(original).Body().AsRaw(), onlyRecord(logs).Body().AsRaw()) || + !reflect.DeepEqual(onlyRecord(original).Attributes().AsRaw(), onlyRecord(logs).Attributes().AsRaw()) { + t.Fatal("receiver retry source changed") + } + if err := p.ConsumeLogs(t.Context(), logs); err != nil { + t.Fatal(err) + } + if len(attempts) != 2 { + t.Fatalf("attempts=%d, want 2", len(attempts)) + } + if !reflect.DeepEqual(onlyRecord(attempts[0]).Body().AsRaw(), onlyRecord(attempts[1]).Body().AsRaw()) || + !reflect.DeepEqual(onlyRecord(attempts[0]).Attributes().AsRaw(), onlyRecord(attempts[1]).Attributes().AsRaw()) { + t.Fatal("retry changed normalized evidence or identity") + } + id, _ := onlyRecord(attempts[1]).Attributes().Get("cloudevents.id") + if id.Str() == "" { + t.Fatal("retry lost identity") + } + encoded, err := (&plog.JSONMarshaler{}).MarshalLogs(attempts[1]) + if err != nil || strings.Contains(string(encoded), "test-only-secret") { + t.Fatalf("retry failed privacy filtering: %v", err) + } + }) + } +} diff --git a/projects/tools/openshell-exporter/processor/openshellprocessor/source_capability.go b/projects/tools/openshell-exporter/processor/openshellprocessor/source_capability.go index b9bdf135..0bd97740 100644 --- a/projects/tools/openshell-exporter/processor/openshellprocessor/source_capability.go +++ b/projects/tools/openshell-exporter/processor/openshellprocessor/source_capability.go @@ -37,6 +37,16 @@ type sourceCapabilityDefinition struct { } var sourceCapabilityDefinitions = []sourceCapabilityDefinition{ + { + source: "gateway_ocsf", profiles: []string{"ocsf.gateway"}, + durability: "checkpointed_file", + limitationCode: "upstream_best_effort_monitor_gateway_drops", available: true, + }, + { + source: "supervisor_ocsf", profiles: []string{"ocsf.supervisor"}, + durability: "checkpointed_file", + limitationCode: "upstream_best_effort_runtime_retention", available: true, + }, { source: "ocsf_files", profiles: []string{"ocsf.file", "ocsf.forwarded"}, durability: "checkpointed_file", @@ -121,6 +131,10 @@ func sourceCapabilitySummaries(enabledProfiles []string) []sourceCapabilitySumma func sourceCapabilityLane(kind string) string { switch sourceProfile(kind) { + case "ocsf.gateway": + return "gateway_ocsf" + case "ocsf.supervisor": + return "supervisor_ocsf" case "ocsf.file", "ocsf.forwarded": return "ocsf_files" case "openshell.log", "openshell.log.forwarded": @@ -143,7 +157,7 @@ func sourceCapabilityLane(kind string) string { // source records remain exportable, but their metric label fails closed. func boundedMetricSource(kind string) string { switch kind { - case "ocsf.file", + case "ocsf.gateway", "ocsf.supervisor", "ocsf.file", "ocsf.forwarded", "sandbox.lifecycle", "gateway.log", diff --git a/projects/tools/openshell-exporter/processor/openshellprocessor/source_capability_test.go b/projects/tools/openshell-exporter/processor/openshellprocessor/source_capability_test.go index 78cbd6bb..f300df6e 100644 --- a/projects/tools/openshell-exporter/processor/openshellprocessor/source_capability_test.go +++ b/projects/tools/openshell-exporter/processor/openshellprocessor/source_capability_test.go @@ -20,6 +20,8 @@ func TestSourceCapabilitySummariesCoverEveryProfile(t *testing.T) { profile string sources []string }{ + {profile: "ocsf.gateway", sources: []string{"gateway_ocsf"}}, + {profile: "ocsf.supervisor", sources: []string{"supervisor_ocsf"}}, {profile: "ocsf.file", sources: []string{"ocsf_files"}}, {profile: "ocsf.forwarded", sources: []string{"ocsf_files"}}, {profile: "openshell.log", sources: []string{"operational_files"}}, @@ -81,6 +83,8 @@ func TestSourceCapabilityKindMappingAndGapHealthAreBounded(t *testing.T) { source string gap bool }{ + {kind: "ocsf.gateway", source: "gateway_ocsf"}, + {kind: "ocsf.supervisor", source: "supervisor_ocsf"}, {kind: "ocsf.file", source: "ocsf_files"}, {kind: "ocsf.forwarded", source: "ocsf_files"}, {kind: "sandbox.file_log", source: "operational_files"}, @@ -114,7 +118,7 @@ func TestSourceCapabilityKindMappingAndGapHealthAreBounded(t *testing.T) { func TestMetricSourceVocabularyIsBounded(t *testing.T) { t.Parallel() for _, kind := range []string{ - "ocsf.file", "ocsf.forwarded", "sandbox.lifecycle", "gateway.log", "sandbox.log", + "ocsf.gateway", "ocsf.supervisor", "ocsf.file", "ocsf.forwarded", "sandbox.lifecycle", "gateway.log", "sandbox.log", "nemo_relay.log", "sandbox.file_log", "openshell.log.forwarded", "platform.event", "policy.draft_updated", "policy.draft.snapshot", "policy.draft.chunk", "policy.draft.history", "policy.status", "policy.revision", diff --git a/projects/tools/openshell-exporter/processor/openshellprocessor/validation.go b/projects/tools/openshell-exporter/processor/openshellprocessor/validation.go index 17461037..52b24540 100644 --- a/projects/tools/openshell-exporter/processor/openshellprocessor/validation.go +++ b/projects/tools/openshell-exporter/processor/openshellprocessor/validation.go @@ -38,9 +38,13 @@ func validateSource(kind string, original any) validationResult { } } errs := make([]string, 0) + classUID, classOK := exactInteger(event["class_uid"]) + categoryUID, categoryOK := exactInteger(event["category_uid"]) + baseEvent := classOK && categoryOK && classUID == 0 && categoryUID == 0 for _, field := range []string{"class_uid", "category_uid", "activity_id", "type_uid"} { value, ok := exactInteger(event[field]) - if !ok || value < 0 || (field != "activity_id" && value == 0) { + allowZero := field == "activity_id" || (baseEvent && (field == "class_uid" || field == "category_uid" || field == "type_uid")) + if !ok || value < 0 || (!allowZero && value == 0) { errs = append(errs, fmt.Sprintf("%s must be a positive integer", field)) } } diff --git a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/client.go b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/client.go index 14723f1a..d18fc0cf 100644 --- a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/client.go +++ b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/client.go @@ -13,6 +13,7 @@ import ( "os" "strings" + dm "github.com/NVIDIA/OpenShell/sdk/go/proto/datamodelv1" pb "github.com/NVIDIA/OpenShell/sdk/go/proto/openshellv1" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -229,12 +230,14 @@ func loadTLSConfig(config *Config, serverName string) (*tls.Config, error) { func (c *grpcGatewayClient) List(ctx context.Context) ([]sandboxRef, error) { const pageSize = uint32(1000) result := make([]sandboxRef, 0) - for offset := uint32(0); ; offset += pageSize { + pageToken := "" + seen := map[string]bool{} + for { response, err := c.api.ListSandboxes(ctx, &pb.ListSandboxesRequest{ - Limit: pageSize, - Offset: offset, - LabelSelector: c.config.LabelSelector, - Workspace: c.config.Workspace, + PageSize: int32(pageSize), + PageToken: pageToken, + LabelSelector: c.config.LabelSelector, + WorkspaceScope: namedWorkspace(c.config.Workspace), }) if err != nil { return nil, err @@ -249,18 +252,24 @@ func (c *grpcGatewayClient) List(ctx context.Context) ([]sandboxRef, error) { Name: metadata.GetName(), }) } - if len(response.GetSandboxes()) < int(pageSize) { + pageToken = response.GetNextPageToken() + if pageToken == "" { return result, nil } + if seen[pageToken] { + return nil, errors.New("sandbox pagination repeated a page token") + } + seen[pageToken] = true } } func (c *grpcGatewayClient) Watch( ctx context.Context, - sandboxID string, + sandboxName string, ) (eventStream, error) { return c.api.WatchSandbox(ctx, &pb.WatchSandboxRequest{ - Id: sandboxID, + Sandbox: sandboxName, + WorkspaceScope: namedWorkspace(c.config.Workspace), FollowStatus: true, FollowLogs: true, FollowEvents: true, @@ -281,34 +290,36 @@ func (c *grpcGatewayClient) GatewayVersion(ctx context.Context) (string, error) func (c *grpcGatewayClient) GetDraft(ctx context.Context, sandboxName string) (*pb.GetDraftPolicyResponse, error) { return c.api.GetDraftPolicy(ctx, &pb.GetDraftPolicyRequest{ - Name: sandboxName, - Workspace: c.config.Workspace, + Sandbox: sandboxName, + WorkspaceScope: namedWorkspace(c.config.Workspace), }) } func (c *grpcGatewayClient) GetDraftHistory(ctx context.Context, sandboxName string) (*pb.GetDraftHistoryResponse, error) { return c.api.GetDraftHistory(ctx, &pb.GetDraftHistoryRequest{ - Name: sandboxName, - Workspace: c.config.Workspace, + Sandbox: sandboxName, + WorkspaceScope: namedWorkspace(c.config.Workspace), }) } func (c *grpcGatewayClient) GetPolicyStatus(ctx context.Context, sandboxName string) (*pb.GetSandboxPolicyStatusResponse, error) { return c.api.GetSandboxPolicyStatus(ctx, &pb.GetSandboxPolicyStatusRequest{ - Name: sandboxName, - Workspace: c.config.Workspace, + Sandbox: sandboxName, + WorkspaceScope: namedWorkspace(c.config.Workspace), }) } func (c *grpcGatewayClient) ListPolicyRevisions(ctx context.Context, sandboxName string) ([]*pb.SandboxPolicyRevision, error) { accumulator := newPolicyRevisionAccumulator(c.config.PolicyReconciliation.MaxRevisions) + pageToken := "" + seen := map[string]bool{} for { if uint32(len(accumulator.revisions)) == accumulator.limit { response, err := c.api.ListSandboxPolicies(ctx, &pb.ListSandboxPoliciesRequest{ - Name: sandboxName, - Workspace: c.config.Workspace, - Limit: 1, - Offset: uint32(len(accumulator.revisions)), + Sandbox: sandboxName, + WorkspaceScope: namedWorkspace(c.config.Workspace), + PageSize: 1, + PageToken: pageToken, }) if err != nil { return accumulator.revisions, &policyRevisionPaginationError{ @@ -318,18 +329,26 @@ func (c *grpcGatewayClient) ListPolicyRevisions(ctx context.Context, sandboxName Cause: err, } } - if len(response.GetRevisions()) == 0 { + if len(response.GetRevisions()) > 0 { + return accumulator.revisions, accumulator.limitError(len(accumulator.revisions) + len(response.GetRevisions())) + } + pageToken = response.GetNextPageToken() + if pageToken == "" { return accumulator.revisions, nil } - return accumulator.revisions, accumulator.limitError(len(accumulator.revisions) + len(response.GetRevisions())) + if seen[pageToken] { + return accumulator.revisions, &policyRevisionPaginationError{Reason: policyRevisionPaginationDrift, Retained: len(accumulator.revisions), Limit: accumulator.limit} + } + seen[pageToken] = true + continue } remaining := accumulator.limit - uint32(len(accumulator.revisions)) requestLimit := min(policyRevisionPageSize, remaining) response, err := c.api.ListSandboxPolicies(ctx, &pb.ListSandboxPoliciesRequest{ - Name: sandboxName, - Workspace: c.config.Workspace, - Limit: requestLimit, - Offset: uint32(len(accumulator.revisions)), + Sandbox: sandboxName, + WorkspaceScope: namedWorkspace(c.config.Workspace), + PageSize: int32(requestLimit), + PageToken: pageToken, }) if err != nil { if len(accumulator.revisions) == 0 { @@ -346,9 +365,14 @@ func (c *grpcGatewayClient) ListPolicyRevisions(ctx context.Context, sandboxName if err := accumulator.add(page, requestLimit); err != nil { return accumulator.revisions, err } - if len(page) < int(requestLimit) { + pageToken = response.GetNextPageToken() + if pageToken == "" { return accumulator.revisions, nil } + if seen[pageToken] { + return accumulator.revisions, &policyRevisionPaginationError{Reason: policyRevisionPaginationDrift, Retained: len(accumulator.revisions), Limit: accumulator.limit} + } + seen[pageToken] = true } } @@ -370,3 +394,7 @@ func (c bearerCredentials) GetRequestMetadata( func (c bearerCredentials) RequireTransportSecurity() bool { return true } + +func namedWorkspace(name string) *dm.WorkspaceSelector { + return &dm.WorkspaceSelector{Selection: &dm.WorkspaceSelector_Workspace{Workspace: name}} +} diff --git a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/convert.go b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/convert.go index a17d88be..2d99d0fd 100644 --- a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/convert.go +++ b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/convert.go @@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "fmt" + "google.golang.org/protobuf/types/known/timestamppb" "time" pb "github.com/NVIDIA/OpenShell/sdk/go/proto/openshellv1" @@ -81,7 +82,7 @@ func lifecycleLogs( return plog.Logs{}, errors.New("sandbox payload has no stable ID") } eventType := "MODIFIED" - if metadata.GetDeletionTimestampMs() > 0 { + if timestampMillis(metadata.GetDeletionTime()) > 0 { eventType = "DELETED" } status := sandbox.GetStatus() @@ -145,7 +146,7 @@ func logLineLogs( } body := map[string]any{ "sandbox_id": line.GetSandboxId(), - "timestamp_ms": line.GetTimestampMs(), + "timestamp_ms": timestampMillis(line.GetEventTime()), "level": line.GetLevel(), "target": line.GetTarget(), "message": line.GetMessage(), @@ -167,8 +168,8 @@ func logLineLogs( if err != nil { return plog.Logs{}, err } - if line.GetTimestampMs() > 0 { - record.Attributes().PutInt("openshell.event.time_unix_ms", line.GetTimestampMs()) + if timestampMillis(line.GetEventTime()) > 0 { + record.Attributes().PutInt("openshell.event.time_unix_ms", timestampMillis(line.GetEventTime())) } return logs, nil } @@ -181,7 +182,7 @@ func platformEventLogs( ) (plog.Logs, error) { body := map[string]any{ "sandbox_id": sandbox.ID, - "timestamp_ms": event.GetTimestampMs(), + "timestamp_ms": timestampMillis(event.GetEventTime()), "source": event.GetSource(), "type": event.GetType(), "reason": event.GetReason(), @@ -203,10 +204,10 @@ func platformEventLogs( if err != nil { return plog.Logs{}, err } - if event.GetTimestampMs() > 0 { + if timestampMillis(event.GetEventTime()) > 0 { record.Attributes().PutInt( "openshell.event.time_unix_ms", - event.GetTimestampMs(), + timestampMillis(event.GetEventTime()), ) } return logs, nil @@ -370,3 +371,10 @@ func stringMapToAny(values map[string]string) map[string]any { } return result } + +func timestampMillis(value *timestamppb.Timestamp) int64 { + if value == nil { + return 0 + } + return value.AsTime().UnixMilli() +} diff --git a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/metrics.go b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/metrics.go index d1533bc8..8765fe5b 100644 --- a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/metrics.go +++ b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/metrics.go @@ -30,6 +30,8 @@ type watchMetrics struct { reconnects metric.Int64Counter gapWarnings metric.Int64Counter backpressure metric.Int64Counter + backpressureActive metric.Int64UpDownCounter + unacknowledgedRecords metric.Int64Counter sourceEnabled metric.Int64Gauge lastSuccess metric.Int64Gauge policyConfigured metric.Int64Gauge @@ -54,6 +56,8 @@ func newWatchMetrics(provider metric.MeterProvider) *watchMetrics { reconnects, _ := meter.Int64Counter("openshell.exporter.stream.reconnects", metric.WithUnit("{reconnect}")) gapWarnings, _ := meter.Int64Counter("openshell.exporter.stream.gap_warnings", metric.WithUnit("{warning}")) backpressure, _ := meter.Int64Counter("openshell.exporter.stream.backpressure_retries", metric.WithUnit("{retry}")) + backpressureActive, _ := meter.Int64UpDownCounter("openshell.exporter.stream.backpressure_active", metric.WithDescription("Receiver deliveries waiting to retry downstream; includes policy and warning evidence."), metric.WithUnit("{delivery}")) + unacknowledgedRecords, _ := meter.Int64Counter("openshell.exporter.stream.unacknowledged_records", metric.WithDescription("WatchSandbox records without downstream acknowledgement on cancellation or permanent rejection; partial delivery is possible."), metric.WithUnit("{record}")) sourceEnabled, _ := meter.Int64Gauge("openshell.exporter.source.enabled", metric.WithDescription("Configured source profile capability; one means enabled."), metric.WithUnit("1")) lastSuccess, _ := meter.Int64Gauge("openshell.exporter.source.last_success_unixtime", metric.WithDescription("Unix time of the last normalized record by bounded source kind."), metric.WithUnit("s")) policyConfigured, _ := meter.Int64Gauge(policyConfiguredMetricName, metric.WithDescription("One when read-only policy reconciliation is configured."), metric.WithUnit("1")) @@ -69,6 +73,8 @@ func newWatchMetrics(provider metric.MeterProvider) *watchMetrics { reconnects: reconnects, gapWarnings: gapWarnings, backpressure: backpressure, + backpressureActive: backpressureActive, + unacknowledgedRecords: unacknowledgedRecords, sourceEnabled: sourceEnabled, lastSuccess: lastSuccess, policyConfigured: policyConfigured, @@ -235,3 +241,7 @@ func boundedPolicyConsistencyState(state string) string { return "other" } } + +func (m *watchMetrics) unacknowledged(ctx context.Context, reason string, count int) { + m.unacknowledgedRecords.Add(ctx, int64(count), metric.WithAttributes(attribute.String("reason", reason))) +} diff --git a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/pagination_test.go b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/pagination_test.go index a60c6c19..bdf46b37 100644 --- a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/pagination_test.go +++ b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/pagination_test.go @@ -10,6 +10,7 @@ import ( "sync" "testing" + dm "github.com/NVIDIA/OpenShell/sdk/go/proto/datamodelv1" pb "github.com/NVIDIA/OpenShell/sdk/go/proto/openshellv1" "google.golang.org/grpc" "google.golang.org/grpc/codes" @@ -44,13 +45,13 @@ func TestPolicyRevisionPaginationUsesOneRecordBoundaryProbe(t *testing.T) { t.Parallel() api := &policyRevisionAPI{} api.respond = func(request *pb.ListSandboxPoliciesRequest) (*pb.ListSandboxPoliciesResponse, error) { - switch request.GetOffset() { - case 0: - return revisionResponse(3, 2, 1), nil - case 3: + switch request.GetPageToken() { + case "": + return revisionPage("next", 3, 2, 1), nil + case "next": return revisionResponse(), nil default: - return nil, fmt.Errorf("unexpected offset %d", request.GetOffset()) + return nil, fmt.Errorf("unexpected page token %q", request.GetPageToken()) } } client := testPolicyRevisionClient(api, 3) @@ -61,8 +62,8 @@ func TestPolicyRevisionPaginationUsesOneRecordBoundaryProbe(t *testing.T) { } assertRevisionVersions(t, revisions, 3, 2, 1) requests := api.snapshotRequests() - if len(requests) != 2 || requests[0].GetLimit() != 3 || requests[0].GetOffset() != 0 || - requests[1].GetLimit() != 1 || requests[1].GetOffset() != 3 { + if len(requests) != 2 || requests[0].GetPageSize() != 3 || requests[0].GetPageToken() != "" || + requests[1].GetPageSize() != 1 || requests[1].GetPageToken() != "next" { t.Fatalf("pagination requests=%#v, want bounded page and one-record probe", requests) } } @@ -71,8 +72,8 @@ func TestPolicyRevisionPaginationReportsOverflowAndRetainsBoundedNewestSet(t *te t.Parallel() api := &policyRevisionAPI{} api.respond = func(request *pb.ListSandboxPoliciesRequest) (*pb.ListSandboxPoliciesResponse, error) { - if request.GetOffset() == 0 { - return revisionResponse(5, 4, 3), nil + if request.GetPageToken() == "" { + return revisionPage("next", 5, 4, 3), nil } return revisionResponse(2), nil } @@ -103,8 +104,8 @@ func TestPolicyRevisionPaginationReturnsPartialEvidenceAfterLaterPageFailure(t * } api := &policyRevisionAPI{} api.respond = func(request *pb.ListSandboxPoliciesRequest) (*pb.ListSandboxPoliciesResponse, error) { - if request.GetOffset() == 0 { - return revisionResponse(firstPage...), nil + if request.GetPageToken() == "" { + return revisionPage("next", firstPage...), nil } return nil, status.Error(codes.Unavailable, "injected later-page failure") } @@ -225,3 +226,115 @@ func assertPaginationError(t *testing.T, err error, reason string, retained int) t.Fatalf("pagination error=%#v, want reason=%q retained=%d", err, reason, retained) } } + +func revisionPage(token string, versions ...uint32) *pb.ListSandboxPoliciesResponse { + response := revisionResponse(versions...) + response.NextPageToken = token + return response +} + +func TestPolicyRevisionPaginationFollowsShortPagesAndRejectsCycles(t *testing.T) { + for _, cycle := range []bool{false, true} { + t.Run(fmt.Sprint(cycle), func(t *testing.T) { + api := &policyRevisionAPI{} + api.respond = func(request *pb.ListSandboxPoliciesRequest) (*pb.ListSandboxPoliciesResponse, error) { + if request.GetSandbox() != "agent" || request.GetWorkspaceScope().GetWorkspace() != "default" { + t.Fatalf("scope lost: %v", request) + } + if request.GetPageToken() == "" { + return revisionPage("opaque-next", 3), nil + } + if request.GetPageToken() != "opaque-next" { + t.Fatalf("token changed: %v", request) + } + if cycle { + return revisionPage("opaque-next", 2), nil + } + return revisionResponse(2), nil + } + revisions, err := testPolicyRevisionClient(api, 10).ListPolicyRevisions(context.Background(), "agent") + if cycle { + assertPaginationError(t, err, policyRevisionPaginationDrift, 2) + } else if err != nil { + t.Fatal(err) + } + assertRevisionVersions(t, revisions, 3, 2) + if len(api.snapshotRequests()) != 2 { + t.Fatal("pagination did not stop") + } + }) + } +} + +type sandboxPaginationAPI struct { + pb.OpenShellClient + requests []*pb.ListSandboxesRequest + cycle bool + watch *pb.WatchSandboxRequest +} + +func (a *sandboxPaginationAPI) ListSandboxes(_ context.Context, request *pb.ListSandboxesRequest, _ ...grpc.CallOption) (*pb.ListSandboxesResponse, error) { + a.requests = append(a.requests, request) + token := "" + if request.GetPageToken() == "" || a.cycle { + token = "opaque-next" + } + return &pb.ListSandboxesResponse{Sandboxes: []*pb.Sandbox{{Metadata: &dm.ObjectMeta{Id: fmt.Sprint(len(a.requests)), Name: "agent"}}}, NextPageToken: token}, nil +} +func (a *sandboxPaginationAPI) WatchSandbox(_ context.Context, request *pb.WatchSandboxRequest, _ ...grpc.CallOption) (grpc.ServerStreamingClient[pb.SandboxStreamEvent], error) { + a.watch = request + return nil, nil +} +func TestSandboxRequestsUseNamedWorkspaceAndOpaquePagination(t *testing.T) { + for _, cycle := range []bool{false, true} { + api := &sandboxPaginationAPI{cycle: cycle} + config := createDefaultConfig().(*Config) + config.Workspace = "team" + config.LabelSelector = "owner=demo" + client := &grpcGatewayClient{api: api, config: config} + refs, err := client.List(context.Background()) + if (err != nil) != cycle { + t.Fatalf("cycle=%t: %v", cycle, err) + } + if !cycle && len(refs) != 2 { + t.Fatalf("short page lost: %v", refs) + } + if len(api.requests) != 2 || api.requests[1].GetPageToken() != "opaque-next" { + t.Fatal("opaque pagination failed") + } + for _, request := range api.requests { + if request.GetWorkspaceScope().GetWorkspace() != "team" || request.GetLabelSelector() != "owner=demo" { + t.Fatalf("scope lost: %v", request) + } + } + if _, err = client.Watch(context.Background(), "agent"); err != nil { + t.Fatal(err) + } + if api.watch.GetSandbox() != "agent" || api.watch.GetWorkspaceScope().GetWorkspace() != "team" || api.watch.GetResumeAfterCursor() != "" { + t.Fatalf("watch request=%v", api.watch) + } + } +} + +func TestPolicyRevisionBoundaryProbeFollowsEmptyPageToken(t *testing.T) { + api := &policyRevisionAPI{} + api.respond = func(request *pb.ListSandboxPoliciesRequest) (*pb.ListSandboxPoliciesResponse, error) { + switch request.GetPageToken() { + case "": + return revisionPage("empty-page", 3, 2), nil + case "empty-page": + return revisionPage("last-page"), nil + case "last-page": + return revisionResponse(1), nil + default: + t.Fatalf("unexpected token %q", request.GetPageToken()) + return nil, nil + } + } + revisions, err := testPolicyRevisionClient(api, 2).ListPolicyRevisions(context.Background(), "sandbox") + assertPaginationError(t, err, policyRevisionLimitExceeded, 2) + assertRevisionVersions(t, revisions, 3, 2) + if len(api.snapshotRequests()) != 3 { + t.Fatal("empty page suppressed later revision") + } +} diff --git a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/policy_convert.go b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/policy_convert.go index 1e9eaf7b..83cb886c 100644 --- a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/policy_convert.go +++ b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/policy_convert.go @@ -35,7 +35,7 @@ func draftSnapshotLogs( "sandbox_id": sandbox.ID, "draft_version": sanitized.GetDraftVersion(), "rolling_summary": sanitized.GetRollingSummary(), - "last_analyzed_at_ms": sanitized.GetLastAnalyzedAtMs(), + "last_analyzed_at_ms": timestampMillis(sanitized.GetLastAnalyzedTime()), "chunk_count": len(sanitized.GetChunks()), "review_tokens_removed": removed, "effective_policies_included": config.PolicyReconciliation.IncludeEffectivePolicies, @@ -49,8 +49,8 @@ func draftSnapshotLogs( return plog.Logs{}, err } record.Attributes().PutInt("openshell.policy.revision", int64(sanitized.GetDraftVersion())) - if sanitized.GetLastAnalyzedAtMs() > 0 { - record.Attributes().PutInt("openshell.event.time_unix_ms", sanitized.GetLastAnalyzedAtMs()) + if timestampMillis(sanitized.GetLastAnalyzedTime()) > 0 { + record.Attributes().PutInt("openshell.event.time_unix_ms", timestampMillis(sanitized.GetLastAnalyzedTime())) } return logs, nil } @@ -88,8 +88,8 @@ func draftChunkLogs( if sanitized.GetId() != "" { record.Attributes().PutStr("openshell.policy.chunk.id", sanitized.GetId()) } - if sanitized.GetCreatedAtMs() > 0 { - record.Attributes().PutInt("openshell.event.time_unix_ms", sanitized.GetCreatedAtMs()) + if timestampMillis(sanitized.GetCreatedTime()) > 0 { + record.Attributes().PutInt("openshell.event.time_unix_ms", timestampMillis(sanitized.GetCreatedTime())) } return logs, nil } @@ -125,8 +125,8 @@ func policyStatusLogs( } if revision := sanitized.GetRevision(); revision != nil { record.Attributes().PutInt("openshell.policy.revision", int64(revision.GetVersion())) - if revision.GetCreatedAtMs() > 0 { - record.Attributes().PutInt("openshell.event.time_unix_ms", revision.GetCreatedAtMs()) + if timestampMillis(revision.GetCreatedTime()) > 0 { + record.Attributes().PutInt("openshell.event.time_unix_ms", timestampMillis(revision.GetCreatedTime())) } } return logs, nil @@ -162,8 +162,8 @@ func policyRevisionLogs( } record.Attributes().PutInt("openshell.policy.version", int64(sanitized.GetVersion())) record.Attributes().PutInt("openshell.policy.revision", int64(sanitized.GetVersion())) - if sanitized.GetCreatedAtMs() > 0 { - record.Attributes().PutInt("openshell.event.time_unix_ms", sanitized.GetCreatedAtMs()) + if timestampMillis(sanitized.GetCreatedTime()) > 0 { + record.Attributes().PutInt("openshell.event.time_unix_ms", timestampMillis(sanitized.GetCreatedTime())) } return logs, nil } @@ -182,7 +182,7 @@ func draftHistoryLogs( "sandbox_id": sandbox.ID, "event_type": entry.GetEventType(), "policy_chunk_id": entry.GetChunkId(), - "timestamp_ms": entry.GetTimestampMs(), + "timestamp_ms": timestampMillis(entry.GetEventTime()), } body, payloadType, err := withPublicPayload(body, entry) if err != nil { @@ -195,8 +195,8 @@ func draftHistoryLogs( if entry.GetChunkId() != "" { record.Attributes().PutStr("openshell.policy.chunk.id", entry.GetChunkId()) } - if entry.GetTimestampMs() > 0 { - record.Attributes().PutInt("openshell.event.time_unix_ms", entry.GetTimestampMs()) + if timestampMillis(entry.GetEventTime()) > 0 { + record.Attributes().PutInt("openshell.event.time_unix_ms", timestampMillis(entry.GetEventTime())) } return logs, nil } diff --git a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver.go b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver.go index ec5e8046..bcbcd10e 100644 --- a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver.go +++ b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver.go @@ -10,6 +10,7 @@ import ( "io" "math/rand/v2" "slices" + "strings" "sync" "sync/atomic" "time" @@ -22,6 +23,7 @@ import ( "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/receiver" "go.uber.org/zap" + "golang.org/x/mod/semver" ) type watchReceiver struct { @@ -72,10 +74,27 @@ func newWatchReceiver( } func (r *watchReceiver) Start(ctx context.Context, host component.Host) error { + if err := ctx.Err(); err != nil { + return err + } client, err := r.newClient(r.config) if err != nil { return err } + // Verify the API contract before opening persistent state or starting workers. + infoContext, cancelInfo := context.WithTimeout(ctx, 5*time.Second) + gatewayVersion, err := client.GatewayVersion(infoContext) + cancelInfo() + if err != nil { + return errors.Join(fmt.Errorf("verify OpenShell version: %w", err), client.Close()) + } + if err := ctx.Err(); err != nil { + return errors.Join(err, client.Close()) + } + if err := validateGatewayVersion(gatewayVersion); err != nil { + return errors.Join(err, client.Close()) + } + r.gatewayVersion = gatewayVersion r.client = client runContext, cancel := context.WithCancel(context.Background()) r.cancel = cancel @@ -95,16 +114,6 @@ func (r *watchReceiver) Start(ctx context.Context, host component.Host) error { zap.Bool("watch_events_rpc", false), ) - infoContext, cancelInfo := context.WithTimeout(context.Background(), 5*time.Second) - r.gatewayVersion, err = client.GatewayVersion(infoContext) - cancelInfo() - if err != nil { - r.settings.Logger.Warn( - "gateway version enrichment unavailable", - zap.Error(err), - ) - } - r.discoveryWG.Add(1) go r.discoveryLoop(runContext) return nil @@ -115,7 +124,7 @@ func (r *watchReceiver) Shutdown(ctx context.Context) error { if r.cancel != nil { r.cancel() } - go r.finishShutdown() + go r.finishShutdown(ctx) }) select { case <-r.shutdownDone: @@ -125,17 +134,19 @@ func (r *watchReceiver) Shutdown(ctx context.Context) error { } } -func (r *watchReceiver) finishShutdown() { +func (r *watchReceiver) finishShutdown(ctx context.Context) { r.discoveryWG.Wait() r.watchWG.Wait() r.reconcileWG.Wait() var shutdownErrors []error - if r.policyStorage != nil { - shutdownErrors = append(shutdownErrors, r.policyStorage.Close(context.Background())) - } + // Release the transport even if storage cleanup blocks. All workers have + // stopped using both resources; give storage the caller's shutdown deadline. if r.client != nil { shutdownErrors = append(shutdownErrors, r.client.Close()) } + if r.policyStorage != nil { + shutdownErrors = append(shutdownErrors, r.policyStorage.Close(ctx)) + } r.shutdownErr = errors.Join(shutdownErrors...) close(r.shutdownDone) } @@ -219,8 +230,11 @@ func (r *watchReceiver) watch(ctx context.Context, sandbox sandboxRef) { if ctx.Err() != nil { return } - stream, err := r.client.Watch(ctx, sandbox.ID) + stream, err := r.client.Watch(ctx, sandbox.Name) if err != nil { + if ctx.Err() != nil { + return + } r.metrics.reconnect(ctx, "stream_open_failed") r.emitWarning( ctx, @@ -231,7 +245,7 @@ func (r *watchReceiver) watch(ctx context.Context, sandbox sandboxRef) { if !r.waitReconnect(ctx, backoff) { return } - backoff = min(backoff*2, r.config.ReconnectMax) + backoff += min(backoff, r.config.ReconnectMax-backoff) continue } @@ -275,9 +289,12 @@ func (r *watchReceiver) watch(ctx context.Context, sandbox sandboxRef) { r.metrics.succeeded(ctx) deliveryErr := r.consumeWithBackpressure(ctx, logs) if deliveryErr != nil { - if errors.Is(deliveryErr, context.Canceled) { + if ctx.Err() != nil { + r.metrics.unacknowledged(ctx, "canceled", logs.LogRecordCount()) return } + r.metrics.unacknowledged(ctx, "permanent_rejection", logs.LogRecordCount()) + r.metrics.gap(ctx, "downstream_permanent_rejection") r.settings.Logger.Warn( "sandbox event delivery failed", zap.Error(deliveryErr), @@ -295,7 +312,7 @@ func (r *watchReceiver) watch(ctx context.Context, sandbox sandboxRef) { if !r.waitReconnect(ctx, backoff) { return } - backoff = min(backoff*2, r.config.ReconnectMax) + backoff += min(backoff, r.config.ReconnectMax-backoff) } } @@ -330,8 +347,7 @@ func (r *watchReceiver) emitWarning( } func (r *watchReceiver) waitReconnect(ctx context.Context, delay time.Duration) bool { - jitter := time.Duration(rand.Int64N(int64(delay/2) + 1)) - timer := time.NewTimer(min(delay+jitter, r.config.ReconnectMax)) + timer := time.NewTimer(reconnectDelay(delay, r.config.ReconnectMax)) defer timer.Stop() select { case <-ctx.Done(): @@ -341,12 +357,29 @@ func (r *watchReceiver) waitReconnect(ctx context.Context, delay time.Duration) } } +// Equal jitter retains spread even at the maximum delay. It bounds each wait +// between half the capped backoff and the cap; tails are still non-resumable. +func reconnectDelay(delay, maximum time.Duration) time.Duration { + capDelay := min(delay, maximum) + floor := capDelay / 2 + return floor + time.Duration(rand.Int64N(int64(capDelay-floor)+1)) +} + func (r *watchReceiver) consumeWithBackpressure( ctx context.Context, logs plog.Logs, ) error { delay := time.Second + stalled := false + defer func() { + if stalled { + r.metrics.backpressureActive.Add(ctx, -1) + } + }() for { + if err := ctx.Err(); err != nil { + return err + } // Downstream processors may mutate their input even when delivery fails. // Retain the receiver-owned evidence for retries and checkpoint hashes. attempt := plog.NewLogs() @@ -356,16 +389,32 @@ func (r *watchReceiver) consumeWithBackpressure( } else if consumererror.IsPermanent(err) { return err } + if err := ctx.Err(); err != nil { + return err + } + if !stalled { + stalled = true + r.metrics.backpressureActive.Add(ctx, 1) + r.metrics.gap(ctx, "downstream_backpressure") + } r.metrics.backpressured(ctx) timer := time.NewTimer(delay) select { case <-ctx.Done(): - if !timer.Stop() { - <-timer.C - } + timer.Stop() return ctx.Err() case <-timer.C: } delay = min(delay*2, 30*time.Second) } } + +// The 0.1 API changed workspace selectors, resource names, and pagination. +// Older gateways must be rejected before starting any source watches. +func validateGatewayVersion(raw string) error { + version := "v" + strings.TrimPrefix(raw, "v") + if !semver.IsValid(version) || semver.Compare(version, "v0.1.0") < 0 { + return fmt.Errorf("OpenShell %q is unsupported: version 0.1.0 or newer is required", raw) + } + return nil +} diff --git a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver_lifecycle_test.go b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver_lifecycle_test.go index a9c6ba92..51c094af 100644 --- a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver_lifecycle_test.go +++ b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver_lifecycle_test.go @@ -6,6 +6,7 @@ package watchsandboxreceiver import ( "context" "errors" + "fmt" "io" "sync" "sync/atomic" @@ -16,8 +17,11 @@ import ( pb "github.com/NVIDIA/OpenShell/sdk/go/proto/openshellv1" "go.opentelemetry.io/collector/component" "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/consumererror" "go.opentelemetry.io/collector/pdata/plog" "go.opentelemetry.io/collector/receiver" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/metric/metricdata" "go.uber.org/zap" ) @@ -44,6 +48,7 @@ type lifecycleGateway struct { listCalls atomic.Int32 closeCalls atomic.Int32 versionError error + version string } func (g *lifecycleGateway) List(context.Context) ([]sandboxRef, error) { @@ -71,7 +76,10 @@ func (g *lifecycleGateway) Watch(ctx context.Context, sandboxID string) (eventSt } func (g *lifecycleGateway) GatewayVersion(context.Context) (string, error) { - return "0.0.test", g.versionError + if g.version != "" { + return g.version, g.versionError + } + return "0.1.2", g.versionError } func (g *lifecycleGateway) GetDraft(context.Context, string) (*pb.GetDraftPolicyResponse, error) { @@ -174,7 +182,7 @@ func TestReceiverLifecycleFiltersDiscoveryAndSurfacesStreamGap(t *testing.T) { gateway.watchMu.Lock() defer gateway.watchMu.Unlock() for _, sandboxID := range gateway.watchedIDs { - if sandboxID != "sandbox-allowed" { + if sandboxID != "allowed" { t.Fatalf("unauthorized sandbox was watched: %q", sandboxID) } } @@ -204,3 +212,311 @@ func TestReceiverStartFailsClosedAndReleasesClient(t *testing.T) { t.Fatalf("failed start close calls=%d, want 1", gateway.closeCalls.Load()) } } + +func TestCanceledDeliveryDoesNotCallDownstream(t *testing.T) { + var calls atomic.Int32 + next, err := consumer.NewLogs(func(context.Context, plog.Logs) error { + calls.Add(1) + return nil + }) + if err != nil { + t.Fatal(err) + } + r := newWatchReceiver(createDefaultConfig().(*Config), lifecycleSettings(), next) + ctx, cancel := context.WithCancel(context.Background()) + cancel() + if err := r.consumeWithBackpressure(ctx, plog.NewLogs()); !errors.Is(err, context.Canceled) { + t.Fatalf("delivery error = %v, want cancellation", err) + } + if calls.Load() != 0 { + t.Fatal("canceled delivery reached downstream") + } +} + +func TestWatchPermanentRejectionReportsGap(t *testing.T) { + reader := sdkmetric.NewManualReader() + provider := sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)) + t.Cleanup(func() { _ = provider.Shutdown(context.Background()) }) + gateway := &lifecycleGateway{sandboxes: []sandboxRef{{ID: "sandbox", Name: "allowed"}}} + config := createDefaultConfig().(*Config) + config.DiscoveryInterval = time.Hour + config.ReconnectInitial = time.Hour + config.ReconnectMax = time.Hour + next, err := consumer.NewLogs(func(context.Context, plog.Logs) error { + return consumererror.NewPermanent(errors.New("rejected")) + }) + if err != nil { + t.Fatal(err) + } + settings := lifecycleSettings() + settings.MeterProvider = provider + r := newWatchReceiver(config, settings, next) + r.newClient = func(*Config) (gatewayClient, error) { return gateway, nil } + if err := r.Start(context.Background(), lifecycleHost{}); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = r.Shutdown(context.Background()) }) + deadline := time.Now().Add(time.Second) + for { + var found bool + for _, m := range collectMetrics(t, reader) { + if m.Name != "openshell.exporter.stream.gap_warnings" { + continue + } + for _, point := range m.Data.(metricdata.Sum[int64]).DataPoints { + reason, _ := point.Attributes.Value("reason") + if reason.AsString() == "downstream_permanent_rejection" && point.Value == 1 { + found = true + } + } + } + if found { + break + } + if time.Now().After(deadline) { + t.Fatal("permanently rejected source event did not report a gap") + } + time.Sleep(time.Millisecond) + } +} + +// Each stream offers an unlimited sequence. A saturated downstream must leave +// exactly one record per watch in flight, not keep draining into local buffers. +type loadGateway struct { + lifecycleGateway + reads atomic.Int32 +} + +func (g *loadGateway) Watch(ctx context.Context, id string) (eventStream, error) { + g.watchCalls.Add(1) + return &loadStream{ctx: ctx, id: id, reads: &g.reads}, nil +} + +type loadStream struct { + ctx context.Context + id string + reads *atomic.Int32 +} + +func (s *loadStream) Recv() (*pb.SandboxStreamEvent, error) { + if err := s.ctx.Err(); err != nil { + return nil, err + } + s.reads.Add(1) + return &pb.SandboxStreamEvent{Payload: &pb.SandboxStreamEvent_Sandbox{Sandbox: &pb.Sandbox{ + Metadata: &datamodelv1.ObjectMeta{Id: s.id, Name: s.id, ResourceVersion: 1}, + }}}, nil +} + +func TestSaturatedWatchesBoundReadsAndCancelUnderLoad(t *testing.T) { + for _, slow := range []bool{false, true} { + t.Run(fmt.Sprintf("blocking=%t", slow), func(t *testing.T) { + const watches = 32 + gateway := &loadGateway{} + for i := range watches { + gateway.sandboxes = append(gateway.sandboxes, sandboxRef{ID: fmt.Sprint(i), Name: fmt.Sprint(i)}) + } + reader := sdkmetric.NewManualReader() + provider := sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)) + t.Cleanup(func() { _ = provider.Shutdown(context.Background()) }) + settings := lifecycleSettings() + settings.MeterProvider = provider + entered := make(chan struct{}, watches*2) + next, err := consumer.NewLogs(func(ctx context.Context, _ plog.Logs) error { + entered <- struct{}{} + if slow { + <-ctx.Done() + return ctx.Err() + } + return errors.New("bounded queue full") + }) + if err != nil { + t.Fatal(err) + } + config := createDefaultConfig().(*Config) + config.DiscoveryInterval = time.Hour + r := newWatchReceiver(config, settings, next) + r.newClient = func(*Config) (gatewayClient, error) { return gateway, nil } + if err := r.Start(context.Background(), lifecycleHost{}); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = r.Shutdown(context.Background()) }) + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + for range watches { + select { + case <-entered: + case <-ctx.Done(): + t.Fatal("watches did not saturate downstream") + } + } + // Long enough to catch an accidental read-ahead loop, shorter than retry backoff. + time.Sleep(50 * time.Millisecond) + if got := gateway.reads.Load(); got != watches { + t.Fatalf("reads=%d, want bounded %d", got, watches) + } + if !slow { + m := collectMetrics(t, reader) + assertIntSum(t, m, "openshell.exporter.stream.gap_warnings", watches, "reason", "downstream_backpressure") + active := findMetric(t, m, "openshell.exporter.stream.backpressure_active").Data.(metricdata.Sum[int64]) + if len(active.DataPoints) != 1 || active.DataPoints[0].Value != watches { + t.Fatalf("active retries: %#v", active) + } + } + shutdown, stop := context.WithTimeout(context.Background(), time.Second) + defer stop() + if err := r.Shutdown(shutdown); err != nil { + t.Fatal(err) + } + if gateway.closeCalls.Load() != 1 { + t.Fatal("gateway was not closed exactly once") + } + m := collectMetrics(t, reader) + assertIntSum(t, m, "openshell.exporter.stream.unacknowledged_records", watches, "reason", "canceled") + if !slow { + active := findMetric(t, m, "openshell.exporter.stream.backpressure_active").Data.(metricdata.Sum[int64]) + if active.DataPoints[0].Value != 0 { + t.Fatalf("active retries after shutdown: %#v", active) + } + } + }) + } +} + +func TestReconnectJitterRemainsBoundedAtCap(t *testing.T) { + for _, delay := range []time.Duration{10 * time.Millisecond, time.Second, 10 * time.Second} { + const maximum = time.Second + unique := map[time.Duration]bool{} + for range 100 { + got := reconnectDelay(delay, maximum) + if got < min(delay, maximum)/2 || got > min(delay, maximum) { + t.Fatalf("delay %v produced %v", delay, got) + } + unique[got] = true + } + if len(unique) < 2 { + t.Fatalf("jitter disappeared at delay=%v", delay) + } + } + r := newWatchReceiver(createDefaultConfig().(*Config), lifecycleSettings(), nil) + ctx, cancel := context.WithCancel(context.Background()) + cancel() + if r.waitReconnect(ctx, time.Hour) { + t.Fatal("canceled reconnect waited") + } +} + +type startupGateway struct { + lifecycleGateway + entered chan struct{} +} + +func (g *startupGateway) GatewayVersion(ctx context.Context) (string, error) { + close(g.entered) + <-ctx.Done() + return "", ctx.Err() +} +func TestCanceledStartupStopsVersionEnrichment(t *testing.T) { + gateway := &startupGateway{entered: make(chan struct{})} + r := newWatchReceiver(createDefaultConfig().(*Config), lifecycleSettings(), nil) + r.newClient = func(*Config) (gatewayClient, error) { return gateway, nil } + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + done := make(chan error, 1) + go func() { done <- r.Start(ctx, lifecycleHost{}) }() + select { + case <-gateway.entered: + case <-time.After(time.Second): + t.Fatal("version lookup did not start") + } + cancel() + select { + case err := <-done: + if !errors.Is(err, context.Canceled) { + t.Fatalf("startup error=%v", err) + } + case <-time.After(time.Second): + t.Fatal("startup ignored cancellation") + } + if gateway.closeCalls.Load() != 1 || gateway.listCalls.Load() != 0 { + t.Fatal("canceled startup did not release the client before discovery") + } +} + +type slowClosingStorage struct { + *memoryPolicyStorage + entered chan struct{} +} + +func (s *slowClosingStorage) Close(ctx context.Context) error { + close(s.entered) + <-ctx.Done() + return ctx.Err() +} +func TestShutdownCancelsStorageCloseAndReleasesGateway(t *testing.T) { + r := newWatchReceiver(createDefaultConfig().(*Config), lifecycleSettings(), nil) + gateway := &lifecycleGateway{} + store := &slowClosingStorage{memoryPolicyStorage: newMemoryPolicyStorage(), entered: make(chan struct{})} + r.client = gateway + r.policyStorage = store + ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond) + defer cancel() + if err := r.Shutdown(ctx); !errors.Is(err, context.DeadlineExceeded) { + t.Fatalf("shutdown error=%v", err) + } + select { + case <-store.entered: + default: + t.Fatal("storage was not closed") + } + select { + case <-r.shutdownDone: + case <-time.After(time.Second): + t.Fatal("storage close did not receive cancellation") + } + if gateway.closeCalls.Load() != 1 { + t.Fatal("storage close prevented gateway cleanup") + } + if err := r.Shutdown(context.Background()); !errors.Is(err, context.DeadlineExceeded) { + t.Fatalf("storage close error was lost: %v", err) + } +} + +func TestGatewayMinimumVersion(t *testing.T) { + for _, version := range []string{"0.1.0", "v0.1.0", "0.1.2", "1.0.0", "0.1.0+build.1"} { + if err := validateGatewayVersion(version); err != nil { + t.Errorf("%s: %v", version, err) + } + } + for _, version := range []string{"", "dev", "0.0.113", "0.1.0-rc.1", "not-a-version"} { + if err := validateGatewayVersion(version); err == nil { + t.Errorf("accepted unsupported version %q", version) + } + } +} + +func TestUnsupportedGatewayFailsBeforeDiscovery(t *testing.T) { + for _, tt := range []struct { + name, version string + err error + }{ + {name: "old", version: "0.0.113"}, + {name: "malformed", version: "unknown"}, + {name: "unavailable", err: errors.New("version unavailable")}, + } { + t.Run(tt.name, func(t *testing.T) { + gateway := &lifecycleGateway{version: tt.version, versionError: tt.err} + r := newWatchReceiver(createDefaultConfig().(*Config), lifecycleSettings(), nil) + r.newClient = func(*Config) (gatewayClient, error) { return gateway, nil } + if err := r.Start(context.Background(), lifecycleHost{}); err == nil { + t.Fatal("unsupported gateway started") + } + if gateway.listCalls.Load() != 0 || gateway.watchCalls.Load() != 0 { + t.Fatal("unsupported gateway was queried") + } + if gateway.closeCalls.Load() != 1 { + t.Fatal("client was not closed exactly once") + } + }) + } +} diff --git a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver_test.go b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver_test.go index 99f63a3f..c906a34d 100644 --- a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver_test.go +++ b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/receiver_test.go @@ -6,6 +6,7 @@ package watchsandboxreceiver import ( "context" "errors" + "google.golang.org/protobuf/types/known/timestamppb" "strings" "testing" "time" @@ -46,10 +47,10 @@ func TestEveryPublicWatchSandboxVariantConverts(t *testing.T) { event: &pb.SandboxStreamEvent{ Payload: &pb.SandboxStreamEvent_Log{ Log: &pb.SandboxLogLine{ - SandboxId: "sandbox-id", - TimestampMs: 1_700_000_000_000, - Source: "gateway", - Message: "allowed", + SandboxId: "sandbox-id", + EventTime: timestamppb.New(time.UnixMilli(1_700_000_000_000)), + Source: "gateway", + Message: "allowed", }, }, }, @@ -71,10 +72,10 @@ func TestEveryPublicWatchSandboxVariantConverts(t *testing.T) { event: &pb.SandboxStreamEvent{ Payload: &pb.SandboxStreamEvent_Event{ Event: &pb.PlatformEvent{ - TimestampMs: 1_700_000_000_001, - Source: "kubernetes", - Type: "Warning", - Reason: "BackOff", + EventTime: timestamppb.New(time.UnixMilli(1_700_000_000_001)), + Source: "kubernetes", + Type: "Warning", + Reason: "BackOff", }, }, }, @@ -164,14 +165,14 @@ func TestLifecyclePreservesCompletePublicPayload(t *testing.T) { config := createDefaultConfig().(*Config) logs, err := lifecycleLogs(config, "v0.0.113", &pb.Sandbox{ Metadata: &datamodelv1.ObjectMeta{ - Id: "sandbox-id", - Name: "sandbox-name", - CreatedAtMs: 1_700_000_000_000, - Labels: map[string]string{"team": "security"}, - ResourceVersion: 19, - Annotations: map[string]string{"trace.id": "trace-from-annotation"}, - Workspace: "default", - DeletionTimestampMs: 1_700_000_100_000, + Id: "sandbox-id", + Name: "sandbox-name", + CreatedTime: timestamppb.New(time.UnixMilli(1_700_000_000_000)), + Labels: map[string]string{"team": "security"}, + ResourceVersion: 19, + Annotations: map[string]string{"trace.id": "trace-from-annotation"}, + Workspace: "default", + DeletionTime: timestamppb.New(time.UnixMilli(1_700_000_100_000)), }, Spec: &pb.SandboxSpec{ LogLevel: "debug", @@ -184,16 +185,15 @@ func TestLifecyclePreservesCompletePublicPayload(t *testing.T) { Providers: []string{"nvidia"}, }, Status: &pb.SandboxStatus{ - SandboxName: "driver-sandbox-id", - AgentPod: "agent-pod-1", - AgentFd: "agent.sock", - SandboxFd: "sandbox.sock", + AgentPod: "agent-pod-1", + AgentFd: "agent.sock", + SandboxFd: "sandbox.sock", Conditions: []*pb.SandboxCondition{{ - Type: "Ready", - Status: "True", - Reason: "Provisioned", - Message: "sandbox is ready", - LastTransitionTime: "2026-08-21T00:00:00Z", + Type: "Ready", + Status: "True", + Reason: "Provisioned", + Message: "sandbox is ready", + TransitionTime: timestamppb.New(time.Date(2026, 8, 21, 0, 0, 0, 0, time.UTC)), }}, Phase: pb.SandboxPhase_SANDBOX_PHASE_READY, CurrentPolicyVersion: 7, @@ -332,3 +332,27 @@ func TestConsumeWithBackpressureDoesNotRetryPermanentError(t *testing.T) { t.Fatalf("permanent error was retried or lost: %v", err) } } + +func TestOpenShell013LifecycleFieldsArePreserved(t *testing.T) { + sandbox := &pb.Sandbox{ + Metadata: &datamodelv1.ObjectMeta{Id: "sb-1", Name: "demo", Workspace: "default"}, + HostKeyFingerprint: "SHA256:public-fingerprint", + Spec: &pb.SandboxSpec{RestartPolicy: pb.SandboxRestartPolicy_SANDBOX_RESTART_POLICY_ON_FAILURE}, + Status: &pb.SandboxStatus{RestartCount: 2, NextRestartTime: timestamppb.New(time.Unix(1791540000, 0))}, + } + logs, err := lifecycleLogs(createDefaultConfig().(*Config), "0.1.3", sandbox) + if err != nil { + t.Fatal(err) + } + body := logs.ResourceLogs().At(0).ScopeLogs().At(0).LogRecords().At(0).Body().AsRaw().(map[string]any) + payload := body["source_payload"].(map[string]any) + if payload["host_key_fingerprint"] != "SHA256:public-fingerprint" { + t.Fatalf("fingerprint lost: %v", payload) + } + if payload["spec"].(map[string]any)["restart_policy"] != "SANDBOX_RESTART_POLICY_ON_FAILURE" { + t.Fatal("restart policy lost") + } + if payload["status"].(map[string]any)["restart_count"] != float64(2) { + t.Fatalf("restart count lost: %v", payload) + } +} diff --git a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciler.go b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciler.go index be1845c8..860cfbce 100644 --- a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciler.go +++ b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciler.go @@ -284,7 +284,7 @@ func (r *watchReceiver) reconcileSandbox(parent context.Context, request reconci historyComplete = false continue } - event, eventErr := newPolicySequenceEvent(logs, entry.GetTimestampMs(), entry.GetChunkId()+"\x00"+entry.GetEventType()) + event, eventErr := newPolicySequenceEvent(logs, timestampMillis(entry.GetEventTime()), entry.GetChunkId()+"\x00"+entry.GetEventType()) if eventErr != nil { r.recordPolicyConversionFailure(ctx, request, "openshell.v1.OpenShell/GetDraftHistory", eventErr) historyComplete = false diff --git a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciler_test.go b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciler_test.go index ad69b4fd..332c3709 100644 --- a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciler_test.go +++ b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciler_test.go @@ -7,9 +7,11 @@ import ( "context" "encoding/json" "errors" + "google.golang.org/protobuf/types/known/timestamppb" "reflect" "sync" "testing" + "time" pb "github.com/NVIDIA/OpenShell/sdk/go/proto/openshellv1" "go.opentelemetry.io/collector/consumer" @@ -33,7 +35,7 @@ type reconciliationGateway struct { func (g *reconciliationGateway) List(context.Context) ([]sandboxRef, error) { return nil, nil } func (g *reconciliationGateway) Watch(context.Context, string) (eventStream, error) { return nil, nil } func (g *reconciliationGateway) GatewayVersion(context.Context) (string, error) { - return "0.0.113", nil + return "0.1.2", nil } func (g *reconciliationGateway) GetDraft(context.Context, string) (*pb.GetDraftPolicyResponse, error) { g.mu.Lock() @@ -47,7 +49,7 @@ func (g *reconciliationGateway) GetDraftHistory(context.Context, string) (*pb.Ge if g.history != nil { return g.history, nil } - return &pb.GetDraftHistoryResponse{Entries: []*pb.DraftHistoryEntry{{TimestampMs: 1700000000000, EventType: "analysis_cycle", ChunkId: "chunk-1"}}}, nil + return &pb.GetDraftHistoryResponse{Entries: []*pb.DraftHistoryEntry{{EventTime: timestamppb.New(time.UnixMilli(1700000000000)), EventType: "analysis_cycle", ChunkId: "chunk-1"}}}, nil } func (g *reconciliationGateway) GetPolicyStatus(context.Context, string) (*pb.GetSandboxPolicyStatusResponse, error) { g.mu.Lock() diff --git a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciliation_state_test.go b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciliation_state_test.go index 05935316..c97ce654 100644 --- a/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciliation_state_test.go +++ b/projects/tools/openshell-exporter/receiver/watchsandboxreceiver/reconciliation_state_test.go @@ -8,9 +8,11 @@ import ( "context" "encoding/json" "fmt" + "google.golang.org/protobuf/types/known/timestamppb" "math" "strings" "testing" + "time" pb "github.com/NVIDIA/OpenShell/sdk/go/proto/openshellv1" ) @@ -77,7 +79,7 @@ func TestPolicySequenceMutationAndTruncationReplayWithDiagnostics(t *testing.T) } history[1] = &pb.DraftHistoryEntry{ - TimestampMs: history[1].GetTimestampMs(), + EventTime: history[1].GetEventTime(), EventType: history[1].GetEventType(), Description: "corrected source description", ChunkId: history[1].GetChunkId(), @@ -85,7 +87,7 @@ func TestPolicySequenceMutationAndTruncationReplayWithDiagnostics(t *testing.T) revisions[1] = &pb.SandboxPolicyRevision{ Version: revisions[1].GetVersion(), PolicyHash: "sha256:corrected", - CreatedAtMs: revisions[1].GetCreatedAtMs(), + CreatedTime: revisions[1].GetCreatedTime(), } gateway.setPolicySnapshots(history, revisions) r.reconcileSandbox(context.Background(), request) @@ -327,7 +329,7 @@ func testPolicyHistory(count int) []*pb.DraftHistoryEntry { entries := make([]*pb.DraftHistoryEntry, 0, count) for index := 1; index <= count; index++ { entries = append(entries, &pb.DraftHistoryEntry{ - TimestampMs: int64(1700000000000 + index), + EventTime: timestamppb.New(time.UnixMilli(int64(1700000000000 + index))), EventType: "analysis_cycle", Description: fmt.Sprintf("history entry %d", index), ChunkId: fmt.Sprintf("chunk-%d", index), @@ -342,7 +344,7 @@ func testPolicyRevisions(count int) []*pb.SandboxPolicyRevision { revisions = append(revisions, &pb.SandboxPolicyRevision{ Version: uint32(version), PolicyHash: fmt.Sprintf("sha256:policy-%d", version), - CreatedAtMs: int64(1700000000000 + version), + CreatedTime: timestamppb.New(time.UnixMilli(int64(1700000000000 + version))), }) } return revisions diff --git a/projects/tools/openshell-exporter/source.json b/projects/tools/openshell-exporter/source.json new file mode 100644 index 00000000..f0a0c1a8 --- /dev/null +++ b/projects/tools/openshell-exporter/source.json @@ -0,0 +1,89 @@ +{ + "source_commit": "75a41db6be6cc6ad160e3619ad09270d1cdb5b1d", + "manifest_sha256": "62b449a3108bfc14dabf29e476b84f143de6a1d5333057c57642200e6c433c34", + "files_sha256": { + ".dockerignore": "7015c01ec785bb29a93a1bb9165cf8a997ea698d91c4ef8ab68b296cc7d9cf7e", + ".gitignore": "58ba682331c688ea5155ddb7212ebf288a306b8f6a4e829946c6fe89484c6af3", + "AGENTS.md": "c6cf73e858bae62f02e1043374ffcdf7b83b59e0446eb74b9b7ad15f2a84bd9c", + "Dockerfile": "a0a3f040970b4e9807e87c1eb9b7fa39cca18a818ed29a5e533ee9599dbca3d9", + "LICENSE": "b967d1c87b93b7d61ebcf4f8737e6ad79e5433e743e49dff395a36fb3c327047", + "NOTICE": "aa27dfad6a88c162b55bb679a8f3c7fdfdc6fbcc19ee9d6782ff9079c3520f7f", + "README.md": "5a697d39f5791fdd256ea6114bd26bb9783baebd7e94da590ba5eb13c097be8c", + "VERSION": "badd136bbecfaf2a71a5b02d71570957053b439e91cd1d3a742fe1c671f47818", + "cmd/healthcheck/main.go": "c43de30363a7f91f5c8ee1b5d5a2cc383e90ab9d3cce824998a29971e27a64e6", + "cmd/healthcheck/status.go": "af3995bdb6573f61d87084a474de64cebb6b891f5a6bdf83a238357e1d5b6343", + "cmd/healthcheck/status_test.go": "1a581dacd90844c5865c95605e7b65377b368bad0b6e46f25f440ce2ed42cc49", + "cmd/openshell-event-exporter/components.go": "94230ae633d5fdaaeabc03fca96db5d6b71bc89c3ecc150f68c8eff8799485e2", + "cmd/openshell-event-exporter/main.go": "b37c99b25d383d2d74f7a2da353bcaed8f3633f4d15fed28f19dd0bd61805ab8", + "cmd/openshell-event-exporter/main_others.go": "1262519dbff8841e66027c7fc4b65f08bf79444f996c594378f2ba4bcc1cdde2", + "cmd/openshell-event-exporter/main_windows.go": "ab553901e36b01737b03922e41956bc5fb73c1c733c5fbd44dd55f1b8ac8e12f", + "config.yaml": "4a18e7ece635ebe9a52319656aca8067bf3e6be9d7319e00c12e979d510cff33", + "exporter/cloudeventsexporter/acknowledgement_test.go": "79c98ffe74d7afa3aa85d79c94e3a4d4746caddb06b8cb1c881833e7c0e30e4e", + "exporter/cloudeventsexporter/config.go": "de6fa18dd2852b62ebf69311d956f0aed7860c995853f3ed81e7bfd87f5bef40", + "exporter/cloudeventsexporter/config_test.go": "239c3dce2722ece13a7922b09849cb4f52e7b14c516ea8b355423d41c5d8f086", + "exporter/cloudeventsexporter/exporter.go": "23e594f6ce3ba9d82b3078204600c3a06ff6f3fc844f7f4309908cf4da49c33d", + "exporter/cloudeventsexporter/exporter_test.go": "b7ceb7b13d469a1817333be8b139cc0b490a643bd221500bda2fac8a7129cffa", + "exporter/cloudeventsexporter/factory.go": "db9ed9ad0c9425b1c392c7251f6be2433f547d5d4a9ff0bc5b645a3a2e0919a8", + "exporter/cloudeventsexporter/lifecycle_security_test.go": "22e16396765eb3d7b9d983df00bf12993aac872c52ca1fcab8f95296122cc1e7", + "exporter/cloudeventsexporter/metrics.go": "38e9a2e1e92d6b2994b43fc869596feba588d9ffd76b021f671fa306f4c95e99", + "extension/storagehealthextension/config.go": "b99382df8c903800608a38a9a0fa135383b65e6ca49c532bd917aa07b6132c84", + "extension/storagehealthextension/extension.go": "449d05ec74b695f0d2271a599f4eea0fda87c78039be9d51e62f8dea34bdaa3d", + "extension/storagehealthextension/extension_test.go": "278d03e24e769fa311d266b7f3dc3b7c93a96ba38ed815fdfdb2fad3e53d0395", + "extension/storagehealthextension/factory.go": "ad199adc740968fe96e18d2c4d7f0976c69c54d3d6ba1934f50d48b5d1232ab9", + "go.mod": "c154f31e2dcdc55780315681a153aafd4e2b72c2383678271cd93e07f5bcf02f", + "go.sum": "f3adebb153970fe5cc3bf6e31506ad995b00a355c42389b09c71fab71cdaeb50", + "http.config.yaml": "c8b3a95ddffee2ff9a9f4acbdc0a499442c0c2395be8b4aab56d06f46463172b", + "processor/evidencecontractprocessor/config.go": "bb61ca14cfa1b8eedded7a297b4f0f851834683bd784fbe1378bbf35d9becf76", + "processor/evidencecontractprocessor/factory.go": "237932a2041ea956507c3be837cd7ee10f2bf94418285589374ef3fe922f2e55", + "processor/evidencecontractprocessor/processor.go": "3f5193032c9f67348443259c98841f915e25d5914ef9fde9adbbbe71b56181a4", + "processor/evidencecontractprocessor/processor_test.go": "1bcb7a83c5c434bf3f6ede97732a5677755846910584d42eb1c37bcc9803961d", + "processor/openshellprocessor/attribute_redaction_test.go": "c7d8c718141c76d8a2fe2f206963d32a1298f0899da3082875644ce17dc9bfc9", + "processor/openshellprocessor/config.go": "5dfe37c938d36e916d67c6f3c33601621bff8afb3e503b4e771d0e9955b3db00", + "processor/openshellprocessor/context.go": "ca8b3b80c876703de36919c01831bde6b633bb96b41451e024389a344991ffa9", + "processor/openshellprocessor/context_test.go": "03013e6c47494a01f508210e2474b186744864f6a2fa196c4ac7313a9625e8a5", + "processor/openshellprocessor/envelope.go": "3e719a309c46dbb0113c808d3266a6a2ebec5afae6358d5132dcdf7f9fd40ec1", + "processor/openshellprocessor/factory.go": "5b8f07b21fa6ace062ae6adfa6254e9141821708fc34162e08cecd85711615a0", + "processor/openshellprocessor/forwarded_test.go": "f4808a8eea7b9bd08acb705bb81b392677e0326d0d87746b6b3b11c427fc9505", + "processor/openshellprocessor/identity.go": "73e53fb46ed51521e2f61e405ce3ff3035f3954012a57bb4ce76ea9244866f70", + "processor/openshellprocessor/metrics.go": "3453caaaefb5f51ce1e7562258d6c035cd4f9b7894a369f3e5f6c84fbca344bb", + "processor/openshellprocessor/metrics_test.go": "9031ac116d76af2368bba3ed2fd6d10ae5c4e7059e20d72cde23214dfdc5045c", + "processor/openshellprocessor/processor.go": "b4b4fc8db92f902a4aee163e8a5d30a60ff1c28f3e864d4acfb44767dbe26ea2", + "processor/openshellprocessor/processor_test.go": "1aafa68690ed75586ec9c548289655e863b3906098f3752127ba5ab035a4612d", + "processor/openshellprocessor/redaction.go": "9053d95c60f5ee68dde308c9df315faa466aaece8c00f257d9e3f3e12eadac0d", + "processor/openshellprocessor/relay_file_test.go": "51b3bd3e683c8ffd214db8ad9ed1a97cb7cd238c1704793594cb0a7c93734337", + "processor/openshellprocessor/source_capability.go": "3617f8cb0a0e7676397d14445c0d60537efeee76e832b5f194f953a475473408", + "processor/openshellprocessor/source_capability_test.go": "760bd4d7b6d98eab04844c28ce3d6d7ff5209e6f3ea63a4b7ad47f0b29d6615a", + "processor/openshellprocessor/validation.go": "4c0b6653f69f559854626dcf6b344f7643a99ca8b7ba85fe92f6257d40522289", + "processor/relayprocessor/config.go": "2f09b9b53ee1b9993b3b5fc291b50266d5fe57ab48711c8715fbd4257e7e3072", + "processor/relayprocessor/factory.go": "15a1aa681385e14391d529e27af5332f335e0d06b2610f9f25c2af43c5089b17", + "processor/relayprocessor/metrics.go": "5bba63d855e862502086f9a146647ad62e76d5e15a1e627e90e196c3d2f85072", + "processor/relayprocessor/metrics_test.go": "2146540845fdf849ff535d399ab292a790915a2611b1e76a758a27ecffd60df7", + "processor/relayprocessor/native_test.go": "36f10f62f7df36e56f3f72a1874ea0ff64cbcad08134cfddf24bcf11c140e78e", + "processor/relayprocessor/processor.go": "2e0ba3864ff29fedb216552a893017dd7da5d2186fdad31551a2886be0d375c2", + "processor/relayprocessor/processor_test.go": "06620001c6d846026b848945c0211efdc0012f9fe9788d3ff93cd03d60c871cc", + "processor/relayprocessor/source_capability_test.go": "7859077a182c4de463be83ea2e60c8a32b6c073bdef654c8a9da3ba6506a0c0d", + "receiver/watchsandboxreceiver/client.go": "46695742bad5b21b060ce327c46a6e445533d1d8ce3f9994e9e8b85886c2d45c", + "receiver/watchsandboxreceiver/client_security_test.go": "725e0aac585744280b5de226c9667459b6b69aca88c341e576dd1d514127761b", + "receiver/watchsandboxreceiver/config.go": "73651b1f43a2c721dbc6c2fa2aaf60f3bcb4fe9cdd93e745f8deb9c1faac5ba5", + "receiver/watchsandboxreceiver/config_test.go": "90613aacaeeb0a43dfaa078420044a97ed65574d315a18395fa98a17bbd9b66a", + "receiver/watchsandboxreceiver/convert.go": "a8e3766feeb588396d4edc912da0fc0621b973390fa00a1baa5de401842f5892", + "receiver/watchsandboxreceiver/discovery_cleanup_test.go": "135c7b61266268c95b9cfac4acb7ebe7036330e35ecc791ecc653dbf7894d34b", + "receiver/watchsandboxreceiver/factory.go": "ab2f8f22860b828414a8cbd808158acc819ff4b37017178564db5ec54cad697b", + "receiver/watchsandboxreceiver/metrics.go": "c97835bd0c496a767c34fe08f74485ddc4699329a2fd787fa49dde4094192a26", + "receiver/watchsandboxreceiver/metrics_test.go": "85a4c247d50b50cd09f31a3fbeb3768d686fda42a23515c5190028deeb529aea", + "receiver/watchsandboxreceiver/normalizer_delivery_test.go": "5b037721214d7ce96c34896d95f3d44fecae1d66d62b28fee596912530f839a5", + "receiver/watchsandboxreceiver/pagination_test.go": "4917966b7d315f71b99ea8d87c10e208f8499cbf47bd529a1e54808c373a2769", + "receiver/watchsandboxreceiver/policy_convert.go": "f8e19b68edd8d5fcefe3a06ead9e64372a1cf1adc6ea9d963b41317379021762", + "receiver/watchsandboxreceiver/policy_convert_test.go": "07ecd50435f8b37eb15793d99afd0a71921949e56df956de02246c80d495eead", + "receiver/watchsandboxreceiver/receiver.go": "b7036599a1905afadaab267ae8581939566542f0591d5286e8a0a7cde4abbfa3", + "receiver/watchsandboxreceiver/receiver_lifecycle_test.go": "3579f60dd9153adbd3f568a4cd1a47024311e09db66898d7ee70d3f89d6cff19", + "receiver/watchsandboxreceiver/receiver_test.go": "80f64e587ca1840e301f9e391d9579a9b4fe064775986db32809a39dea1de0be", + "receiver/watchsandboxreceiver/reconciler.go": "d0f4dc16e9ee0cfd5a7407c8165cb6fd617f3de50f5645e14b99adbb06e75279", + "receiver/watchsandboxreceiver/reconciler_test.go": "490e48632e9a2f7db27c552050f7a14e002e7298ef7b50c0cc2057d8074cd16b", + "receiver/watchsandboxreceiver/reconciliation_state.go": "1175c8c7827197ba1911e963d33b7b2b50a65bef4f5ad5369a20b421f5b212f1", + "receiver/watchsandboxreceiver/reconciliation_state_test.go": "96d34ffedf6b4f04590310cc1b8aedfe8f92427e8c6b8fc64c62bdc17aeaa13d", + "template.config.yaml": "5661f0916c1e2fd9acd65e6fde806ff2fcb57d7a8da920bc62ae444fcee3da66", + "testdata/ocsf/ai-inference.json": "3b65789a687b8b13928c8789bfa399c649274a17c9aa28b1d6d2897d7c11f0de", + "testdata/ocsf/network-denied.json": "1628c60d9fed22a64c7b9572fb2b190c5fd881028fd8e1756fc8aac8f0e006b1" + } +} diff --git a/projects/tools/openshell-exporter/template.config.yaml b/projects/tools/openshell-exporter/template.config.yaml index 668872fd..1426f024 100644 --- a/projects/tools/openshell-exporter/template.config.yaml +++ b/projects/tools/openshell-exporter/template.config.yaml @@ -1,4 +1,4 @@ -# OpenShell Event Exporter v0.0.5-rc.1 / Collector v0.160.0 +# OpenShell Event Exporter v0.0.5-rc.1 / Collector v0.162.0 # Configuration reference: every exporter-owned setting and examples for all # component types included in the exporter image. Advanced upstream transport # and parser settings are outside this reference. Values are examples, not a @@ -55,6 +55,64 @@ extensions: bearertokenauth/internal: filename: /run/secrets/internal-token receivers: + file_log/gateway_ocsf: + include: [/input/gateways/*/gateway-ocsf.jsonl*] + start_at: beginning + storage: file_storage/checkpoints + retry_on_failure: + enabled: true + initial_interval: 1s + max_interval: 30s + max_elapsed_time: 0s + include_file_path: true + include_file_path_resolved: true + include_file_record_offset: true + include_file_record_number: true + on_truncate: read_whole_file + max_log_size: 8MiB + max_log_size_behavior: split + attributes: + openshell.acquisition.kind: ocsf.gateway + openshell.acquisition.source_instance: gateway-ocsf-jsonl + operators: + - type: json_parser + parse_from: body + parse_to: body + on_error: send + file_log/supervisor_ocsf: + include: [/input/supervisors/*/stderr.log*] + start_at: beginning + storage: file_storage/checkpoints + retry_on_failure: + enabled: true + initial_interval: 1s + max_interval: 30s + max_elapsed_time: 0s + include_file_path: true + include_file_path_resolved: true + include_file_record_offset: true + include_file_record_number: true + on_truncate: read_whole_file + max_log_size: 8MiB + max_log_size_behavior: split + attributes: + openshell.acquisition.kind: ocsf.supervisor + openshell.acquisition.source_instance: supervisor-stderr + operators: + # Input is the unwrapped platform log stream (docker/podman/kubectl logs). + # Select only the structured copy; retain malformed marked payloads. + - type: filter + expr: 'body not matches "^\\S+ OCSF-JSON(?: |$)"' + - type: regex_parser + regex: '^\S+ OCSF-JSON ?(?P.*)$' + on_error: send + - type: move + from: attributes.record + to: body + - type: json_parser + parse_from: body + parse_to: body + on_error: send otlp/nemo_relay: protocols: grpc: @@ -236,6 +294,8 @@ processors: # adding patterns. Identity is calculated before redaction. openshell: source_profiles: + - ocsf.gateway + - ocsf.supervisor - ocsf.file - ocsf.forwarded - openshell.log @@ -611,6 +671,8 @@ service: logs/files: receivers: - file_log/openshell_ocsf + - file_log/gateway_ocsf + - file_log/supervisor_ocsf processors: - memory_limiter - openshell