Repository navigation
Add in-flight and richer duration Prometheus metrics on all Porch API operations - #1198
JamesMcDermott wants to merge 14 commits into
Conversation
✅ Deploy Preview for kpt-porch canceled.Built without sensitive environment variables
|
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Unresolved critical and moderate findings affect metric correctness, test reliability, and existing performance dashboards.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 3
Open (17)
Use approval resource label for in-flight metric · New Classify deletion errors without unsafe type assertion · New Validate all required pods before dereferencing · New Use consistent resource labels for in-flight and duration metrics · New Record successful not-found cleanup with success outcome · New Label lifecycle duration with resulting lifecycle · New Capture render and stale-path errors in operation outcome · New Capture list failures in deferred operation outcome · New Avoid shadowing errors in delete outcome instrumentation · New Avoid shadowing list errors in duration instrumentation · New Handle missing scrape result before indexing · New Defer metric evaluation until Eventually polling · New Clear historical samples before settled-state assertion · New Make CreateL log errors without failing tests · New Preserve performance histogram or update dashboard consumers · New Instrument malformed Create requests before type assertion · New Instrument namespace validation failures · New
What changed in this PR
Adds richer Porch API duration metrics and in-flight operation tracking across REST and controller paths, with expanded E2E coverage and monitoring fixes.
Changes:
- Adds operation, outcome, lifecycle, and package-revision labels.
- Instruments REST and controller operations with in-flight gauges.
- Updates telemetry helpers, tests, and monitoring paths.
| File | Description |
|---|---|
test/performance/metrics_utils.go |
Routes performance durations through telemetry. |
test/e2e/suiteutils/suite.go |
Adds logging-oriented client helpers. |
test/e2e/suiteutils/suite_utils.go |
Refactors metrics collection and parsing. |
test/e2e/crd/suite_test.go |
Initializes the Kubernetes client. |
test/e2e/crd/metrics_test.go |
Adds controller metrics tests. |
test/e2e/crd/helpers_test.go |
Adds deletion polling support. |
test/e2e/api/metrics_test.go |
Adds API metrics and in-flight tests. |
scripts/monitoring/deploy-monitoring.sh |
Fixes monitoring resource paths. |
pkg/registry/porch/packagerevisionresources.go |
Instruments resource operations. |
pkg/registry/porch/packagerevisionresources_update_test.go |
Updates resource-operation mocks. |
pkg/registry/porch/packagerevisionresources_test.go |
Updates lifecycle mocks. |
pkg/registry/porch/packagerevision.go |
Instruments PackageRevision operations. |
pkg/registry/porch/packagerevision_test.go |
Updates revision-operation mocks. |
pkg/registry/porch/packagerevision_approval.go |
Instruments approval operations. |
pkg/registry/porch/packagerevision_approval_test.go |
Updates approval-operation mocks. |
pkg/registry/porch/packagecommon.go |
Returns typed updated revisions. |
internal/telemetry/metrics.go |
Defines enriched metrics. |
internal/telemetry/metrics_test.go |
Updates telemetry tests. |
controllers/packagerevisions/pkg/controllers/packagerevision/source.go |
Refactors source action selection. |
controllers/packagerevisions/pkg/controllers/packagerevision/source_test.go |
Tests source action selection. |
controllers/packagerevisions/pkg/controllers/packagerevision/render.go |
Instruments render operations. |
controllers/packagerevisions/pkg/controllers/packagerevision/packagerevision_controller.go |
Instruments reconciliation. |
controllers/packagerevisions/pkg/controllers/packagerevision/ownership.go |
Instruments deletion cleanup. |
controllers/packagerevisions/pkg/controllers/packagerevision/metadata.go |
Instruments metadata updates. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
31ccc38 to
d4d35c0
Compare
| telemetry.RecordRequestCount(ctx, prrTelemetryName, op.AllCaps, telemetry.APIVersionV1Alpha1) | ||
|
|
||
| name, resourceSelector, err := selector.ParsePRRGet(rawName) | ||
| parsedName, resourceSelector, err := selector.ParsePRRGet(pkgRevK8sName) |
There was a problem hiding this comment.
You have a lot of changes like this which, while improving the readability of the PR, are not related tot he actual telemetry changes. They make the PR much bigger and harder to review.
| return false, err | ||
| } | ||
|
|
||
| saveErr := func(loseableErr error) error { err = loseableErr; return err } |
There was a problem hiding this comment.
This line can be deleted
| telemetry.RecordControllerOperation(ctx, prrTelemetryName, op.AllCaps, op.TitleCase+prrTelemetryName, time.Since(start), err, pr.Spec.Lifecycle, &key) | ||
| }() | ||
|
|
||
| // Create draft and write updated resources. |
There was a problem hiding this comment.
Add this line here:
var draft repository.PackageRevisionDraftSlim
| }() | ||
|
|
||
| // Create draft and write updated resources. | ||
| draft, err := r.ContentCache.CreateDraftFromExisting(ctx, repoKey, pr.Spec.PackageName, pr.Spec.WorkspaceName) |
There was a problem hiding this comment.
| draft, err := r.ContentCache.CreateDraftFromExisting(ctx, repoKey, pr.Spec.PackageName, pr.Spec.WorkspaceName) | |
| draft, err = r.ContentCache.CreateDraftFromExisting(ctx, repoKey, pr.Spec.PackageName, pr.Spec.WorkspaceName) |
| // UpdateResources is a full replace — include all files to avoid data loss. | ||
| resources["Kptfile"] = string(updatedKfBytes) | ||
| log.Info("metadata sync writing resources", "resourceCount", len(resources)) | ||
| if err := draft.UpdateResources(ctx, resources, "metadata-sync"); err != nil { |
There was a problem hiding this comment.
| if err := draft.UpdateResources(ctx, resources, "metadata-sync"); err != nil { | |
| if err = draft.UpdateResources(ctx, resources, "metadata-sync"); err != nil { |
| if err != nil { | ||
| log.Error(err, "failed to create draft") | ||
| return false, err | ||
| return false, saveErr(err) |
There was a problem hiding this comment.
| return false, saveErr(err) | |
| return false, err |
| if err := draft.UpdateResources(ctx, resources, "metadata-sync"); err != nil { | ||
| log.Error(err, "failed to write resources") | ||
| return false, err | ||
| return false, saveErr(err) |
There was a problem hiding this comment.
| return false, saveErr(err) | |
| return false, err |
| if err := r.ContentCache.CloseDraft(ctx, repoKey, draft, 0); err != nil { | ||
| log.Error(err, "failed to close draft") | ||
| return false, err | ||
| return false, saveErr(err) |
There was a problem hiding this comment.
| return false, saveErr(err) | |
| return false, err |
There was a problem hiding this comment.
Please check other places where this saveErr pattern is used and change the code to not use local block err variables.
| saveErr := func(loseableErr error) error { err = loseableErr; return err } | ||
| op := telemetry.Operations.Update | ||
| start := time.Now() | ||
| key := telemetry.ParsePkgRevK8sName2Key(pr.Namespace, pr.Name) |
There was a problem hiding this comment.
What does this function do that key.PkgRevK8sName2Key does not do?
| defer telemetry.TrackInFlightControllerOperation(ctx, prrTelemetryName, op.AllCaps, op.TitleCase+prrTelemetryName, pr.Spec.Lifecycle, &key)() | ||
| defer func() { | ||
| telemetry.RecordControllerOperation(ctx, prrTelemetryName, op.AllCaps, op.TitleCase+prrTelemetryName, time.Since(start), err, pr.Spec.Lifecycle, &key) | ||
| }() |
There was a problem hiding this comment.
I'd really like to boil this down to two function calls.
- enhance existing API-call-duration histogram to include more information from Porch perspective - making it a Porch-API-operation-duration metric - add new metric to track in-flight (currently-in-progress) Porch operations Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
- wire porch_in_flight_api_operations gauge into v1alpha2 controller
reconciler operations
- track lifecycle, source, metadata-sync, render, and delete
reconcile paths
- Published lifecycle transitions recorded under PackageRevisionApproval.
- refactor applySource into selectPackageSourceAction + execution so the
operation type (init/clone/copy/upgrade) is known for telemetry; update
source_test.go accordingly.
- new E2E tests TestAPIOperationDurationMetricExists, TestAPIOperationDurationLabels,
and TestInFlightOperationsMetric in v1alpha1 suite
- counterparts in v1alpha2 suite testing against PorchControllerMetrics.
- small fix in deploy-monitoring.sh config paths
Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
in case of errors - fix unit tests to account for extra calls to GetPackageRevision(), Lifecycle(), etc. Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
- cover cases where error occurs but is hidden from telemetry calls - prevent recording errored operations as success - revisits lifecycle acquisition for telemetry calls - make it as accurate as possible without extra queries to Git or database - changes to packagecommon.updatePackageRevision() to include existing lifecycle in returns - only way to get it back into higher-level Update() methods to include in telemetry Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
- also fix build Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
…hods - as per SonarQube duplication report Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
- wire contexts into metric recording functions - add explicit saveErr calls into API methods' early returns - ensure packageRevisions.Create() has in-flight recording for earliest possible return - ensure controller's reconcileLifecycle doesn't leak in-flight counter for ContentCache.Get() - when recording in case package revision key is nil, at least get namespace from context and record that - for LIST PackageRevision, pluralise telemetry name to get "ListPackageRevisions" operation Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
- also add dedicated function for name-to-key parsing to get PackageRevisionKeys for metrics Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
Signed-off-by: James McDermott <james.j.mcdermott@ericsson.com>
490f9f5 to
63caa82
Compare
|





Description
porch_api_call_duration_seconds) into a Porch-API-operation-duration metricoperationoperation_outcomelifecycle_afternamespacerepositorypackageworkspace_nameporch_in_flight_api_operationsgauge (anInt64UpDownCounter) to trackcurrently-in-progress Porch operations
per-operation/outcome/lifecycle
operations
RecordAPIOperationDuration/RecordControllerOperationTrackInFlightOperation/TrackInFlightControllerOperation, which increments the in-flight gauge at start and decrements it via a deferred closure on completion (including error paths).Type of Change
Checklist
Testing Instructions (Optional)
make test1.
make setup-dev-env run-in-kind-db-cache test-e2e1.
make setup-dev-env run-in-kind-v1alpha2 test-e2e-crd/metricsendpoint and confirm the presence ofporch_api_call_duration_seconds_{bucket,count,sum}with the new labels andporch_in_flight_api_operationssettling to 0 once operations complete.Additional Notes (Optional)
porch_in_flight_api_operationsin-flight proof (the spammer/scraper approach) is only exercised in the v1alpha1 (API) suite; the v1alpha2 (CRD) suite asserts steady-state and per-operation presence but not mid-flight increment, because controller operations are driven by asynchronous reconciliation rather than synchronous, re-runnable REST calls.source_test.goasserts the selected source action viafmt.Sprintf("%#v", ...)function-valuecomparison; this is intentional but relies on stable function formatting.
AI Disclosure
If so, please describe how: