atenet: preserve cold resume outcome and fallback empty template dimension - #1482
Conversation
| // Note: "unknown" is syntactically a legal atespace/template name; like | ||
| // ate.sandbox.class="unknown", this trades potential collision with a real | ||
| // object named "unknown" for maintaining a bounded, non-empty metric dimension. | ||
| const TemplateUnknown = "unknown" |
There was a problem hiding this comment.
Can we have a Normalize for this, like for the rest of unknowns?
There was a problem hiding this comment.
Added normalization in ateattr, following the pattern of NormalizeSandboxClass and NormalizeOperationName, and switched recordRouteDuration to use it. Added unit tests for it in ateattr_test.go as well.
| // - ResumeOutcomeJoined ("joined"): Cold activation joiner (resumed == true or attempt errored, caller's reqID != leaderID). | ||
| outcome := ResumeOutcomeNone | ||
| if callRes.resumed { | ||
| if callRes.resumed || callRes.err != nil { |
There was a problem hiding this comment.
A NotFound never triggered anything, but it now gets resume="triggered". Can we add a new value like unattempted for definitive errors, and keep triggered/joined for the capacity ones where a resume really was in flight?
There was a problem hiding this comment.
Great catch. Added RouterResumeUnattempted = "unattempted" to ateattr and registered it in metrics.yaml.
| // - ResumeOutcomeNone ("none"): resumed == false, actor was already active/running. | ||
| // - ResumeOutcomeTriggered ("triggered"): Cold activation leader (resumed == true, caller's reqID == leaderID). | ||
| // - ResumeOutcomeJoined ("joined"): Cold activation joiner (resumed == true, caller's reqID != leaderID). | ||
| // - ResumeOutcomeNone ("none"): resumed == false and err == nil, actor was already active/running. |
There was a problem hiding this comment.
Here, + the PR says it reserves none for warm hits, but we have multiple places it still returns none on a cancel.
There was a problem hiding this comment.
Updated. Set none only when actual warm hits where the actor was already running.
| The atespace of the ActorTemplate of the actor, or "unknown" if the | ||
| request failed before template resolution. |
There was a problem hiding this comment.
Two things:
- "if the request failed" misses egress. Egress succeeds and still has no template, so it gets unknown too. Result's comment in extproc/handler.go phrases it right, can we mirror that?
- 7 metrics share this brief but only the router sends unknown. And line 72 plus bounded-or-catalog-scoped in docs/metrics/substrate.yaml both say these labels only ever name something an operator made. unknown doesn't, so it needs writing down there.
There was a problem hiding this comment.
Updated both.
| } | ||
| if outcome != ResumeOutcomeNone { | ||
| t.Errorf("expected outcome %q on error, got %q", ResumeOutcomeNone, outcome) | ||
| if outcome != ResumeOutcomeTriggered { |
There was a problem hiding this comment.
Does this expect a nonexistent actor trigering a cold activation basically?
There was a problem hiding this comment.
Fixed. With unattempted introduced, ActorNotFound now expects ResumeOutcomeUnattempted (since no cold activation was ever attempted). Also added a test case for context cancellation verifying it returns unattempted.
…nsions (agent-substrate#1474) Fixes agent-substrate#1474 When atenet-router routes requests: - Mislabeled cold resume failures: Previously, failed resumes were unconditionally overwritten with ate.router.resume="none", distorting cold activation rates and durations. In-flight cold activation attempts (and joiners) now preserve "triggered" and "joined" respectively on capacity and transient errors. Definitive non-activation errors (e.g. NotFound, InvalidArgument), context cancellations, and non-resuming directions (egress) now report "unattempted", strictly reserving "none" for warm hits on running actors. - Missing template labels: Empty template namespace and name dimensions are normalized to "unknown" using ateattr.NormalizeTemplateDimension, satisfying metric registry invariants without using request-derived labels on failure paths. - Documentation: Updated registry metrics.yaml and substrate.yaml to reflect the "unattempted" resume value, mirror handler Result documentation for "unknown" template fallback (including egress), and account for platform-injected unknown dimensions.
1cbcde7 to
9546f66
Compare
|
|
||
| // NormalizeTemplateDimension ensures a template dimension (atespace or name) is | ||
| // non-empty, falling back to TemplateUnknown if unset. | ||
| func NormalizeTemplateDimension(dim string) string { |
There was a problem hiding this comment.
Nice, but it's still only called from the router though, and the group brief now promises unknown for all 7 metrics that ref these attrs.
| // isDefinitiveResumeError reports whether err represents a failure where no cold | ||
| // activation could be attempted (e.g. the actor does not exist, bad request, or | ||
| // permission denied), as opposed to in-flight capacity or transient failures. | ||
| func isDefinitiveResumeError(err error) bool { | ||
| switch status.Code(err) { | ||
| case codes.NotFound, codes.InvalidArgument, codes.PermissionDenied, codes.Unauthenticated: | ||
| return true | ||
| default: | ||
| return false | ||
| } | ||
| } |
There was a problem hiding this comment.
Can we flip the default? Right now Internal, Unimplemented, Unknown etc. fall through to triggered, so an unrecognized code is as an activation in the latency series.
Unknown means we don't know, so unattempted seems safer.
Also wondering about FailedPrecondition, its registry brief is "the state of the actor did not permit a route" and with parking off it fails immediately, which sounds definitive. And retryable's comment just above already groups DeadlineExceeded with NotFound and PermissionDenied, so it's a bit weird to have two classifiers for the same codes I think.
Wdyt?
| // RouterResumeTriggered indicates this request won the singleflight lock and initiated cold activation. | ||
| RouterResumeTriggered = "triggered" |
There was a problem hiding this comment.
initiated cold activation
a request that is ResourceExhausted gets triggered without activating anything. Same wording in the registry brief.
| No cold activation was in flight. The request was invalid, the | ||
| actor did not exist, the direction does not resume, or the | ||
| request canceled before activation was attempted. |
There was a problem hiding this comment.
"No cold activation was in flight" and "request canceled" contradict each other, a canceled joiner was waiting on someone else's activation. Maybe "this request neither attempted nor observed an activation" is more accurate?
Fixes #1474
When atenet-router routes requests: