Skip to content

Network observer metric isolation - #2578

Open
c-kruse wants to merge 4 commits into
skupperproject:mainfrom
c-kruse:network-observer-metric-isolation
Open

c-kruse wants to merge 4 commits into
skupperproject:mainfrom
c-kruse:network-observer-metric-isolation

Conversation

@c-kruse

@c-kruse c-kruse commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Resolves #2566

Summary by CodeRabbit

  • New Features

    • Added network and observer identity labels to network observer metrics.
    • Added configuration options for network and observer IDs, including Helm and command-line settings.
    • Added secure Prometheus query scoping so requests are limited to supported metrics and the configured network.
    • Added support for centrally collecting metrics from multiple Skupper networks.
  • Bug Fixes

    • Improved Prometheus request validation and handling for invalid methods, formats, queries, and request bodies.
  • Documentation

    • Documented network ID configuration and metric-label behavior.

Add configurable network and observer identities to the network observer
to fully qualify metrics.

Signed-off-by: Christian Kruse <christian@c-kruse.com>
Restrict the internal prometheus proxy endpoint to relevant metrics.
Normalizes the http requests, enforces an allow-list of metric names and
constrains all selectors to the observer's configured network_id.

Signed-off-by: Christian Kruse <christian@c-kruse.com>
Pass the namespace as the network ID so observers sharing the host
Prometheus use separate metric partitions.

Signed-off-by: Christian Kruse <christian@c-kruse.com>
Render the network-id argument when networkId is set. Document its
purpose for users collecting metrics.

Signed-off-by: Christian Kruse <christian@c-kruse.com>
@coderabbitai

coderabbitai Bot commented Sep 17, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 9e489371-6356-4921-aa80-3118d207072a

📥 Commits

Reviewing files that changed from the base of the PR and between d562c4c and 95cece4.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (15)
  • charts/network-observer/README.md
  • charts/network-observer/templates/deployment.yaml
  • charts/network-observer/values.yaml
  • cmd/network-observer/config.go
  • cmd/network-observer/handlers.go
  • cmd/network-observer/handlers_test.go
  • cmd/network-observer/internal/collector/collector.go
  • cmd/network-observer/internal/collector/metrics.go
  • cmd/network-observer/internal/collector/metrics_test.go
  • cmd/network-observer/main.go
  • cmd/network-observer/prometheus.go
  • cmd/network-observer/prometheus_test.go
  • go.mod
  • internal/nonkube/network-observer/containers.go
  • internal/nonkube/network-observer/containers_test.go

Included review availability: Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📝 Walkthrough

Walkthrough

The network observer now labels metrics with network and observer identities. Its Prometheus proxy validates, allow-lists, and network-scopes queries. Helm and non-Kubernetes deployments pass the network ID to the observer.

Changes

Network observer metric isolation

Layer / File(s) Summary
Metric identity and registerer propagation
cmd/network-observer/config.go, cmd/network-observer/main.go, cmd/network-observer/internal/collector/*
The observer creates labeled Prometheus registration with network_id and observer_id. Collector registration accepts the prometheus.Registerer interface.
Prometheus proxy validation and network scoping
cmd/network-observer/prometheus.go, cmd/network-observer/handlers.go, cmd/network-observer/*_test.go, go.mod
The proxy validates requests, allow-lists metrics and query forms, injects the configured network matcher, and forwards only accepted queries.
Deployment network ID wiring and documentation
charts/network-observer/*, internal/nonkube/network-observer/*
Helm and non-Kubernetes deployments pass network IDs to the observer. Helm values and documentation describe the metric label.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Bug fix · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant Console
  participant NetworkObserver
  participant CommonPrometheus
  Console->>NetworkObserver: send Prometheus query
  NetworkObserver->>NetworkObserver: validate and add network_id matcher
  NetworkObserver->>CommonPrometheus: forward scoped query
  CommonPrometheus-->>NetworkObserver: return results
  NetworkObserver-->>Console: return response
Loading

Merge Risk: ⚪ Minimal · up to 95cec

The console’s current Prometheus requests remain compatible with the new network-scoping policy, with no actionable merge risk identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 17 functions across 11 files. (4 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: isolating network observer metrics by network and observer identity.
Linked Issues check ✅ Passed PR #2578 meets the coding requirements in issue #2566. It adds network_id and observer_id labels to observer metrics, defaults the IDs as required, derives non-Kubernetes IDs from namespaces, and …
Out of Scope Changes check ✅ Passed The changes stay within issue #2566. The registerer-interface updates enable labeled metric registration, the MetricsQL dependency enables PromQL validation, and the documentation and tests support th…
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 17 functions across 11 files. (4 skipped: 4 unsupported.)

  • Fix all pre-merge checks with AI

Comment @coderabbitai help to get the list of available commands.

Name: fmt.Sprintf("%s-skupper-network-observer", namespace),
Image: images.GetNetworkObserverImageName(),
Command: []string{
fmt.Sprintf("-network-id=%s", namespace),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this is necessary, currently, targets defined in prometheus are labeled with their namespace:

~$ curl -s http://localhost:9091/api/v1/targets | jq .
{
  "status": "success",
  "data": {
    "activeTargets": [
      {
        "discoveredLabels": {
          "__address__": "localhost:9000",
          "__meta_filepath": "/etc/prometheus/targets/east.json",
          "__metrics_path__": "/metrics",
          "__scheme__": "http",
          "__scrape_interval__": "15s",
          "__scrape_timeout__": "10s",
          "job": "skupper-network-observers",
          "namespace": "east"
        },
        "labels": {
          "instance": "localhost:9000",
          "job": "skupper-network-observers",
          "namespace": "east"
        },
        "scrapePool": "skupper-network-observers",
        "scrapeUrl": "http://localhost:9000/metrics",
        "globalUrl": "http://li-12aec04c-3404-11b2-a85c-c8b28bd65981.ibm.com:9000/metrics",
        "lastError": "",
        "lastScrape": "2026-09-18T19:42:10.665199492Z",
        "lastScrapeDuration": 0.00286493,
        "health": "up",
        "scrapeInterval": "15s",
        "scrapeTimeout": "10s"
      },
      {
        "discoveredLabels": {
          "__address__": "localhost:9001",
          "__meta_filepath": "/etc/prometheus/targets/west.json",
          "__metrics_path__": "/metrics",
          "__scheme__": "http",
          "__scrape_interval__": "15s",
          "__scrape_timeout__": "10s",
          "job": "skupper-network-observers",
          "namespace": "west"
        },
        "labels": {
          "instance": "localhost:9001",
          "job": "skupper-network-observers",
          "namespace": "west"
        },
        "scrapePool": "skupper-network-observers",
        "scrapeUrl": "http://localhost:9001/metrics",
        "globalUrl": "http://li-12aec04c-3404-11b2-a85c-c8b28bd65981.ibm.com:9001/metrics",
        "lastError": "",
        "lastScrape": "0001-01-01T00:00:00Z",
        "lastScrapeDuration": 0,
        "health": "unknown",
        "scrapeInterval": "15s",
        "scrapeTimeout": "10s"
      }
    ],
    "droppedTargets": [],
    "droppedTargetCounts": {
      "skupper-network-observers": 0
    }
  }
}

~$ curl -s 'http://localhost:9091/api/v1/query?query=up' | jq '.data.result'
[
  {
    "metric": {
      "__name__": "up",
      "instance": "localhost:9000",
      "job": "skupper-network-observers",
      "namespace": "east"
    },
    "value": [
      1789760604.794,
      "1"
    ]
  },
  {
    "metric": {
      "__name__": "up",
      "instance": "localhost:9001",
      "job": "skupper-network-observers",
      "namespace": "west"
    },
    "value": [
      1789760604.794,
      "1"
    ]
  }
]

@c-kruse c-kruse Sep 18, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nluaces at least in this iteration we do need it. I recall that our original plan involved the namespace label. It was a two-step plan: inject a namespace label in the scrape configuration and then filter metrics on that label for the console's queries.

The idea behind adding a network-id to the network-observers on system sites is that it accomplishes both pieces with a single flag: partition metrics from different observers in the database, then automatically filter console queries down to the right partition. The original namespace label plan would work just as well for system sites. For kube deployments where the user decides to centrally collect metrics (system sites too, I suppose) I think it is better to prescribe a scheme (network_id, observer_id) rather than leaving it up to the user to pick how they want to partition and query metrics from many observers.

That said, keeping both the namespace and the network-id labels aught to be fine. It may even be nice as you've demonstrated, it adds context to the targets: localhost:9000 doesn't mean much to me without tracking it down running netstat, but namespace=east is a good hint.

Does that make sense?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Common Prometheus DB for Network Observer and Console

2 participants