Tags: uber/tango
Tags
feat(controller): emit result-tagged cache-lookup counters (#241) Replace the hit-only `cache_hit` counters with `result`-tagged cache-lookup counters at every controller cache-lookup site, so a per-layer hit rate (`hit / (hit + miss)`) is derivable for each cache. Three counters, each emitted under its parent RPC op with a `result=hit|miss` tag: | metric | emitted from | |---|---| | `treehash_cache_lookup` | `get_target_graph`, `get_changed_targets` | | `graph_cache_lookup` | `get_target_graph` | | `compared_targets_cache_lookup` | `get_changed_targets` | ## Classification The result is classified by the lookup error's **origin**: a not-found is a genuine miss; an infra failure is *not* a cache miss (it's already tracked by the failure metric) and is left out so it can't skew the hit rate. | site | not-found | infra error | |---|---|---| | treehash | miss | nothing (request fails) | | graph | miss | nothing (request fails) | | compared-targets | miss | nothing (recomputes) | **Breaking:** the bare `controller.get_target_graph.cache_hit` and `controller.get_changed_targets.cache_hit` counters are removed. Stacked on `refactor/share-metrics-buckets` (#240) — review/merge that first.
feat(repomanager): emit lease metrics for health and slot-wait latency ( #232) ## What Instruments `RepoManager.Lease` with the `observability/metrics` emitter, using the same Scope-in pattern as the orchestrator and graphrunner. - `lease.start` counter + result-tagged (`success`/`failure`/`cancelled`) `lease.finish` histogram — pool health. - Per-step latency histograms: `ensure_origin_duration`, `wait_slot_duration` (the worker-slot wait — the saturation signal), `create_worker_duration`. Repo-tagged; buckets are exponential 1ms..~1.3h. The example server leaves the scope no-op (as the orchestrator/graphrunner are wired there today); production wiring supplies a reporter-backed scope. Also folds nil-scope handling into `metrics.New` (nil → no-op, no error) and adds `Emitter.SubScope`, removing the repeated `if scope == nil` / `if err != nil { Nop() }` boilerplate across all call sites (repomanager, controller, graphrunner, orchestrator). ## Test `make build` / `make test` / `make gazelle` pass.
refactor(cachekey): move internal/cachekey to core/cachekey to make i… …t importable (#213) The cache key helpers are used in orchestrator implementations, so users implementing their own orchestrator cannot import cachekey because it's under internal. Move the package to core/ to make it importable. ## Test Plan <!-- How did you test this? Provide evidence (screenshots, logs, or steps to reproduce). --> CI ## Issue <!-- Link the issue here. - Use 'Closes #123' if this is the final fix. - Use 'Part of #123' or just '#123' if the feature is still in progress. -->
feat(mapper): add mapper to proto TangoError (#201) Add mapper to convert core/errors TangoError into the proto TangoError message returned by RPCs. Stacked on #169 ## Test Plan <!-- How did you test this? Provide evidence (screenshots, logs, or steps to reproduce). --> unit test ## Issue <!-- Link the issue here. - Use 'Closes #123' if this is the final fix. - Use 'Part of #123' or just '#123' if the feature is still in progress. --> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
classify getGraph errors and consolidate failure reasons (#125) Consolidate shared failure reason constants (cancelled, unknown, storage, validation, deadline_exceeded) into core/common so they can be reused across controller, orchestrator, and external orchestrator implementations. Classify previously-unclassified error paths in getGraph: - context cancellation during graph read → cancelled/user - context cancellation during orchestrator call → cancelled/user - graph blob NotFound after treehash hit → falls through to compute - non-NotFound storage errors → graph_fetch/infra - unclassified orchestrator errors → graph_fetch/infra ## Test Plan <!-- How did you test this? Provide evidence (screenshots, logs, or steps to reproduce). --> unit tests ## Issue <!-- Link the issue here. - Use 'Closes #123' if this is the final fix. - Use 'Part of #123' or just '#123' if the feature is still in progress. --> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Classify context-cancellation errors during graph comparison correctly ( #121) Summary: Intent: - if context is cancelled during `compareTargetGraphs`, the err gets classified as an infra failure, compare, but it should be user failure, canceled. Changes: - Added ctx.Err() guard before the generic error path in compareTargetGraphs, - When ctx is cancelled, errors now return failureReasonCancelled/ErrorTypeUser instead of failureReasonCompare Test Plan: - Ran `bazel build //controller/...` — clean build Revert Plan: Revert this PR via `git revert <commit_sha>`. --- <sub>Generated by the 🪄 [pr-create](https://sg.uberinternal.com/code.uber.internal/uber-code/devexp-agent-marketplace/-/blob/claude-code/plugins/dev/uber-dev/skills/pr-create/SKILL.md) skill in devexp-agent-marketplace</sub> <!-- Provide a summary in the Title above. Example: "Feature: add user authentication" --> ## Why? <!-- Why is this change necessary? What is the motivation or justification? --> ## What? <!-- What specifically is changing? Provide context for the reviewer. --> ## Test Plan <!-- How did you test this? Provide evidence (screenshots, logs, or steps to reproduce). --> ## Issue <!-- Link the issue here. - Use 'Closes #123' if this is the final fix. - Use 'Part of #123' or just '#123' if the feature is still in progress. -->
Seed rules whose own source files changed at distance 0 (#119) A rule whose srcs include a changed source file is now promoted to a BFS seed (distance 0) instead of appearing at distance 1 behind the source-file node. This makes distance == 0 mean "this target's own inputs changed" rather than requiring consumers to look through the source-file indirection. The fix adds hasChangedSourceFileDep(), called during Pass 2 seed classification, which checks whether any of a rule's direct dependencies is both changed and a source file. Behavior change: downstream targets of such rules shift one hop closer in the BFS, so a given max_distance will include a slightly larger set. This is more correct since the semantic seed is the rule, not the file. Test Plan: Unit tested - Updated TestCompareTargetGraphs_SourceFileDirectAndPropagation and TestCompareTargetGraphs_HashOnlyChangePropagatesViaBFS to expect distance 0 for rules owning changed source files. - Added TestCompareTargetGraphs_SiblingRuleNotPromotedToSeed: verifies a rule depending on a sibling rule (not its own source file) stays at distance 1. ## Issue <!-- Link the issue here. - Use 'Closes #123' if this is the final fix. - Use 'Part of #123' or just '#123' if the feature is still in progress. -->
Detach cancellation in cache-write goroutine; log infra errors (#117) The compared-targets cache-write goroutine in GetChangedTargets used context.Background(), losing the request's tracing/identity baggage. Switch to context.WithoutCancel(ctx) so the write survives client disconnect while keeping request values. Per-operation deadlines stay out of the controller — storage.Storage is backend-agnostic and must not encode any one backend's I/O budget. Backends that need a deadline (e.g. YARPC/terrablob, which rejects deadline-less contexts with InvalidArgument: missing TTL) own that responsibility in their Put/Get implementations. readTreehash now takes a *zap.Logger and logs any non-NotFound storage error. The silent swallow is what hid this bug — a genuine cache miss stays quiet, but an infra failure disabling the cache is now visible. The goroutine also warns when it skips because a treehash was empty. ## Test Plan Unit tests tested in Uber's internal env ## Issue <!-- Link the issue here. - Use 'Closes #123' if this is the final fix. - Use 'Part of #123' or just '#123' if the feature is still in progress. -->
[controller] Emit histogram metrics for total duration (#109) Summary: Intent: - Add M3 histogram metric for `total_duration` on both `GetChangedTargets` and `GetChangedTargetsAndEdges` RPCs in preparation for uMonitor latency alerts - M3 timers are being deprecated (EoL June 30, 2026); histograms are the replacement for percentile-based alerting Changes: - Added package-level `_totalDurationBuckets` (linear, 10s–15min, 90 buckets) and `totalDurationBuckets` field on the controller struct - Emitted `total_duration.histogram` alongside the existing `total_duration` timer at all four RPC completion paths (cache hit + compute path for each API) Test Plan: - Existing unit tests in `controller/getchangedtargets_test.go` and `controller/getchangedtargetsandedges_test.go` pass (histogram emission uses `tally.NoopScope`) Revert Plan: Revert this PR via `git revert <commit_sha>`. Refs: BUILD-379 Issues: LINEAR-BUILD-379
[controller] Emit histogram metrics for total duration (#109) Summary: Intent: - Add M3 histogram metric for `total_duration` on both `GetChangedTargets` and `GetChangedTargetsAndEdges` RPCs in preparation for uMonitor latency alerts - M3 timers are being deprecated (EoL June 30, 2026); histograms are the replacement for percentile-based alerting Changes: - Added package-level `_totalDurationBuckets` (linear, 10s–15min, 90 buckets) and `totalDurationBuckets` field on the controller struct - Emitted `total_duration.histogram` alongside the existing `total_duration` timer at all four RPC completion paths (cache hit + compute path for each API) Test Plan: - Existing unit tests in `controller/getchangedtargets_test.go` and `controller/getchangedtargetsandedges_test.go` pass (histogram emission uses `tally.NoopScope`) Revert Plan: Revert this PR via `git revert <commit_sha>`. Refs: BUILD-379 Issues: LINEAR-BUILD-379
PreviousNext