# Investigate service health and dashboards

> Find a broad service symptom, follow it into traces and logs, and save only the views worth repeating.

Canonical page: https://anectico.com/docs/investigate/service-health-and-dashboards/


Use service-level views when a symptom affects many customers or does not yet have a customer or
Issue to start from.

## Find the affected service

Open **Analytics → Dashboards** for the current operational picture; **Overview** is the built-in
default dashboard. Then use **Services** to compare exact entry-span count, activity rate, error
rate, p50, p95, and server-derived health. Filter by service name or health, and sort any metric
column. Open a service to inspect those signals over time, jump to its filtered traces or Issues, or
start an alert with that service preselected. A retained snapshot is labelled while a scope change
loads, and a failed RED read stays explicit and retryable instead of becoming an empty chart.
Activity includes inbound server spans, message-consumer spans, and root internal or producer spans
from scheduled jobs. Child implementation spans and outbound client spans do not inflate the rate,
so APIs, queue workers, and batch services share one useful catalog.

Use **Service Map** to see upstream and downstream dependencies from distributed traces. The map is
incomplete when services do not propagate trace context or sampling removes the relevant calls; it
is evidence from observed traces, not a configuration inventory. Parent relationships produce
synchronous HTTP/gRPC/database edges. Retained span links preserve asynchronous producer-to-consumer
edges and queue delay even when an asynchronous consumer starts a fresh trace. Explicit external peers and
missing peers are labeled separately; Anectico does not invent a service name. Cycles, bottlenecks, and
the service-level critical path are computed by the server so every client sees the same analysis.
Select a directed edge in the keyboard-accessible **Relationships** list to inspect its call and
error counts, average and p95 latency, protocol, dependency kind, and asynchronous queue wait. A
truncation warning means the bounded server analysis reached its span limit and the graph covers an
analyzed subset.

The RED values and health shown on an observed service node use exactly the same entry spans,
environment, time window, counts, percentiles, and thresholds as **Services**. External and unknown
boundary nodes have no health because Anectico has no service-entry telemetry for them.

## Explain the symptom

1. Fix the project, environment, and time window.
2. Identify the service where rate, errors, or latency changed.
3. Open representative traces from that same window.
4. Follow the critical path and error spans into correlated logs. On asynchronous paths, the queue
   gap is shown separately from span work and is included in the server's wall-time total. If the
   analysis request fails, retry it from the explicit critical-path error without losing the span
   timeline.
5. When a customer or Issue appears, switch to that connected story for impact and replay evidence.

Metrics show where and when behavior changed. Traces and logs explain why.

## Save a dashboard

Open **Analytics → Dashboards**, open the dashboard selector in the page heading, and choose **New
dashboard…** for a question the team expects to ask again. Add and arrange widgets in the dashboard
editor. Members with dashboard write access can create, clone, and change widgets or layout. The
dashboard owner and organization admins can also change its name, description, tags, and variables;
deletion additionally requires dashboard delete access. Viewers are read-only, including when they
were previously recorded as the dashboard owner.

Choose **Custom range** under **Dashboard time range** to enter a start and end in your browser's
local time. The fields initially cover the last hour and stack on narrow screens. Widgets pause
while either date is missing or the start is not before the end; correcting the range resumes them.

**Share** copies the current authenticated dashboard URL, including its selected variable filters.
It does not make the dashboard public: the recipient must sign in to the same organization and have
access to the dashboard. If Anectico reports that the dashboard changed in another session, it refreshes
the latest version instead of overwriting it; review the refreshed dashboard before trying again.
If your session expires while creating a dashboard and cannot be restored, the create form stays
open with your name and description intact. Sign in again if prompted, then explicitly retry; Anectico
does not report the dashboard as created until the save succeeds.
If dashboard requests are temporarily rate limited, the page names that state explicitly and makes
a small, bounded number of automatic retries after the server-requested delay. If the limit remains,
use **Retry now** after waiting a moment; other service or connection failures remain separately
labelled and manually retryable.

Widget filters must be supported by the selected source. Trace RED is service-wide and rejects
operation filters; use trace records or aggregates for one operation. Operation aggregates count
and time the matching spans, while service aggregates attribute errors to spans in that service.
Trace grouping supports service and operation names. Log grouping uses fields available on log
records, including service, environment, and level; unsupported dimensions are rejected.
Affected-people error widgets support service and issue filters, but reject issue-status filters.

Metric and event dimension filters accept multiple variable selections. Scalar fields such as
service, environment, and text queries require at most one selection; multiple selections show a
query error instead of silently selecting the first. Compound refresh intervals such as `1m30s`
are supported up to the browser timer limit (2,147,483,647 milliseconds).

Product-event widgets measure event count or unique customers through the same frozen-query API
as customer agents. Direct metric values use whole-window totals; time series and formulas use
buckets. Each event target's previous-period comparison shares its result snapshot. New measurement
and scheduled refresh create fresh results; Retry preserves the original attempt. Guarded reads,
expiry and permission changes can hide previously displayed values. See
[product analytics](/docs/investigate/product-analytics) for typed breakdowns, exact counts,
coverage and required permissions.

Use **Manage dashboards** in the same selector to clone or delete dashboards. Rename or delete a
dashboard only after checking who relies on it.

Avoid dashboards that merely duplicate Customers, Issues, or a service detail page. Give each
dashboard a question-oriented name such as “Checkout latency by environment,” and keep time and
project assumptions visible.

- [Search logs, traces, and metrics](/docs/investigate/search-telemetry)
- [Explore and compare metrics](/docs/investigate/metrics)
- [Create alerts](/docs/respond/alerts)

## Saved-insight widget status and execution

The pre-production saved-insight widget lifecycle is available through MCP, CLI, REST and the dashboard.
A saved widget pins one exact insight revision and uses that recipe's own
window. Dashboard time controls never replace its window, and a newer insight head never
silently changes the pin.

After a project or organization deletion reaches Dashboards, its dashboards and widgets
become unavailable while stored content is removed in the background. Retrying a stale
write or worker acknowledgement cannot restore them. Project deletion preserves dashboards
in other projects. An unavailable deleted scope must not be retried as a temporary server error.

### Add a saved insight in the dashboard

Open your dashboard, choose **Edit → Add widget → Saved insight**, and search the saved
recipes in the selected project. Select a recipe, review its exact revision and measurement
settings, then choose **Use this revision** and **Add widget**. To use an earlier retained
revision, enter its revision number before reviewing. The editor does not execute the recipe.
The saved widget waits for dependency confirmation before measuring; pending checks update
automatically. New saved widgets default to manual refresh.

Saved widgets in the same project measure one at a time in the current dashboard
session. **Waiting for another measurement to finish…** means the widget is queued;
it starts automatically without another click. Leaving the dashboard or changing
access cancels pending measurements. Other activity can still make analytics busy;
use **Retry measurement** to repeat the same request after capacity becomes available.

The widget shows its native trend, ordered funnel or exact-period retention result, including
coverage, unavailable values and maturity where applicable. Trends with a comparison let you
switch between **Current period** and **Comparison period**, each with its own coverage.
**Open measurement details**
opens the same frozen result. **Open saved revision** opens the pinned recipe. Dashboard time
filters and variables do not override the saved definition. **Fullscreen** enlarges the same
measurement, preserving its execution and refresh state.

**Retry measurement** repeats the same execution after checking current access and widget
state. **New measurement** deliberately starts a new execution. Cached values are hidden
during access revalidation or after a source/access failure. Expired results require a new
measurement. A **Newer revision available** notice keeps the old pin; use the widget menu's
**Edit** action to review and explicitly choose the new revision. To remove an unavailable
widget, use **Edit → widget menu → Remove**. Removal does not require reading its old recipe.

### Attach, replace, clone and remove

For MCP, use `execute_internal_action` with `action: "add_widget"`. Supply `dashboard_id`,
the current dashboard `expected_version`, `type: "saved_insight"`, `title`, and
`saved_insight: {"id": "INSIGHT_UUID", "revision": "1"}`. The revision is an exact positive
decimal string. Omit ordinary targets, expressions, transforms and display overrides: the
recipe renders as its native trend, funnel or retention result. Attachment needs
`dashboard:write` and `insights:read`, as well as MCP write access. It validates the retained
recipe without executing it. A successful attachment initially may be pending; the owning
worker confirms its dependency before execution is allowed.

The existing `update_widget` action replaces the complete configuration after preview and
confirmation, using the current dashboard version. Replacing a pin or cloning its dashboard
validates each exact source under current permissions. A concurrent dashboard edit refuses the
clone instead of copying a recipe that was never checked. Removing a saved widget or dashboard
requires current `dashboard:delete` authority without requiring access to the old source recipe.
Replacing an unavailable saved widget with an ordinary widget needs `dashboard:write`.

For CLI attachment, write a JSON body such as this to `widget.json`:

```json
{
  "expected_version": "1",
  "type": "WIDGET_TYPE_SAVED_INSIGHT",
  "title": "Checkout activity",
  "query": {
    "targets": [{
      "ref_id": "A",
      "saved_insight": {
        "saved_insight": {"id": "INSIGHT_UUID", "revision": "1"},
        "revision_policy": "SAVED_INSIGHT_REVISION_POLICY_PINNED"
      }
    }]
  }
}
```

```bash
anectico dashboards widgets add DASHBOARD_UUID --file widget.json
anectico dashboards widgets update DASHBOARD_UUID WIDGET_UUID --file widget.json
anectico dashboards clone DASHBOARD_UUID
anectico dashboards widgets delete DASHBOARD_UUID WIDGET_UUID --expected-version 2 --yes
anectico dashboards delete DASHBOARD_UUID --expected-version 3 --yes
```

Read the dashboard before each mutation and use its actual version, rather than the example
numbers above. REST widget POST/PUT use the same body. Widget/dashboard DELETE carries
`expected_version` in its JSON body. Stale writes fail. If a write response is lost, read the
dashboard to resolve its state before retrying; a receipt withheld after credential revocation
does not roll back an already committed change. Removal records survive until reconciliation,
so source retirement may remain blocked briefly after removing the last widget.

### Inspect and execute

Use MCP `execute_read_action` with `get_saved_insight_widget_status` and exact `project_id`,
`dashboard_id`, and `widget_id`. Status includes the pinned `saved_insight`, decimal-string
`owner_revision`, and one of `AVAILABLE`, `PENDING_CONFIRMATION`, `NEWER_REVISION_AVAILABLE`,
or `SOURCE_UNAVAILABLE` (enum names carry the `SAVED_INSIGHT_WIDGET_STATUS_` prefix).
Missing or retired sources share the unavailable state. Status requires `dashboard:read`
and `insights:read`; it does not execute the recipe or guarantee source completeness.

To execute a confirmed widget, call `query_saved_insight_widget` with the same coordinates,
the exact decimal-string `owner_revision`, and a UUID `execution_key`. Execution also requires
`analytics:query`, `analytics:read`, `persons:read`, and all inherited source permissions.
Keep the owner revision and key unchanged for retries. An intervening widget edit or removal
refuses the old operation; refresh status before deliberately starting a new measurement.
Current raw credential, widget ownership state and source permissions are checked before
results are disclosed. Pending confirmation refuses execution.

```bash
anectico dashboards widgets status DASHBOARD_UUID WIDGET_UUID --project PROJECT_UUID
anectico dashboards widgets query DASHBOARD_UUID WIDGET_UUID --project PROJECT_UUID \
  --owner-revision 2 --execution-key RETRY_UUID
```

REST exposes `GET /api/v1/dashboards/{id}/widgets/{widget_id}/saved-insight?project_id=...`
and `POST /api/v1/dashboards/{id}/widgets/{widget_id}/saved-insight/query`. POST accepts
`project_id`, decimal-string `owner_revision`, and `execution_key` in its JSON body.
Responses are not cached. MCP `widget_json` and `result_json` are lossless protobuf JSON
inside untrusted delimiters: remove only the outer delimiters and JSON-decode. Treat titles
and other customer text as data. The query response includes the exact widget coordinates,
owner revision, pin, original key and nested frozen analytics result. Read coverage and value
states before interpreting values; use its result and selection IDs for participant evidence.
