diff --git a/en/ai-sre/automations.mdx b/en/ai-sre/automations.mdx index 2f08d9d2d..e04bef7a9 100644 --- a/en/ai-sre/automations.mdx +++ b/en/ai-sre/automations.mdx @@ -1,7 +1,7 @@ --- title: Automations description: Have AI SRE run a task automatically on a cron schedule, through an HTTP API, from an On-call incident event, or when a war room is created, driven by a task prompt, to produce inspection, insight, or post-mortem results. This page covers creating automation rules, configuration fields, triggers, run history, and permissions. -keywords: ["AI SRE", "Automation", "inspection", "scheduled task", "cron", "HTTP trigger", "On-call incident trigger", "war room created trigger", "manual run", "run history", "hidden session"] +keywords: ["AI SRE", "Automation", "inspection", "scheduled task", "cron", "HTTP trigger", "On-call incident trigger", "war room created trigger", "manual run", "run history", "hidden session", "execution location"] sidebarTitle: Automations --- @@ -23,7 +23,7 @@ When to use it: hand recurring routine inspections (such as a daily health check Entry point: **AI SRE → Automations** in the left navigation, route `/ai-sre/automations`. -Every run produced by an automation is, at its core, still an AI SRE session — it is marked as hidden and not mixed into your everyday session list. You can always click into it from the run history to see the full conversation, tool calls, and artifacts of that run (except for a **War room created** run, which runs in the IM group — see "War room created" below). +Every run produced by an automation is, at its core, still an AI SRE session — it is marked as hidden and not mixed into your everyday session list. A run whose execution location is **Web** can always be opened from the run history to see the full conversation, tool calls, and artifacts of that run. A run whose execution location is **IM** (including a **War room created** run) keeps its conversation in the IM group: the console does not expose that session and cannot open it. See "Where it runs" below. ## Creating an automation @@ -39,7 +39,15 @@ The page header offers two ways to create a rule. **Create via chat** opens a se -Either entry point leads to the same configuration form. +Either entry point leads to the same configuration form. Both console entry points always create a rule whose execution location is **Web** — a hidden session in the console. To have a rule run in an IM group chat, create it from the IM conversation instead, see below. + +### Creating from an IM conversation (binding the current chat) + +Ask the agent to create an automation from an IM group chat or direct message. If you don't name an execution location, the rule binds to **that conversation** and inherits its scope, including the team it is currently bound to. The command line works the same way: `flashduty automation create` started from an IM conversation binds to the current conversation when `--run-in` is omitted (see the [command-line tool](/en/developer/cli)). Points to know: + +- Once bound, every run opens a new session in that group chat rather than in the console, and the original group chat never changes. +- To run it in **Web** instead (a hidden session in the console), say so at creation (ask for the web console in the chat, or pass `--run-in web`). It cannot be changed afterwards — create a new rule instead. +- Do not pass chat, platform, integration, or session IDs yourself: the server resolves and authorizes the current conversation. ## Configuration fields @@ -48,8 +56,8 @@ The configuration form has the following fields: | Field | Required | Notes | |---|---|---| | Name | Yes | The rule name, up to 255 characters. Placeholder example: `Weekly on-call insights`. | -| Scope | Yes | Use the **scope selector** to choose **Personal** (`team_id=0`) or a **Team** (`team_id>0`). Scope determines the rule's ownership and edit permissions. It also limits the self-hosted Runners you can select in **Environment** to account-global Runners and Runners of the scope's team. | -| Environment | No | Use the **environment picker** to choose the runtime environment: **Auto** (the system picks the best available environment, the default), **Cloud Sandbox**, or a **self-hosted (BYOC) Runner**. After picking a team scope, a team Runner that does not belong to that scope is cleared automatically. | +| Scope | Yes | Use the **scope selector** to choose **Personal** (`team_id=0`) or a **Team** (`team_id>0`). Scope determines the rule's ownership and edit permissions. It also limits the self-hosted Runners you can select in **Environment** to account-global Runners and Runners of the scope's team. Scope cannot be changed after creation; the rule's detail page shows it as **Pinned scope**. | +| Environment | No | Use the **environment picker** to choose the runtime environment: **Auto** (the system picks the best available environment, the default), **Cloud Sandbox**, or a **self-hosted (BYOC) Runner**. After picking a team scope, a team Runner that does not belong to that scope is cleared automatically. A rule whose execution location is **IM** does not use the environment chosen here (see "Where it runs" below). | | Task prompt | Yes | Describe the task for AI SRE to perform, written in a rich-text editor. This prompt is exactly what is sent to the agent on each run. Placeholder: `Describe the task for Flashduty AI SRE to perform.` | | Time zone | No | A field on the **Schedule** trigger card (see "Schedule (cron)" below): the **rule time zone** the cron expression is read in. Pick an IANA zone name (for example `Asia/Shanghai`) from a searchable dropdown; the options are ordered by their UTC offset. On create it defaults to your effective time zone (member time zone first, falling back to the account time zone). When no zone is available the field is left empty and the create request omits it. | @@ -57,6 +65,35 @@ The configuration form has the following fields: For **Environment**, "Auto" has the system pick the best available environment at each run; "Cloud Sandbox" is a platform-managed ephemeral sandbox; a self-hosted Runner runs on your own machine. See Environments for the differences and how to connect them. +## Where it runs (the rule's execution location) + +Every rule has an **execution location**, fixed at creation and not changeable in the console afterwards: + +- **Web** (the default): each run is a hidden session in the console. Every rule created in the console has this value. +- **IM**: the run happens in the IM group chat or direct message bound at creation. Such a rule opens no console session — each of its runs **opens a new session** in the original group chat; when that IM integration has threads on, each run also opens a new thread; a retry of the same run keeps that session and thread; the original group chat never changes. + +Both the **Where it ran** column in the rule list and the **Where it ran** entry under **Configuration** on the rule's detail page show this value (`IM` or `Web`). When a rule enables both the **War room created** trigger and others, the list shows two badges: **War room → IM** and **Other triggers → Web**. **War room created** is the only trigger that does not use the rule's execution location — it runs in the war room's group; see "War room created" below. + +A rule whose execution location is **IM** differs from a Web rule in two more ways: + +- There is no **Clone** in the console. To move an IM rule to Web execution, create a new rule. +- The console does not expose such a run's session identity: in run history its **Name** column reads `-`, and clicking the row only shows **This analysis is in IM. Open IM to view it.** Running it manually from the rule row likewise opens no session. See "Run history" and "Management and permissions" below. + +**Environment**: a rule whose execution location is **IM** does not use the **Environment** selected on the rule — it runs in that group chat, using the execution environment already chosen for that chat (change it with `/env` in the conversation). The console form still shows an environment picker for such a rule, but it has no effect on IM runs. The **War room created** trigger has the same exception; see "War room created" below. + +**When the binding no longer holds, the run is skipped**: if the bound chat's scope or session has changed by the time the run starts (for example the team was changed with `/scope` in that chat, or the chat was reset to a new session), the run is **skipped** — run history shows the status `Skipped` with the reason `chat_scope_mismatch`. The rule itself stays enabled and is never moved to another chat; create a new rule if you need a different chat. + +### Choosing the execution location from the API / CLI (`run_in`) + +A rule created in the console is always **Web**. Creating one through the API or CLI, name the execution location explicitly with `run_in`: + +| Field | Type | Notes | +|---|---|---| +| `run_in` | string | `current-chat`: bind the rule to the **live IM conversation** the authenticated call came from; it can only be used when the call is made in that IM conversation, and is rejected anywhere else. `web`: run in the console, that is execution location **Web**. Omitted, the server decides: a call from an IM conversation gets `current-chat`, everything else gets `web`. | +| `team_id` | int64 | The rule's scope. An explicit `0` is personal scope, and a value above 0 picks a team in the account; omitted, a call from an IM conversation inherits that conversation's scope and everything else takes the server's normal default. With `run_in=current-chat`, an explicit value must match that conversation's scope. | + +`update` accepts no `run_in` and cannot change `team_id` (a changed value is rejected): **the execution location, like the scope, is immutable after creation.** See the [command-line tool](/en/developer/cli) for the matching flag. + ## Triggers A rule must have **at least one trigger** configured. The current console form exposes **Schedule**, **Call via API**, **On-call incident**, and **War room created** in the "Triggers" section, and all four can be enabled at the same time. @@ -223,7 +260,7 @@ If you create or update a rule through the API, use these fields: When a matching war room is created, the system creates a run with `trigger_kind: "war_room_created"` and passes context such as `incident_id`, `channel_id`, and `severity` into the session. This run does not open a new console session: it runs an analysis directly in the war-room group, and the conclusion is posted back into that group. Under one trigger, a single incident starts only one run — a repeated event does not open a second session. -**Environment**: this trigger does not use the rule's **Environment** — an analysis in the war room uses the execution environment already chosen for that group. When the war room is a rule's only trigger, the form hides the environment picker and only says "Analysis in the war room uses the execution environment already chosen for that group. This rule does not pick one." When the rule also enables the schedule / API / incident triggers, the picker stays and shows "Schedule, API, and incident triggers use the execution environment chosen here. The war room trigger uses the group's execution environment and does not change that choice." +**Environment**: this trigger does not use the rule's **Environment** — an analysis in the war room uses the execution environment already chosen for that group. When the war room is a rule's only trigger, the form hides the environment picker and only says "Analysis in the war room uses the execution environment already chosen for that group. This rule does not pick one." When the rule also enables the schedule / API / incident triggers, the picker stays and shows "Schedule, API, and incident triggers use the execution environment chosen here. The war room trigger uses the group's execution environment and does not change that choice." A rule whose execution location is **IM** has the same exception; see "Where it runs" above. The preset template **War room initial analysis** (template key `war_room_initial_analysis`, category **Incident Response**) prefills this trigger and the `Critical` severity; the channels are not prefilled, so you pick them yourself. @@ -235,11 +272,11 @@ Run history is shown as a table with these columns: | Column | Notes | |---|---| -| Name | The title of the run's hidden session (`session_name`), or the session ID (`session_id`) if it can't be resolved. A run merged into another analysis has no session of its own, so this shows its incident (`# `) and, on the line below, the analysis it joined | +| Name | The title of the run's hidden session (`session_name`), or the session ID (`session_id`) if it can't be resolved; a run whose execution location is **IM** shows neither and reads `-` (its conversation is in the IM group, and the console does not expose its session identity). A run merged into another analysis has no session of its own, so this shows its incident (`#<num> <title>`) and, on the line below, the analysis it joined | | Started at | The start time of the run | | Duration | How long the run took | | Triggers | The trigger type of the run, such as `Schedule`, `HTTP POST`, `On-call incident`, `Run manually`, or `War room created` (war_room_created) | -| Where it ran | Where the run happened: `IM` (the session is in the IM group, as for a war-room-created run) or `Web console` (a hidden session in the console). The API field is `execution_place`, with values `im` / `web_console`; when a record does not carry it, a war-room-created run reads `IM` and every other run reads `Web console` | +| Where it ran | Where the run happened: `IM` (the session is in the IM group, as for a war-room-created run) or `Web` (a hidden session in the console). The API field is `execution_place`, with values `im` / `web_console`; when a record does not carry it, a war-room-created run reads `IM` and every other run reads `Web` | | Status | The status of the run (see the table below) | Run status values: @@ -251,7 +288,7 @@ Run status values: | `succeeded` | Succeeded | | `partial` | Partially succeeded | | `failed` | Failed | -| `skipped` | Skipped. Two situations share this status. Either the trigger decided not to run, for example because the rule's owner is inactive or the schedule stopped. Or the incident joined another running analysis (see "Merging similar incidents into one analysis" above) | +| `skipped` | Skipped. Three situations share this status: the trigger decided not to run, for example because the rule's owner is inactive or the schedule stopped; the incident joined another running analysis (see "Merging similar incidents into one analysis" above); or an **IM** rule started when its bound chat's scope or session had already changed (such a run does not move chats — it is simply skipped; see "Where it runs" above) | | `blocked` | Blocked. The run produced real output but stopped at a connector that needs a human. The connector isn't set up yet, or an admin must complete its authorization in the console | | `abandoned` | Abandoned (terminated by the system after running too long without completing) | @@ -261,7 +298,7 @@ Three filters are available above the table: - **Status**: filter by the run statuses above, or choose **All statuses**. - **Trigger type**: choose from `All trigger types` / `Run manually` / `Schedule` / `HTTP POST` / `On-call incident` / `War room created`. -Run records returned by the API also include `trigger_kind`, which can be `schedule`, `manual`, `http_post`, `oncall_incident`, `war_room_created`, or `debug`. `manual` means the run was started through the run-now API, `oncall_incident` means it was started by a matching On-call incident event, and `war_room_created` means it was started by the war-room-created trigger (its session is in the IM group). A run merged into another analysis has no `session_id` of its own. Instead, `joined_session_id` holds that analysis's session ID and `joined_session_name` holds its session name. If both are empty, the run has its own hidden session. +Run records returned by the API also include `trigger_kind`, which can be `schedule`, `manual`, `http_post`, `oncall_incident`, `war_room_created`, or `debug`. `manual` means the run was started through the run-now API, `oncall_incident` means it was started by a matching On-call incident event, and `war_room_created` means it was started by the war-room-created trigger (its session is in the IM group). A run whose `execution_place` is `im` returns no session identity: `session_id` and `joined_session_id` are both empty, and `result_json` is omitted too — only the status, time, and error fields remain. A run merged into another analysis has no `session_id` of its own. Instead, `joined_session_id` holds that analysis's session ID and `joined_session_name` holds its session name. If both are empty, the run has its own hidden session. Click a row to jump to the chat page of the hidden session for that run, where you can view the full messages, tool calls, and artifacts of that run. A run that happened in IM (`execution_place=im`, or one started by `war_room_created`) does not navigate; it shows the message **This analysis is in IM. Open IM to view it.** — you read that analysis in the IM group. A run merged into another analysis has no session of its own, so clicking it opens the analysis that took over the incident. @@ -277,6 +314,7 @@ When a run's status is `failed`, `blocked`, `abandoned` or `skipped`, the **Name | The run was interrupted (`interrupted`) | — | | The run ended without a final reply (`no_final_response`) | — | | Joined another analysis (`similar_incident_fan_in`) | Click the row to open the analysis that took over the incident | +| The bound group chat's scope or session changed, so the run did not execute (`chat_scope_mismatch`) | The rule stays enabled and still runs in the original group chat; create a new rule to use another chat | Other reasons show the text recorded by the system. @@ -293,7 +331,7 @@ Each rule offers a set of actions in the **Actions** column: | Action | Notes | |---|---| | Enable / Disable | An inline switch. When disabled, the rule is kept but no longer triggers; disabling does not delete existing run history. | -| Run now | Starts one real run manually from the rule row. The action performs preflight checks first, then creates a hidden session for the run. Manual runs are limited to one per rule per minute. When **War room created** is the rule's only trigger, neither the list nor the detail page offers this action — such a rule produces no console run, and calling the run-now API returns an error. | +| Run now | Starts one real run manually from the rule row, after preflight checks. A rule whose execution location is **Web** gets a new hidden session, opened straight away; a rule whose execution location is **IM** opens its session in the bound IM group chat, and the console only says **Manual run submitted. Check the run history for progress.** — follow the progress in the run history. Manual runs are limited to one per rule per minute. When **War room created** is the rule's only trigger, neither the list nor the detail page offers this action — such a rule produces no console run, and calling the run-now API returns an error. | Clicking anywhere on the rule row opens its detail page, where you can edit the configuration, delete the rule, and view its run history (see "Run History" above). @@ -307,13 +345,14 @@ Automation rules share the same two-level scope model as the other resources und | Dimension | Rule | |---|---| -| Ownership | **Personal rules** belong to their creator; **team rules** belong to that team. **Scope cannot be changed after creation**; to use a different scope, click **Clone** on the rule's detail page and pick a new scope for the copy. To create a team rule, the operator must be a member of that team; account Owners and admins are no exception. A team rule keeps running after its creator leaves the team; a personal rule is disabled automatically once its creator is no longer an active account member. | +| Ownership | **Personal rules** belong to their creator; **team rules** belong to that team. **Scope cannot be changed after creation**; to use a different scope, click **Clone** on the rule's detail page and pick a new scope for the copy (a rule whose execution location is **IM** offers no Clone — see below). To create a team rule, the operator must be a member of that team; account Owners and admins are no exception. A team rule keeps running after its creator leaves the team; a personal rule is disabled automatically once its creator is no longer an active account member. | | Visibility / list | The account Owner and admins see all rules; ordinary members see rules they created and rules of teams they belong to. | | Edit / manage (team rules) | Only **current members** of the rule's owning team can act on the rule (enable / disable, edit, delete, run now). Once the creator has left the team, they keep no standing privilege. The account Owner and admins have no exemption and must join the team first. | | Edit / manage (personal rules) | Only the creator can view and manage a personal rule. Account Owners and admins cannot view or manage other members' personal rules. | | HTTP POST trigger | When initiating a real run through the trigger URL, authorization is only the trigger's Bearer Token. Any external system holding that Token can trigger the rule, and the run creates a hidden session under the rule's personal or team scope. | | On-call incident trigger | Started by a registered incident subscription, not by an HTTP POST Bearer token. The run still creates a hidden session under the rule's personal or team scope. | | War room created trigger | Started by a registered war-room-created subscription, not by an HTTP POST Bearer token. The session is created in the war room's IM group rather than the console, and the run still belongs to the rule's personal or team scope. | +| IM execution location | Set when the rule is created from an IM conversation and bound to it (see "Where it runs" above): the binding and the scope are both fixed by the source conversation at creation, cannot be changed in the console, and cannot be migrated through `update`. Such a rule offers no **Clone** in the console. | <Note> The account Owner / admins can see other members' personal rules in the list (see "Visibility / list" above), but they can't open the detail page. The "Edit / manage" permission has no Owner / admin exemption on personal rules, the same as on team rules. diff --git a/en/ai-sre/im.mdx b/en/ai-sre/im.mdx index 66af62053..a8c72159c 100644 --- a/en/ai-sre/im.mdx +++ b/en/ai-sre/im.mdx @@ -11,7 +11,7 @@ sidebarTitle: IM platform Incident response usually happens right inside your IM group — alerts come in, the team discusses in the channel, and someone spins up a war room. AI SRE puts the agent directly into that collaboration chain: **you never have to switch to the console. You can summon it from IM to investigate**, and your teammates can follow every step of its analysis in real time. -AI SRE's IM integration has two trigger modes: +AI SRE's IM integration has three trigger modes: <CardGroup cols={2}> <Card title="@Mention Summon" icon="at"> @@ -20,8 +20,13 @@ AI SRE's IM integration has two trigger modes: <Card title="War Room Auto-Diagnosis" icon="people-group"> When someone opens an IM war room for an incident, AI SRE runs a preliminary diagnosis and posts the findings to the war room if the account has an enabled **War room created** automation rule that the incident's channel and severity match. No one needs to summon it. </Card> + <Card title="Automation Replies in the Group" icon="clock"> + Ask AI SRE in the group to create an ordinary automation rule and it pins **this group** as where the rule runs: when that rule fires on schedule, through the API, or on an On-call incident, it runs the turn in the original group in a **fresh session** and posts the findings back there. Every run is a brand-new session and carries none of the group's conversation history; if the IM integration uses thread replies, the run also starts a new thread, whose root is the first real output of that run (progress or findings) and whose later progress and findings are replies inside it — nothing like a canned "started" message is posted before there is content. The binding and scope are fixed at creation and cannot be moved to another group: AI SRE re-checks them before the run and **skips the entire run** if the group's team scope or session has changed, and if the same rule already has a run active in that group, this occurrence does not queue either — it is skipped too. + </Card> </CardGroup> +The first two modes are initiated by a person; the third runs from an automation rule you set up. For how to create the rule and how its run location and scope are pinned, see [Automations · Configuration fields](/en/ai-sre/automations#configuration-fields). + ## Supported IM platforms AI SRE's IM interaction covers four major platforms. Each platform supports inbound @mentions (webhook), historical message reads, and outbound replies: diff --git a/en/ai-sre/sessions.mdx b/en/ai-sre/sessions.mdx index 595281687..88427cf49 100644 --- a/en/ai-sre/sessions.mdx +++ b/en/ai-sre/sessions.mdx @@ -86,6 +86,7 @@ Type a message in the input and press Enter. The input supports Markdown; type ` - **Supported types**: images, PDF, text / Markdown / CSV / HTML, Office documents, archives (`.zip` / `.rar`), and any UTF-8 text file (such as `.go`, `.py`, `.yaml`). Empty files are rejected. - **Size and count**: up to **50 MB** per file; up to **9 attachments** per message, **50 MB** in total. + - **Images**: so that every vision model can read them, an image whose longest side is over **8192 px**, whose shortest side is under **11 px**, or whose long-to-short ratio is over **200:1** is scaled down, padded with white, and **re-encoded** — the stored format can change (a GIF is stored as PNG and only its first frame survives) and the file name's extension is adjusted to match. Such an image is rejected outright if it holds more than **40 megapixels**, with a prompt to send a smaller one. An image that is corrupt, or an unrecognized variant, fails to upload. Images inside a folder are stored as sent and get none of this treatment. - **Folders**: choose **Upload folder** from the plus menu or drag a folder onto the input. A folder can hold up to **50 files** (`node_modules` and dot-files are not counted). A larger folder is rejected as a whole, and individual files that do not qualify are skipped with the reason listed. A folder counts as 1 attachment and keeps its directory structure. - **How the agent reads them**: attachments are provided as text. For text over 64 KB only the beginning is provided directly, and the agent reads the full file from the sandbox when needed. Archives and folders are not expanded up front; the agent unpacks and reads them in the sandbox as needed. </Accordion> diff --git a/en/changelog/changelog.mdx b/en/changelog/changelog.mdx index 33d89c7ef..23994df05 100644 --- a/en/changelog/changelog.mdx +++ b/en/changelog/changelog.mdx @@ -4,6 +4,34 @@ description: "This page documents important updates and feature releases for Fla keywords: ["Changelog", "Product Release", "Feature Updates", "Flashduty", "Version History"] --- +<Update label="2026-10-16" description="🤖 AI SRE automations can run in the IM chat that created them, RUM issues gain a resolve mode, DingTalk and Lark integrations link members automatically on save"> + +### AI SRE automations: an execution location that can bind a rule to the IM chat that created it + +An automation rule now carries an **execution location**, fixed at creation: **Web** (the default) or **IM**. When you have the Agent create a rule in an IM group chat or DM, the rule binds to **that conversation** (an API call that passes `run_in: current-chat` does the same, but that value is only accepted from the live IM conversation). Both create entries in the console always produce a rule with the **Web** execution location, and an IM rule offers no **Clone** action in the console either, so running a rule in a different location means creating a new one. The execution location cannot be changed after creation: the edit form shows the scope and the execution location as read-only, with the hint "The scope and IM destination were fixed at creation and cannot be changed in the console." beside an IM rule. + +A rule with the IM execution location never opens a session in the console. Every run **opens a new session** in the original group chat, plus a new topic when the integration has threads on; a retry of the same run keeps that session and thread, the original group chat never changes, and the conclusion is posted back into that chat. If the chat's scope or session has changed by the time the rule runs (say `/scope` or `/new` was used), that run is **skipped** (status "Skipped" in the run history, reason `chat_scope_mismatch`); the rule stays enabled and never moves to another chat. + +The rule list gains a column for the execution location, with the values `IM` / `Web`; when a rule has both a war room trigger and other triggers, that column shows two badges — "War room → IM" and "Other triggers → Web". See [AI SRE automations](/en/ai-sre/automations). + +### RUM issues: a resolve mode — Resolved / Resolved in next version + +**Resolved** and **Resolved in next version** in an issue's status dropdown are one resolved status split by how a recurrence reopens the issue: + +- **Resolved** (the dropdown says "Reopens if it occurs again"): the error occurring again reopens the issue as For Review and marks it **Issue Regression**, even in the same version; +- **Resolved in next version** ("Reopens only if it occurs in a newer version"): only a recurrence in a version the issue has not seen before reopens it, while repeats inside the same version leave it resolved. + +You can switch between the two in the status dropdown at any time. A new issue defaults to **Resolved in next version**, and existing issues carry that same default; an error that reports no version label reopens the issue under either mode. See [Issue status](/en/rum/error-tracking/issue-status). + +### DingTalk and Lark integrations link members automatically on save + +Saving or editing a DingTalk or Lark integration starts one link attempt right away, and once an hour the system sweeps every enabled DingTalk and Lark integration: it resolves each member's phone number (and, for Lark, email) to an IM account ID and writes the binding. Members do nothing, and they no longer have to sign in to the IM app first. Click **Link users** on the integration detail page only when you want to retry immediately. + +An IM account ID another member already holds is never overwritten; a member the platform answers "no such user" for is not looked up again for 7 days; and when a DingTalk app lacks the `qyapi_get_member_by_mobile` permission or its server IP is not whitelisted, or a Lark app lacks the contacts permission, automatic linking for that integration pauses for 24 hours — fix the permission or the whitelist and save the integration again to resume. Automatic linking covers DingTalk and Lark only; WeCom still uses the manual **Link users** button, and Slack integrations offer no member linking at all. See [DingTalk](/en/on-call/integration/instant-messaging/dingtalk) and [Lark](/en/on-call/integration/instant-messaging/lark). + +</Update> + + <Update label="2026-10-14" description="🧭 Investigation entries open the exact dashboard or query from an alert, alert-grouping rework, label-panel redesign, weekly and monthly scheduled notifications, dashboard global search"> ### Investigation entries: from an alert straight to a dashboard or the Query Workbench diff --git a/en/developer/cli.mdx b/en/developer/cli.mdx index 1c767853d..3954c4819 100644 --- a/en/developer/cli.mdx +++ b/en/developer/cli.mdx @@ -18,7 +18,7 @@ The tool is open source at [flashcatcloud/flashduty-cli](https://github.com/flas curl -sSL https://static.flashcat.cloud/flashduty-cli/install.sh | sh ``` -Installs to `/usr/local/bin` by default. Override with the `FLASHDUTY_INSTALL_DIR` environment variable. +Installs to the directory of the `flashduty` already on your `PATH` by default, so an upgrade replaces that copy in place; when there is no `flashduty` on `PATH`, it installs to `/usr/local/bin`. Override the directory with the `FLASHDUTY_INSTALL_DIR` environment variable. </Tab> <Tab title="Windows (PowerShell)"> @@ -39,13 +39,15 @@ Read the latest version from the [CDN latest version pointer](https://static.fla | Variable | Description | Default | |----------|-------------|---------| | `FLASHDUTY_VERSION` | Install a specific version, for example, `v1.5.12` | latest | -| `FLASHDUTY_INSTALL_DIR` | Custom install directory | `/usr/local/bin` (shell), `~\.flashduty\bin` (PowerShell) | +| `FLASHDUTY_INSTALL_DIR` | Custom install directory | the directory of the `flashduty` already on `PATH`, else `/usr/local/bin` (shell); `~\.flashduty\bin` (PowerShell) | | `MIRROR_URL` | Override the release asset download mirror prefix used by the installer script; must use `https://` | `https://static.flashcat.cloud/flashduty-cli` | | `FLASHDUTY_UPDATE_BASE_URL` | Override the base URL used by `flashduty update` and the automatic update check | `https://static.flashcat.cloud/flashduty-cli` | | `INSTALLED_NAME` | Command name to install as, for example, `fduty` | `flashduty` | A copy installed under another command name uses that name in help output, error messages, and shell completion scripts; `flashduty update` replaces the running binary in place, under its own name and directory, instead of installing a default-named copy elsewhere. +After installing, the script re-checks `PATH`: if the `flashduty` your shell actually runs is not the copy it just installed (an older copy earlier on `PATH` shadows it), it tells you to remove that copy or move the new directory ahead of it. When the current process is managed by flashduty-runner (`FLASHDUTY_MANAGED_BY_RUNNER=1`), the script refuses to run and tells you to upgrade the runner instead — the runner ships a CLI copy it was built and verified against, and replacing it in place desyncs the two. + ## Authentication ### Log in @@ -635,12 +637,17 @@ Core fields for `datasource-create` / `datasource-update`: - `kafka`: `sasl_mechanism` (`none` default / `plain` / `scram-sha-256` / `scram-sha-512`, the latter three require username and password), `username` / `password`, `timeout_ms` (default 5000), TLS fields (`tls_min_version` defaults to 1.2, max 1.3). - Passwords and `kafka.tls_key` support `${env:NAME}` references (resolved on the edge); literal values are omitted from responses, only `${env:...}` references are echoed. **On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear**. -#### Dashboards and rule folders (dashboard-* / folder-list) +#### Dashboards and rule folders (dashboard-* / folder-*) The `monit dashboard-*` family manages monitor dashboards (provided by generated OpenAPI commands). A dashboard is a `dashboard.v1` document: pass the `definition` in `--data` when creating or updating. `update`, `delete`, `move`, and `restore` all require `--expected-revision` — if the revision you send is not the current one, the call is rejected with `DashboardRevisionConflict`, so re-read and submit again. ```bash flashduty monit folder-list # List every monitor rule folder, to get a folder-id (top-level array, use jq '.[]') +flashduty monit folder-health # Read folder health summaries, including issues in descendant folders (paged envelope, use jq '.items[]') +flashduty monit folder-create --name <folder-name> [flags] # Create a folder (--name required, no . / ,; --parent-id parent folder, 0 = root; --note note; --team-id team, 0 = account-wide) +flashduty monit folder-update --id <folder-id> --name <folder-name> # Update a folder's name, note, and team assignment (--id and --name required) +flashduty monit folder-move <dest-parent-id> --id <folder-id> # Move a folder and its descendants (dest-parent-id is positional and always required; 0 moves it to the root) +flashduty monit folder-delete --id <folder-id> # Delete a folder (empty folders only: child folders, rules, or dashboards make the call fail) flashduty monit dashboard-list <folder-id> # List the dashboards in one folder (paged envelope, use jq '.items[]') flashduty monit dashboard-search --query "payments" # Search dashboards by title and description (at least one word) flashduty monit dashboard-get <dashboard-id> # Read a dashboard, including its definition and current revision @@ -660,6 +667,8 @@ flashduty monit dashboard-runtime-variables-preview # Preview draf flashduty monit dashboard-runtime-queries-resolve <panel-id> [<id2>...] # Resolve panel queries: expressions with variables substituted, and the bound datasource ``` +The `monit folder-*` commands manage the folders themselves. `folder-health` returns a `{items:[...]}` paged envelope in which each entry carries only `folder_id` and `has_issue` (`has_issue` marks a folder whose visible descendants include active alerts or rule runtime issues), and `folder-list` returns a top-level array — read both with `--json | jq`. `folder-create` and `folder-update` return the updated folder object; `folder-move` and `folder-delete` return no folder object. A folder name may not contain `.`, `/`, or `,`. `folder-move` requires `dest-parent-id` even when moving to the root (`0`), and `folder-delete` accepts only an empty folder — child folders, rules, or dashboards inside it make the call fail, so empty it yourself first. + Panel runtime and variable resolution take their time window and variable selections as JSON objects in `--data` (time uses millisecond `from_ms` / `to_ms` timestamps). `dashboard-panel-preview` and `dashboard-runtime-variables-preview` need a `context`: `kind: existing` with a `dashboard_id` targets a stored dashboard, `kind: new` with a `folder_id` targets a folder that does not hold one yet. `dashboard-runtime-queries-resolve` takes two further flags that shape the result: `--max-data-points` (int, 2–5000; both the downsampling target and what decides the step the built-in time variables render with — omit it or send `null` for the server default of 100) and `--preserve-builtin-variables` (bool, off by default): when set, the **built-in time variables** stay verbatim in the resolved expressions so a caller with its own execution window can render them, while user variables are still resolved. The sibling commands `dashboard-panel-run` and `dashboard-panel-preview` already carried `--max-data-points`, likewise a 2–5000 downsampling target. @@ -721,11 +730,12 @@ Common `create` flags: | Flag | Notes | |------|-------| | `--name` | Rule name (required) | -| `--team-id` | Scope team ID; `0` means personal scope (default). The scope is immutable after creation | +| `--team-id` | Scope team ID; an explicit `0` means personal scope and `>0` means that team; when omitted the field is not sent, so the server inherits the authenticated IM conversation's scope when one is available and otherwise applies its normal default. With `--run-in current-chat`, the team ID you pass must match that conversation's scope — it cannot switch the conversation to a different personal or team scope. The scope is immutable after creation | +| `--run-in` | Execution destination: `current-chat` binds the rule to the current IM conversation, `web` runs it in the web console. When omitted the server decides — it selects `current-chat` for an authenticated IM invocation and `web` otherwise. The server rejects `current-chat` outside a live IM conversation | | `--schedule` | Schedule helper: `hourly`, `daily`, `weekly`, or `cron`; defaults to `daily` when omitted | | `--at` | `HH:MM` local time (in the rule's timezone); for `hourly` only the minute is used (default 0), for `daily`/`weekly` both hour and minute (default 09:00) | | `--weekday` | Weekday for `weekly`: `sun`–`sat` or `0`–`7` (`0` and `7` both mean Sunday; defaults to Monday) | -| `--cron-expr` | Exact 5-field cron expression (interpreted in the rule's timezone); overrides the `--schedule` helpers | +| `--cron-expr` | A supported 5-field cron expression (interpreted in the rule's timezone); overrides the `--schedule` helpers. The minute must be a fixed `0`–`59` integer, so the fastest schedule is hourly; minute wildcards, ranges, lists, and steps are unsupported, and expressions such as `*/15 * * * *` or `0,30 * * * *` are rejected | | `--timezone` | IANA timezone name (for example, `Asia/Shanghai`) that `--at` and `--cron-expr` are interpreted in; when omitted the server uses the caller's member timezone, then the account timezone, then `Asia/Shanghai`. A timezone the server cannot load is rejected | | `--disabled` | Create the rule disabled (enabled by default) | | `--schedule-enabled` | Whether the schedule trigger is enabled (default `true`) | @@ -733,7 +743,9 @@ Common `create` flags: | `--prompt` / `--prompt-file` | Task prompt, exactly one required; `--prompt-file` reads from a file (`-` for stdin) | | `--environment-kind` / `--environment-id` | Runtime environment: `cloud` or `byoc` (`byoc` requires `--environment-id`); empty means automatic | -`update` accepts `--name`, `--prompt`/`--prompt-file`, `--schedule`/`--at`/`--weekday`/`--cron-expr`/`--timezone`, `--enable`/`--disable`, `--enable-schedule`/`--disable-schedule`, `--enable-http-post-trigger`/`--disable-http-post-trigger`, `--rotate-http-post-token`, and `--environment-kind`/`--environment-id`. The personal/team scope is immutable after creation, so `update` exposes no scope flag. +When you create a rule from an IM conversation, omitting `--run-in` lets the server bind the rule to that conversation and inherit its scope; you neither need to nor should pass a chat, platform, integration, or session ID — the server resolves and authorizes the current conversation. Once bound to a conversation, every ordinary run starts a fresh execution session and, where the IM integration creates threads, a fresh IM thread, and it stays on the conversation and immutable scope captured at creation rather than reusing an old session or thread; a retry of the same run reuses that run's execution identity. If the bound conversation's scope no longer matches the rule when it runs, the run is skipped — the rule is never moved or run in another conversation. War-room Automations keep their existing behavior. Because each run starts from a fresh context, write the prompt so it carries the chat context it needs (the service, the team, the delivery target) and do not refer to "above" or to an earlier session. Like the scope, the execution destination is immutable after creation. + +`update` accepts `--name`, `--prompt`/`--prompt-file`, `--schedule`/`--at`/`--weekday`/`--cron-expr`/`--timezone`, `--enable`/`--disable`, `--enable-schedule`/`--disable-schedule`, `--enable-http-post-trigger`/`--disable-http-post-trigger`, `--rotate-http-post-token`, and `--environment-kind`/`--environment-id`. The personal/team scope and the execution destination (`--run-in`) are both immutable after creation, so `update` exposes neither. `update`'s `--cron-expr` carries the same constraint as `create`: the minute must be a fixed `0`–`59` integer, so the fastest schedule is hourly, and minute wildcards, ranges, lists, and steps are unsupported. `runs` supports `--status` (`queued`/`running`/`retrying`/`succeeded`/`partial`/`failed`/`skipped`/`abandoned`), `--trigger-kind` (server-side values `schedule`/`debug`/`manual`/`http_post`/`oncall_incident`/`war_room_created`, where `war_room_created` is a run triggered by a war room being created), `--since`/`--until`, `--page`, and `--limit`. `fire` authenticates with the trigger's token (`--token`, or the `FLASHDUTY_AUTOMATION_TRIGGER_TOKEN` environment variable); `--text` passes context for the run, and `--data` passes a full JSON request body (inline JSON or `-` to read stdin). diff --git a/en/developer/go-sdk.mdx b/en/developer/go-sdk.mdx index ec2d19cc3..f0e4ab7d3 100644 --- a/en/developer/go-sdk.mdx +++ b/en/developer/go-sdk.mdx @@ -155,7 +155,7 @@ Endpoints are grouped by service and hang off the client: the call convention is | `client.Account` | Account | | `client.AuditLogs` | Audit logs | | `client.AlertRules` | Alert rules | -| `client.RuleFolders` | Rule folders; `List` lists every monitor folder the caller can read (`POST /monit/folder/list`) | +| `client.RuleFolders` | Rule folders; `ReadList` lists every folder the caller can read (`POST /monit/folder/list`), `ReadHealth` returns folder health summaries (`POST /monit/folder/health`, including active alerts and rule runtime issues in visible descendants), and `WriteCreate` / `WriteUpdate` / `WriteMove` / `WriteDelete` create, update, move, and delete folders; the old `List` is kept as a compatibility alias for `ReadList` | | `client.AlertEnrichment` | Alert enrichment | | `client.DataSources` | Data sources | | `client.Dashboards` | Dashboards; panel preview and run, panel query resolution (`QueryReadResolve`), variable resolution, plus dashboard read/write, move/restore, and revision history | @@ -167,7 +167,7 @@ Endpoints are grouped by service and hang off the client: the call convention is | `client.Analytics` | Analytics | | `client.A2aAgents` | A2A Agents | | `client.Artifacts` | AI SRE artifacts | -| `client.Automations` | AI SRE automations | +| `client.Automations` | AI SRE automations (`RuleReadGet` / `RuleReadList` / `RuleWriteCreate` / `RuleWriteUpdate` / `RuleWriteDelete` / `RuleWriteRun` / `RunReadList` / `TemplateReadList`); on create, the execution destination comes from `AutomationRuleCreateRequest.RunIn` (`current-chat` / `web`; omitted lets the server decide) and the scope from that struct's `TeamID` (a `*int64`: an explicit `0` is personal scope, omitted inherits the authenticated IM conversation's scope); `AutomationRuleUpdateRequest` no longer has `TeamID` | | `client.Knowledge` | AI SRE Knowledge (the knowledge itself and its files) | | `client.McpServers` | MCP Servers | | `client.Sessions` | AI SRE sessions | @@ -200,10 +200,24 @@ The following services have behavior that needs extra explanation: `client.Artifacts` (AI SRE artifacts) covers the 11 operations under `/safari/artifact/*`: on the gallery read side `ReadGet` (get a single published artifact by ID), `ReadList` (list artifacts visible to the caller, with title substring search and `scope` (`all` / `personal` / `team`) plus `team_ids` filtering), and `ReadGetFileState` (probe up to 50 presented-file IDs (`pf_` prefix) in one call for ones that already have a live published artifact); on the file side `ReadSign` (issue short-lived download/preview URLs for a presented file, valid 5 minutes, `expires_in` is fixed at 300) and `ReadStream` (download or preview the file's bytes with a signed token — the success body is a file, not a JSON envelope, with the raw bytes on `Response.Raw`); on the write side `WritePublish` (publish a session-produced file to the gallery), `WriteUpdate` (rename the artifact or transfer it between personal and team scope), and `WriteDelete` (detach it from the gallery; the source file stays with its session); public sharing `WriteShareEnable` (turn on anonymous public sharing and return the public link — anyone with the link can view it, no login required), `WriteShareRevoke` (turn sharing off; the link stops resolving immediately), and `WriteShareSync` (refresh the public snapshot with the latest content — when `share_enabled` is true and `share_file_id` differs from `file_id`, the snapshot is stale and calling this refreshes it). Exported types include `PublishedArtifactItem`, `ArtifactShareState`, `SignedUrLs`, and the various `Artifact*Request` / `Artifact*Response` structs. +### Automation rules + +`client.Automations` covers `/safari/automation/*`. A rule's **execution destination** (scope and where it runs) is fixed at creation time: + +- `AutomationRuleCreateRequest.RunIn` (`run_in`) is `current-chat` (binds the rule to the authenticated live IM conversation) or `web` (runs in the web console). Omitted, the server decides: `current-chat` for an authenticated IM invocation, `web` otherwise. Sending `current-chat` outside a live IM conversation is rejected. +- `AutomationRuleCreateRequest.TeamID` (`team_id`) is a `*int64`: an explicit `0` means personal scope and a value greater than 0 picks a team in the account. Omitted, it inherits the authenticated IM conversation's scope when one is present; otherwise the server applies its normal default. A `current-chat` rule's scope must match that conversation's scope. +- `AutomationRuleUpdateRequest` no longer has `TeamID` (nor `RunIn`): scope and execution destination are immutable after creation. Old code that set `TeamID` on an update request should drop the line — otherwise it will not compile. + ### Member email notifications `client.Members.MemberNotify` (`POST /member/notify`, `memberNotify`) sends an email to account members on behalf of the caller. Only a credential minted for an AI SRE session can call it. Any other credential, including a plain `app_key`, is rejected with `AccessDenied` (check with `IsAccessDenied` / `ErrorCodeOf`). Request fields are `subject` (required, 1–200 characters) and `html` (required, the full email body, up to 102,400 bytes). `person_ids` is optional: at most 20, no duplicates. If it's omitted or empty, the email goes to the caller only. `script`, `meta`, `link`, and `base` tags and `on*` event handlers are silently stripped from `html` before sending; a `style`, `svg`, `iframe`, `object`, `embed`, `form`, `input`, or `button` tag, an `img` without an `https` `src`, or a link outside `http`/`https`/`mailto` instead fails the call with `InvalidParameter` before anything is queued, naming each offending construct. Delivery is asynchronous, so `accepted` only means the email was queued. `recipients[]` returns one entry per recipient with `person_id` and `status` (`accepted` or `skipped`). A skipped entry has a `reason`: `not_member`, `no_email`, `email_disabled`, `duplicate`, `rate_limited` (at most 20 emails per recipient per hour), or `send_failed`. The response carries only two fields, `recipients[]` and an optional `agent_instructions`, and never echoes the sanitized email HTML back; `agent_instructions` is returned when the `html` doesn't follow the default email layout (no `max-width:600px` wrapper table). It tells the calling AI SRE agent how to conform. It's advisory, so an intentional layout needs no change. +### Rule folders + +`client.RuleFolders` covers the six operations under `/monit/folder/*`. `ReadList` (`POST /monit/folder/list`) and `ReadHealth` (`POST /monit/folder/health`) take no request body. The first returns a flat `[]FolderItem` that you rebuild into a tree in the client from `ParentID` / `ParentPath` (dashboards and alert rules share that same tree); the second returns a `FolderHealthOutput`, whose `FolderHealthItem.HasIssue` marks a folder that — or whose visible descendant — has active alerts or rule runtime issues. On the write side `WriteCreate` (`/monit/folder/create`) and `WriteUpdate` (`/monit/folder/update`) return the `FolderItem`, while `WriteMove` (`/monit/folder/move`) and `WriteDelete` (`/monit/folder/delete`) return only a `*Response`. Further exported types are `FolderCreateRequest`, `FolderUpdateRequest`, `FolderMoveRequest`, and `FolderDeleteRequest`. + +Request fields: `FolderCreateRequest.Name` is required and may not contain a period, slash, or comma, and a `ParentID` of 0 or omitted creates a root folder. `FolderUpdateRequest` requires both `ID` and `Name` and replaces the editable fields — omitting `Note` clears the note and omitting `TeamID` resets it to 0 (account-wide). `FolderMoveRequest` requires `DestParentID` even when moving back to the root (pass 0), and a folder cannot be moved under itself or one of its descendants. `FolderDeleteRequest` carries only `ID`; only an empty folder can be deleted, so child folders, alert rules, or dashboards inside it make the call fail with HTTP 409 and `FolderNotEmpty`. + ### Diagnostic queries `client.Diagnostics.QueryData` runs a synchronous query through `POST /monit/query/data` and returns a stable `query_result.v1` structured result (`result.kind` is one of `frames`, `records`, or `samples`). This API requires monit-edge v0.65.0 or later. For log-pattern and metric-trend analysis, use `client.DataSources.ToolsInvoke` with `prometheus.metric_trends`, `loki.log_patterns`, or `victorialogs.log_patterns`. diff --git a/en/on-call/channel/create-edit.mdx b/en/on-call/channel/create-edit.mdx index 233236b75..1954d8442 100644 --- a/en/on-call/channel/create-edit.mdx +++ b/en/on-call/channel/create-edit.mdx @@ -103,7 +103,7 @@ The wizard pre-selects the first method your subscription allows and marks that | :--- | :--- | | **Grouping fields** (rule-based grouping only) | `labels.check` by default; you can multi-select `labels.check`, `labels.service`, `labels.resource` and the alert title | | **Grouping time** | **Until the incident closes** (default) or **Fixed 60 minutes** | -| **Advanced settings → Strict grouping** (rule-based grouping only) | When on, an empty label counts as a distinct value; off by default | +| **Advanced settings → Strict grouping** (rule-based grouping only) | When on, an empty comparison field counts as a distinct value and nothing is grouped; when off (the default), fields that are empty on both sides count as equal, but at least one field must carry a value — if every comparison field is empty, nothing is grouped | | **Advanced settings → Fields used for the similarity judgement** (intelligent grouping only) | Fields used by the similarity judgement; `title`, `description`, `labels.service`, `labels.resource` by default | | **Advanced settings → Alert storm warning** | When on, reaching the merged-alert threshold (100 by default) records an alert storm event and notifies you; off by default | diff --git a/en/on-call/channel/noise-reduction.mdx b/en/on-call/channel/noise-reduction.mdx index 913770ee2..e8b058ccd 100644 --- a/en/on-call/channel/noise-reduction.mdx +++ b/en/on-call/channel/noise-reduction.mdx @@ -135,7 +135,7 @@ The Alert Grouping page offers three mutually exclusive methods. A choice takes In the create wizard, methods your subscription doesn't include are greyed out, with the tooltip "Your current subscription does not support this grouping method". The API field `group_method` carries the same choice: `i` (intelligent grouping), `p` (rule-based grouping), `n` (no grouping); see [Incident webhook](/en/on-call/integration/webhooks/incident-webhook). -The **Current effect** card at the top of the page summarizes the active method in one line: with no grouping it reads "No grouping · every alert creates its own incident"; with intelligent grouping it lists the fields used for the similarity judgement; with rule-based grouping it lists the grouping fields (and reports per-alert rules when you use them), alongside the aggregation window, the empty-value rule and the storm-warning state. Switching methods opens a confirmation dialog first: the page then swaps in the new method's settings, and nothing takes effect until you click **Save**. +The **Current effect** card at the top of the page summarizes the active method in one line: with no grouping it reads "No grouping · every alert creates its own incident"; with intelligent grouping it lists the fields used for the similarity judgement; with rule-based grouping it lists the grouping fields (and reports per-alert rules when you use them), alongside the aggregation window, the empty-value rule and the storm-warning state. Clicking another method card swaps in that method's settings right away (there is no confirmation dialog), and a draft you have already filled in is kept; nothing takes effect until you click **Save**. ### Common configuration @@ -145,7 +145,7 @@ The **Current effect** card at the top of the page summarizes the active method | **Window Timing Start** | Only configurable when the aggregation window is enabled. **Incident trigger** (default): Fixed timer starts from incident creation, stops grouping when the window duration is reached. **Alert merges into incident**: Timer resets each time a new alert merges in, the window recalculates from the last merge | | **Window Duration** | Only configurable when the aggregation window is enabled. Set the duration of the aggregation window, minimum 1 minute. Rule-based grouping and intelligent grouping share the same cap: 24 hours by default, extendable to 30 days on request (contact the Flashduty team to enable) | | **Alert Storm Warning** | When merged alert count reaches a configured threshold, the system records an alert storm event in the incident timeline and triggers a warning notification, prompting urgent handling. You can configure up to 5 thresholds, each ranging from 2 to 10,000 | -| **Strict Grouping** | When enabled, empty label values are treated as different; when disabled, empty values are treated as the same (not supported for intelligent grouping) | +| **Strict Grouping** | When enabled, an alert does not group as soon as any of the compared fields is missing; when disabled, a field empty on both sides counts as a match (missing values compare as `null`), but at least one compared field must have a value — an alert with every compared field empty does not group (not supported for intelligent grouping) | <Tabs> <Tab title="Intelligent Grouping"> diff --git a/en/on-call/comparison/vs-opsgenie.mdx b/en/on-call/comparison/vs-opsgenie.mdx index d2a4a6ee4..2172d8545 100644 --- a/en/on-call/comparison/vs-opsgenie.mdx +++ b/en/on-call/comparison/vs-opsgenie.mdx @@ -124,7 +124,7 @@ Response solves "closing the loop quickly once the right person is found": a sin | --- | --- | --- | | **AI Summaries & Post-Mortems** | Built-in AI incident summaries and one-click AI post-mortems | No equivalent | | **Autonomous Troubleshooting Agent** | [AI SRE](/en/ai-sre): a fully capable autonomous Agent loop connected to your real environment — cloud sandbox + self-hosted Runner executing diagnostic commands dynamically, extensible without limit through Skills, MCP, Subagents, and A2A; with an enabled Monitors data source, it can **query data sources directly through the alerting engine** (built-in monit-query Skill, no Runner needed) | No equivalent | -| **Native IM Troubleshooting** | [Group-chat @-mentions and private-chat troubleshooting](/en/ai-sre/im) across Feishu/Lark, DingTalk, WeCom, and Slack, with automatic initial diagnosis driven by a matching automation rule once a war room is created | No equivalent | +| **Native IM Troubleshooting** | [Group-chat @-mentions and private-chat troubleshooting](/en/ai-sre/im) across Feishu/Lark, DingTalk, WeCom, and Slack, with automatic initial diagnosis driven by a matching automation rule once a war room is created; an automation rule can also be bound to an IM chat at creation, run in that chat, and reply there | No equivalent | | **Billing** | Usage-based credits billing (1 credit = ¥1); activation is free, with gift credits each billing period | — | ### Platform & integrations diff --git a/en/on-call/comparison/vs-pagerduty.mdx b/en/on-call/comparison/vs-pagerduty.mdx index 9eedbe699..a408d8393 100644 --- a/en/on-call/comparison/vs-pagerduty.mdx +++ b/en/on-call/comparison/vs-pagerduty.mdx @@ -158,7 +158,7 @@ The two vendors take different approaches to AI. **PagerDuty splits AI across mu | --- | --- | --- | | **Product Form** | Autonomous SRE Agent: conversational troubleshooting + autonomous planning and execution + knowledge accumulation | AIOps for incident noise reduction/correlation; Advance as a generative AI assistant (summaries, Q&A, post-mortem drafts); four preset AI Agents each own a slice: SRE (diagnosis + pre-configured remediation), Scribe (meeting notes), Shift (scheduling), Insights (data Q&A) | | **Troubleshooting & Remediation** | Cloud sandbox + self-hosted [Runner (BYOC)](/en/ai-sre/environments), dynamically executing diagnostic commands and querying monitoring data and logs within your environment—**able to investigate problems it has never seen before**; with an enabled Monitors data source, it can **query data sources directly through the alerting engine** (built-in monit-query Skill, no Runner needed) | SRE Agent can automatically analyze logs/metrics and match them against historical incidents; remediation actions depend on **pre-configured** Automation Actions scripts | -| **Native IM Collaboration** | [Group-chat @-mentions and private-chat troubleshooting](/en/ai-sre/im) across Feishu/Lark, Dingtalk, WeCom, and Slack, with **automatic initial diagnosis driven by a matching automation rule once a war room is created** | Primarily Slack and Teams, no China-region IM support | +| **Native IM Collaboration** | [Group-chat @-mentions and private-chat troubleshooting](/en/ai-sre/im) across Feishu/Lark, Dingtalk, WeCom, and Slack, with **automatic initial diagnosis driven by a matching automation rule once a war room is created**; an automation rule can also be bound to an IM chat at creation, run in that chat, and reply there | Primarily Slack and Teams, no China-region IM support | | **Code Repositories & K8s** | [GitHub/GitLab App](/en/ai-sre/apps) accesses code repositories from within the sandbox and can submit PRs/MRs/Issues; a Kubernetes App connects to clusters at the namespace level | Not found in public materials | | **AI Automation Tasks** | [Automations](/en/ai-sre/automations) trigger on a cron schedule, by HTTP API, on incident events, or when a war room is created, with built-in templates for alert noise analysis, incident post-mortems, on-call insights, and more; on-call incident triggers support **similar-incident merge analysis** (incidents with similarity ≥0.9 join the in-progress analysis session) | Relies on the separate Event Orchestration and Runbook Automation product lines | | **Extensibility** | [Skills marketplace](/en/ai-sre/skills), [MCP external tools](/en/ai-sre/mcp), [Subagent and A2A delegation](/en/ai-sre/agents), **with no ceiling on the extension surface** | SRE Agent is limited to toggling official preset connectors (about 23, for example, Datadog, Splunk, CloudWatch) and appending prompt-style Skills; it doesn't support mounting arbitrary MCP tools to its own agents, has no subagent spawning, and cross-vendor agent collaboration is still in early access | diff --git a/en/on-call/configuration/filter-conditions.mdx b/en/on-call/configuration/filter-conditions.mdx index fed818d71..35d8354e7 100644 --- a/en/on-call/configuration/filter-conditions.mdx +++ b/en/on-call/configuration/filter-conditions.mdx @@ -91,6 +91,12 @@ Target values are always strings; the format decides the matching method: **rege - `*` matches zero or more characters - `?` matches a single character + Every character other than `*` and `?` matches **literally** and is never read as a regex: the `[` and `]` in `host[0-9]*`, the `(`, `)` and `|` in `(a|b)*`, and the `.` in `host.*` are all ordinary characters — `host[0-9]*` matches only values that start with the literal text `host[0-9]`. To use a character class or a group, write a regex instead, for example `/^host[0-9]+.*$/`. + + <Note> + Stored wildcard values that were written as regexes are rewritten by the system into the equivalent `/^...$/` regex (for example `BDP.*` becomes `/^BDP.[\s\S]*$/`), which matches exactly what it matched before. Reopening such a condition shows it in the `/.../` form, handled as **Regex Matching**. + </Note> + **Example**: - `labels.check`: `outage*` — matches when check label starts with "outage" diff --git a/en/on-call/integration/alert-integration/routing-rules.mdx b/en/on-call/integration/alert-integration/routing-rules.mdx index da6097470..d0475ed3f 100644 --- a/en/on-call/integration/alert-integration/routing-rules.mdx +++ b/en/on-call/integration/alert-integration/routing-rules.mdx @@ -34,7 +34,7 @@ Go to Integration Center → Alert Events → Integration Details → **Routing* | Method | Example | Recognition rule | | :------- | :----------------------- | :-------------------------------- | | **Exact** | `cpu.idle<10%` | When nothing else matches, values must be identical | -| **Wildcard** | `host * down` | A value containing `*` or `?` and no `/` prefix/suffix is treated as a wildcard | +| **Wildcard** | `host * down` | A value containing `*` or `?` and no `/` prefix/suffix is treated as a wildcard (every other character matches literally; use `/.../` when you need a regex) | | **Regex** | `/api-server-\d+/` | A value wrapped in `/` is treated as an RE2 regex | | **CIDR** | `cidr:192.168.1.0/24` | A value prefixed with `cidr:` matches by IP range | | **Numeric** | `num:gt:0.95` | A value prefixed with `num:` plus a comparison operator (`gt`/`ge`/`lt`/`le`) is compared numerically | diff --git a/en/on-call/integration/instant-messaging/dingtalk.mdx b/en/on-call/integration/instant-messaging/dingtalk.mdx index 51930bffa..f899a42d8 100644 --- a/en/on-call/integration/instant-messaging/dingtalk.mdx +++ b/en/on-call/integration/instant-messaging/dingtalk.mdx @@ -14,7 +14,7 @@ This documentation uses the new version of Dingtalk Open Platform as an example. ## Required permissions -Request these permissions on the Dingtalk Open Platform **Permission Management** page. Basic notifications need the first two; War Room adds items 3–5 (item 5 is also used for one-click user linking); a Dingtalk AI streaming card template adds the last two. +Request these permissions on the Dingtalk Open Platform **Permission Management** page. Basic notifications need the first two; War Room adds items 3–5 (item 5 is also used for automatic member linking); a Dingtalk AI streaming card template adds the last two. | Official permission name | Purpose | | :--- | :--- | @@ -22,7 +22,7 @@ Request these permissions on the Dingtalk Open Platform **Permission Management* | `qyapi_robot_sendmsg` | Send bot messages for basic notifications, session-webhook bot replies, standard interactive cards, War Room messages, and downloading files received by the bot | | `qyapi_chat_read` | Read group chat information for War Room group status checks and member handling | | `qyapi_chat_base_read` | Read basic group chat information for War Room group queries | -| `qyapi_get_member_by_mobile` | Get Dingtalk user IDs by phone number for one-click user linking and inviting members to War Rooms | +| `qyapi_get_member_by_mobile` | Get Dingtalk user IDs by phone number for automatic member linking, one-click user linking, and inviting members to War Rooms | | `Card.Instance.Write` | Create and deliver AI SRE streaming cards; required only when a Dingtalk AI streaming card template is enabled | | `Card.Streaming.Write` | Update AI SRE streaming card content; required only when a Dingtalk AI streaming card template is enabled | @@ -233,9 +233,21 @@ In the **Linked Users** tab of the integration detail page, you can view the lin The list shows every team member and their linking status. Filter by **All / Linked / Unlinked**, or search by name or email. +### Automatic linking + +Members do not need to do anything: the system links them automatically. + +- Once immediately after you save the integration +- Once an hour afterwards, across every enabled Dingtalk integration + +Automatic linking resolves each member's verified phone number in the personal center to a Dingtalk account ID (Dingtalk has no lookup by email), equivalent to the member logging into Flashduty with the same phone number on Dingtalk. Two limits keep it from retrying immediately: + +- A member Dingtalk answered for but no binding was created — the phone number is unknown on the Dingtalk side, or that Dingtalk account is already linked to another member — is not looked up again for 7 days; changing the member's phone number triggers a new attempt +- When the Dingtalk app lacks the `qyapi_get_member_by_mobile` permission (error code 60011) or the server IP is outside the app's whitelist (error code 60020), automatic linking pauses for that integration for 24 hours; fix the permission or whitelist and save the integration again to resume + ### One-click linking -When unlinked members exist, click the **One-Click Link** button. The system will attempt to obtain Dingtalk account IDs by phone numbers and automatically link them, equivalent to members logging into Flashduty using the same phone number on Dingtalk. +When unlinked members exist, click the **One-Click Link** button. The system will attempt to obtain Dingtalk account IDs by phone numbers and automatically link them, equivalent to members logging into Flashduty using the same phone number on Dingtalk. The button ignores the 7-day window above and looks everyone up again right away; if it reports **no new members linked**, this run produced no new binding — for example the phone number is unknown on the Dingtalk side, or the matching Dingtalk account is already linked to another member. <Tip> The system can only push Dingtalk message notifications after members complete linking. If linking fails, verify that the member's phone number matches their Dingtalk account. @@ -246,6 +258,8 @@ The system can only push Dingtalk message notifications after members complete l <AccordionGroup> <Accordion title="Messages cannot be delivered to individuals, operation log shows 'App not linked'?"> Go to Dingtalk → Workspace → Search app name → **Open App**, and sign in once to link your Dingtalk and Flashduty accounts. Flashduty needs this identity to deliver messages. + +If the member has already verified a phone number in the personal center, the system may have linked the account automatically, without any sign-in; check the current linking status in the **Linked Users** tab of the integration detail page. </Accordion> <Accordion title="Message card buttons not working or showing errors?"> diff --git a/en/on-call/integration/instant-messaging/lark.mdx b/en/on-call/integration/instant-messaging/lark.mdx index 870556769..405f3393b 100644 --- a/en/on-call/integration/instant-messaging/lark.mdx +++ b/en/on-call/integration/instant-messaging/lark.mdx @@ -155,9 +155,17 @@ In the **Linked Users** tab of the integration detail page, you can view the lin The list shows every team member and their linking status. Filter by **All / Linked / Unlinked**, or search by name or email. +### Automatic linking + +Members do not need to do anything: the system links them automatically — once immediately after you save the integration, and once an hour afterwards, across every enabled Feishu/Lark integration. + +Automatic linking resolves each member's verified phone number or email in the personal center in batches of 50 to obtain Feishu/Lark account IDs. Feishu returns an empty `user_id` both for accounts it cannot find and for users outside the app's **visibility scope**, so both count as not found. If the Feishu/Lark app lacks contact permissions (error codes 99991672 / 99991679) or Feishu rejects its credentials, automatic linking pauses for that integration for 24 hours; grant the permissions and save the integration again to resume. + +A member the platform answered for but whose Feishu/Lark account was not found is not looked up again for 7 days; changing the member's contact information triggers a new attempt. + ### One-click linking -When unlinked members exist, click the **One-Click Link** button. The system will attempt to obtain Feishu/Lark account IDs by phone numbers or emails and automatically link them, equivalent to members logging into Flashduty using the same information on Feishu/Lark. +When unlinked members exist, click the **One-Click Link** button. The system will attempt to obtain Feishu/Lark account IDs by phone numbers or emails and automatically link them, equivalent to members logging into Flashduty using the same information on Feishu/Lark. The button ignores the 7-day window above and looks everyone up again right away; if it reports **no new members linked**, this run produced no new binding. <Tip> The system can only push Feishu/Lark message notifications after members complete linking. If linking fails, verify that the member's phone number or email matches their Feishu/Lark account. @@ -168,6 +176,8 @@ The system can only push Feishu/Lark message notifications after members complet <AccordionGroup> <Accordion title="Messages cannot be delivered to individuals, operation log shows 'App not linked'?"> Go to Feishu/Lark → Workspace → Search app name → **Open App**, and sign in once to link your Feishu/Lark and Flashduty accounts. Flashduty needs this identity to deliver messages. + +If the member has already verified a phone number or email in the personal center, the system may have linked the account automatically, without any sign-in; check the current linking status in the **Linked Users** tab of the integration detail page. </Accordion> <Accordion title="Message card buttons not working or showing errors?"> diff --git a/en/on-call/integration/instant-messaging/slack.mdx b/en/on-call/integration/instant-messaging/slack.mdx index 9bc67e2cd..550fe0545 100644 --- a/en/on-call/integration/instant-messaging/slack.mdx +++ b/en/on-call/integration/instant-messaging/slack.mdx @@ -40,21 +40,13 @@ These controls do not take effect until AI SRE is enabled for the account. The automatic AI incident analysis that follows a War Room creation is no longer configured on this page: to start one when a War Room is created, add a rule in [Automations](/en/ai-sre/automations), choose the **War room created** trigger, and select the channels and severities to watch. -## Linked users +## Member linking -In the **Linked Users** tab of the integration detail page, you can view the linking status between team members and Slack accounts, and quickly complete batch linking. +The Slack integration has no member-linking page: the integration detail page shows only the configuration page — there is no **Linked Users** tab and no **One-Click Link** button, and Flashduty does not exchange member phone numbers or emails for Slack account IDs to link them in bulk. -### View linking status +Slack identifies members by **email**: when a member acts on an alert card in Slack, Flashduty reads that Slack account's email and matches it against the member emails of the account, treating a match as that member. So there is nothing to link member by member — but the member's Slack email and Flashduty member email must match. When they do not, the system replies in Slack with a note that no member matched. -The list shows every team member and their linking status. Filter by **All / Linked / Unlinked**, or search by name or email. - -### One-click linking - -When unlinked members exist, click the **One-Click Link** button. The system will attempt to obtain Slack account IDs by phone numbers or emails and automatically link them, equivalent to members logging into Flashduty using the same information on Slack. - -<Tip> -The system can only push Slack message notifications after members complete linking. If linking fails, verify that the member's email matches their Slack account. -</Tip> +Slack is connected per **workspace**: once the OAuth authorization in [Install app](#install-app) completes, channel notifications, @mentioning AI SRE in a group chat, and War Rooms are available in that workspace. <span id="aisre-permissions"></span> <span id="war-room-scope"></span> diff --git a/en/rum/error-tracking/error-viewing.mdx b/en/rum/error-tracking/error-viewing.mdx index d63c7d9f1..739b41913 100644 --- a/en/rum/error-tracking/error-viewing.mdx +++ b/en/rum/error-tracking/error-viewing.mdx @@ -39,7 +39,7 @@ The Issue list can be **sorted by priority**, and the Priority filter is include ## Issue status -Issues have 4 statuses, with transitions as follows: +Issues have 4 statuses; **Resolved** is split by how a recurrence is handled into two selectable options, **Resolved** and **Resolved in next version**. The transitions are as follows: <Frame> <img src="https://docs-cdn.flashcat.cloud/imges/png/d81cfab46793c24b044c8d87ef30402b.png" alt="Issue Status Transitions" /> @@ -49,7 +49,7 @@ Issues have 4 statuses, with transitions as follows: |--------|-------------| | **For Review** | Newly discovered issues that need attention | | **Reviewed** | Confirmed issues being fixed | -| **Resolved** | Issues that have been fixed | +| **Resolved** | Issues that have been fixed; split by how a recurrence is handled into **Resolved** (reopens if it occurs again, including in the same version, and is marked Regression) and **Resolved in next version** (reopens only if it occurs in a newer version). Switchable in the status selector | | **Ignored** | Issues that don't need handling | <Tip> @@ -176,7 +176,7 @@ Regression refers to previously fixed bugs reappearing. </Frame> <Warning> -If a resolved error occurs again in a different version, the Issue reopens and is marked "Regression". +If a resolved error occurs again afterwards, the Issue reopens from its closed state and is marked "Regression". Whether it reopens depends on the Issue's resolve mode: with **Resolved** (`resolve_mode=any`) any recurrence reopens it, including in the same version; with **Resolved in next version** (`resolve_mode=version`, the default) it reopens only when it occurs in a newer version. See the "Resolve mode" section of [Issue Status](./issue-status). </Warning> ## Issue details diff --git a/en/rum/error-tracking/issue-status.mdx b/en/rum/error-tracking/issue-status.mdx index 45c5c5b99..df54b0ea3 100644 --- a/en/rum/error-tracking/issue-status.mdx +++ b/en/rum/error-tracking/issue-status.mdx @@ -12,7 +12,7 @@ In Error Tracking, all Issues have a status that helps you categorize and priori | **For Review** | `for_review` | New issues or regressions that need attention | | **Reviewed** | `reviewed` | Categorized issues that need fixing, can be handled immediately or later | | **Ignored** | `ignored` | Issues that don't require further investigation or handling | -| **Resolved** | `resolved` | Issues that have been fixed and are no longer occurring | +| **Resolved** | `resolved` | Issues that have been fixed and are no longer occurring; split by how a recurrence is handled into two selectable options, **Resolved** and **Resolved in next version** (see [Resolve mode](#resolve-mode)) | <Info> All newly discovered Issues have an initial status of **For Review (for_review)**. Flashduty automatically updates status based on specific conditions, and you can also manually adjust it. @@ -37,18 +37,21 @@ Properly configuring your application's `version` tag is crucial for accurately ## Auto-reopen issues -Flashduty has Issue detection capability. When a resolved Issue reappears, the system automatically reopens it and marks it as **For Review (for_review)** status, while recording the event as "Regression" in the activity timeline. +Flashduty has Issue detection capability. When a resolved Issue reappears and meets the condition set by the Issue's **resolve mode**, the system automatically reopens it and marks it as **For Review (for_review)** status, while recording the event as "Regression" in the activity timeline. ### What is regression? -Regression refers to previously fixed problems unexpectedly reappearing after code updates. Flashduty's regression detection automatically identifies these situations, reopening related Issues instead of creating duplicate Issues, thereby preserving the complete context and history of the problem. +Regression refers to previously fixed problems reappearing — most often unexpectedly, after a code update. Flashduty's regression detection automatically identifies these situations, reopening related Issues instead of creating duplicate Issues, thereby preserving the complete context and history of the problem. ### Regression detection mechanism +When an error is grouped into a **Resolved (resolved)** Issue, whether it counts as a regression depends on the Issue's **resolve mode** (see [Resolve mode](#resolve-mode) below): + <Warning> -Regression detection is triggered when any of the following conditions are met: -- If a **Resolved (resolved)** error reappears in an updated version of the code -- If a **Resolved (resolved)** error reappears when no version tag is set +- Resolve mode **Resolved in next version (`version`, the default)**: detection is triggered only when the error recurs in a version the Issue has not seen before +- Resolve mode **Resolved (`any`)**: any recurrence triggers detection, including a repeated occurrence in the same version +- When an error carries no `version` tag, both resolve modes trigger detection +- An error that occurred before the Issue was resolved does not trigger detection (a redelivered duplicate, or an old error an SDK buffered offline and flushed late) </Warning> Once regression is detected, Flashduty will: @@ -64,7 +67,7 @@ Once regression is detected, Flashduty will: ### Associated version configuration -Regression detection considers the service version information when the error occurred. Detection is only triggered in new versions after the Issue is marked as **Resolved (resolved)**. +Regression detection considers the service version information when the error occurred. With the default resolve mode **Resolved in next version (`version`)**, detection is only triggered in new versions after the Issue is marked as **Resolved (resolved)** — versions the Issue has not seen before; with resolve mode **Resolved (`any`)**, the version is not compared, so a recurrence in the same version triggers detection too. ```javascript window.FLASHCAT_RUM.init({ @@ -78,6 +81,21 @@ window.FLASHCAT_RUM.init({ Without a version tag, a resolved Issue that gets new errors is still marked "Regression". However, the system can't tell whether the errors came from a new version. </Note> +## Resolve mode + +In the status selector, **Resolved** is split into two options by how a recurrence of the error is handled. Both write the `resolved` status; they differ in the Issue's resolve mode field, `resolve_mode`: + +| Selector option | Resolve mode | Behaviour on recurrence | +|-----------------|--------------|-------------------------| +| **Resolved** | `any` | Reopens if it occurs again: a repeated occurrence in the same version reopens it too | +| **Resolved in next version** | `version` | Reopens only if it occurs in a newer version: only a recurrence in a version the Issue has not seen before reopens it | + +- You can switch between the two options at any time in the status selector; switching only the resolve mode changes neither the Issue's statistics nor its alert state. +- New Issues default to **Resolved in next version (`version`)**; Issues created before resolve mode existed are also treated as `version`, so their behaviour stays the same as before. +- When the system auto-resolves an Issue, it also writes `version`. +- When an error carries no `version` tag, both resolve modes reopen the Issue — without version information there is no way to tell the fixed code from the old one. +- On reopen, the Issue is set to **For Review (for_review)** and marked "Regression", and the time and version of the recurrence are recorded. The status cell in the list is too narrow to show both, so both resolve modes display as **Resolved**; the details panel additionally prints "Resolved in next version" next to it. + ## Manually update status You can manually update Issue status anywhere Issues are displayed, including the Issue list or details panel. @@ -86,7 +104,7 @@ You can manually update Issue status anywhere Issues are displayed, including th <img src="https://docs-cdn.flashcat.cloud/images/png/a57c54a6a28915dec4480a9db9411e30.png" alt="Manually Update Status" style={{maxWidth: "600px", margin: "0 auto", display: "block"}} /> </Frame> -Click the current status and select the new status from the dropdown menu. +Click the current status and select the new status from the dropdown menu. The dropdown has 5 options: **For Review**, **Reviewed**, **Resolved**, **Resolved in next version**, and **Ignored**; each of the two Resolved options shows its own reopen hint below the label — see [Resolve mode](#resolve-mode) for the difference. ## Best practices diff --git a/zh/ai-sre/automations.mdx b/zh/ai-sre/automations.mdx index 34ca9a7c1..442c77113 100644 --- a/zh/ai-sre/automations.mdx +++ b/zh/ai-sre/automations.mdx @@ -1,7 +1,7 @@ --- title: 自动化 description: 让 AI SRE 按 cron 周期、HTTP API、On-call 故障事件或作战室创建自动运行一次任务,用一段任务提示词产出巡检、洞察或复盘结果;本文介绍自动化规则的新建、配置字段、触发方式、运行历史与权限。 -keywords: ["AI SRE", "自动化", "Automation", "巡检", "定时任务", "cron", "HTTP 触发", "On-call 故障触发", "作战室创建触发", "手动执行", "运行历史", "隐藏会话"] +keywords: ["AI SRE", "自动化", "Automation", "巡检", "定时任务", "cron", "HTTP 触发", "On-call 故障触发", "作战室创建触发", "手动执行", "运行历史", "隐藏会话", "执行位置"] sidebarTitle: 自动化 --- @@ -23,7 +23,7 @@ sidebarTitle: 自动化 入口:左侧导航 **AI SRE → 自动化**,对应路由 `/ai-sre/automations`。 <Note> -自动化跑出的每一次运行,本质上仍是一个 AI SRE 会话——只是它被标记为隐藏,不混进您的日常会话列表。您随时可以从运行历史点进去,看到这次运行完整的对话、工具调用与产物(跑在 IM 群里的 **作战室创建触发** 运行除外,见下文“作战室创建触发(War room created)”)。 +自动化跑出的每一次运行,本质上仍是一个 AI SRE 会话——只是它被标记为隐藏,不混进您的日常会话列表。**Web** 执行位置的运行随时可以从运行历史点进去,看到这次运行完整的对话、工具调用与产物;**IM** 执行位置的运行(含 **作战室创建触发** 的运行)的对话在 IM 群里,控制台不暴露它的会话,也点不进去,见下文“执行位置”。 </Note> ## 新建自动化 @@ -39,7 +39,15 @@ sidebarTitle: 自动化 </Step> </Steps> -无论从哪条入口进入,接下来都是同一张配置表单。 +无论从哪条入口进入,接下来都是同一张配置表单。控制台的两个入口一律创建 **Web** 执行位置的规则,也就是运行在控制台里的隐藏会话;要让规则跑在某个 IM 群聊里,得从 IM 会话里创建,见下节。 + +### 在 IM 会话里创建(绑定当前会话) + +在 IM 群聊或私聊里让 Agent 建一条自动化,不指定执行位置时,规则就绑定到**当前这个会话**,并继承它的范围(包括当前绑定的团队)。用命令行等同:`flashduty automation create` 在 IM 会话里发起时省略 `--run-in` 即可(见 [命令行工具](/zh/developer/cli))。要点: + +- 绑定后每次运行都在那个群聊里新开会话,不在控制台里建会话;原群聊固定不变。 +- 想让它跑在 **Web** 上(也就是控制台里的隐藏会话),创建时就得说清楚(在对话里要求用 Web 控制台执行,或命令行加 `--run-in web`)。规则建好之后改不了,只能重建一条。 +- 不要自己传 chat、平台、集成或会话 ID,服务端负责解析并鉴权当前会话。 ## 配置字段 @@ -48,8 +56,8 @@ sidebarTitle: 自动化 | 字段 | 必填 | 说明 | |---|---|---| | 名称 | 是 | 规则名称,最长 255 字符。占位示例:`每周值班洞察`。 | -| 范围 | 是 | 通过 **范围选择器** 选 **个人**(`team_id=0`)或某个 **团队**(`team_id>0`)。范围既决定这条规则的归属与编辑权限,也限定 **执行 Environment** 里可选的自托管 Runner——只有账户全局的 Runner,以及与该范围同团队的 Runner 才可选。 | -| 执行环境 | 否 | 通过 **环境选择器** 选运行环境:**自动**(由系统挑选最优可用环境,默认值)、**云端沙箱**,或某个 **自托管(BYOC)Runner**。选了某个团队范围后,不属于该范围的团队 Runner 会被自动清除。 | +| 范围 | 是 | 通过 **范围选择器** 选 **个人**(`team_id=0`)或某个 **团队**(`team_id>0`)。范围既决定这条规则的归属与编辑权限,也限定 **执行 Environment** 里可选的自托管 Runner——只有账户全局的 Runner,以及与该范围同团队的 Runner 才可选。范围创建后不可修改,规则详情页里把它展示为 **固定范围**。 | +| 执行环境 | 否 | 通过 **环境选择器** 选运行环境:**自动**(由系统挑选最优可用环境,默认值)、**云端沙箱**,或某个 **自托管(BYOC)Runner**。选了某个团队范围后,不属于该范围的团队 Runner 会被自动清除。**IM** 执行位置的规则不使用这里选的环境(见下文“执行位置”)。 | | 任务提示词 | 是 | 描述要让 AI SRE 执行的任务,用富文本编辑器撰写。这段提示词就是每次运行时发给 Agent 的内容。占位提示:`描述 Flashduty AI SRE 要执行的任务。` | | 时区 | 否 | **按周期执行** 触发卡片里的字段(见下文“按周期执行(cron)”):cron 表达式所依据的 **规则时区**,用一个可搜索的下拉框选择 IANA 时区名(如 `Asia/Shanghai`),选项按下拉框里的 UTC 偏移排列。新建规则时默认为你的生效时区(成员时区优先,成员未设置时回退账户时区);没有可用时区时该字段留空,创建请求不携带它。 | @@ -57,6 +65,35 @@ sidebarTitle: 自动化 **执行环境** 的“自动”会在每次运行时由系统挑选当前最优的可用环境;“云端沙箱”是平台托管的临时沙箱;自托管 Runner 则把运行落在您自己的机器上。三者的差异与连接方式见 <a href="/zh/ai-sre/environments">运行环境</a>。 </Note> +## 执行位置(规则跑在哪里) + +每条规则有一个 **执行位置**,在创建时固定,之后不能在控制台修改: + +- **Web**(默认):每次运行是控制台里的一个隐藏会话。控制台创建的规则一定是这个取值。 +- **IM**:运行发生在创建时绑定的那个 IM 群聊 / 私聊里。IM 执行位置的规则不在控制台新建会话——它的每一次运行都在原来的群聊里 **新开一个会话**;该 IM 集成开启话题时,每次运行还会新开一个话题;同一次运行的重试仍复用这次的会话与话题;原来的群聊永远不变。 + +规则列表的 **执行位置** 列、规则详情页“配置信息”里的 **执行位置** 一项都显示这个取值(`IM` 或 `Web`)。一条规则同时启用了 **作战室创建触发** 和其它触发时,这一列显示两枚徽标:**作战室触发→IM** 与 **其他触发→Web**。**作战室创建触发** 是唯一不使用规则执行位置的触发方式,它按作战室所在群执行,见下文“作战室创建触发(War room created)”。 + +执行位置为 **IM** 的规则还有两点与 Web 规则不同: + +- 控制台不提供 **克隆**。要把一条 IM 规则换成 Web 执行,只能重建一条。 +- 控制台不暴露这类运行的会话标识:运行历史里它的“名称”列显示 `-`,点击该行只提示 **本分析位于 IM,请进入 IM 查看。**;从规则行手动执行它也不会跳进会话,见下文“运行历史”与“管理与权限”。 + +**执行环境**:IM 执行位置的规则不使用规则上选的 **执行环境**——运行在那个群聊里,用的是该群聊已经选好的执行环境(可在会话里用 `/env` 更换)。控制台表单对这类规则照常显示环境选择器,但它对 IM 运行不生效。作战室创建触发有同样的例外,见下文“作战室创建触发(War room created)”。 + +**绑定失效就跳过**:如果运行发生时,绑定群聊的范围或会话已经变了(例如在群里用 `/scope` 换过绑定的团队,或这个群重开过一次会话),本次运行会被 **跳过**——运行历史里状态为 `已跳过`、原因 `chat_scope_mismatch`。规则本身保持启用,也不会被搬到别的群里去执行;要换群请重建一条规则。 + +### 经 API / CLI 创建时怎么指定(`run_in`) + +控制台创建的规则一律是 **Web** 执行位置;经 API 或 CLI 创建时,用 `run_in` 明确指定: + +| 字段 | 类型 | 说明 | +|---|---|---| +| `run_in` | string | `current-chat`:把规则绑定到鉴权来源所在的 **实时 IM 会话**,只能在该 IM 会话里发起调用时使用,在别处传会被拒绝;`web`:在控制台里执行,即执行位置 **Web**。省略时由服务端决定——来自 IM 会话的调用取 `current-chat`,其余取 `web`。 | +| `team_id` | int64 | 规则的归属范围。显式 `0` 表示个人范围,大于 `0` 表示账户内的某个团队;省略时,来自 IM 会话的调用继承该会话的范围,其余取服务端常规默认值。`run_in=current-chat` 时,显式传入的值必须与该会话的范围一致。 | + +`update` 不接受 `run_in`,也不能变更 `team_id`(传入改动过的值会被拒绝):**执行位置与范围一样,创建后不可变更**。命令行对应参数见 [命令行工具](/zh/developer/cli)。 + ## 触发方式 一条规则必须 **至少配置一种触发方式**。当前控制台表单在“触发方式”区提供 **按周期执行**、**经 API 调用**、**On-call 故障触发** 与 **作战室创建触发** 四种入口,四种可同时启用。 @@ -223,7 +260,7 @@ curl -X POST 'https://<触发地址>' \ 匹配的作战室创建后,系统会以 `war_room_created` 作为 `trigger_kind` 创建运行,并把 `incident_id`、`channel_id`、`severity` 等上下文带进会话。这次运行不在控制台里新建会话,而是直接在作战室群里跑一轮分析,结论也发回这个群。同一条触发器下、同一个故障只启动一次运行,重复的事件不会另起会话。 -**执行环境**:这条触发方式不使用规则上的 **执行环境**——作战室里的分析用群里已经选好的执行环境。规则的唯一触发方式是作战室创建时,表单不显示环境选择器,只提示“作战室里的分析用这个群已经选好的执行环境,规则上不再选。”;同时启用了周期 / API / 故障触发时,环境选择器照常出现,并提示“周期、API 和故障触发使用这里的执行环境。作战室触发使用群里的执行环境,不会改掉群里已经选好的。”。 +**执行环境**:这条触发方式不使用规则上的 **执行环境**——作战室里的分析用群里已经选好的执行环境。规则的唯一触发方式是作战室创建时,表单不显示环境选择器,只提示“作战室里的分析用这个群已经选好的执行环境,规则上不再选。”;同时启用了周期 / API / 故障触发时,环境选择器照常出现,并提示“周期、API 和故障触发使用这里的执行环境。作战室触发使用群里的执行环境,不会改掉群里已经选好的。”。**IM** 执行位置的规则有同样的例外,见上文“执行位置”。 预设模板 **作战室初步分析**(模板键 `war_room_initial_analysis`,分类 **故障响应**)预置了这条触发方式与 `Critical` 严重程度;协作空间不由模板预置,需要您自己选。 @@ -235,11 +272,11 @@ curl -X POST 'https://<触发地址>' \ | 列 | 说明 | |---|---| -| 名称 | 本次运行对应的隐藏会话标题(`session_name`),解析不到时显示会话 ID(`session_id`)。被并入其它分析的运行没有自己的会话,改显示对应的故障(`#<num> <title>`),并在下一行标明并入了哪次分析 | +| 名称 | 本次运行对应的隐藏会话标题(`session_name`),解析不到时显示会话 ID(`session_id`);**IM** 执行位置的运行两者都不显示,只显示 `-`(这类运行的对话在 IM 群里,控制台不暴露它的会话标识)。被并入其它分析的运行没有自己的会话,改显示对应的故障(`#<num> <title>`),并在下一行标明并入了哪次分析 | | 执行时间 | 本次运行的开始时间 | | 耗时 | 本次运行的持续时长 | | 触发方式 | 本次运行的触发类型标签,如 `定时`(schedule)、`HTTP POST`、`On-call incident`、`手动执行` 或 `作战室创建触发`(war_room_created) | -| 执行位置 | 本次运行跑在哪里:`IM`(会话在 IM 群里,例如作战室创建触发的运行)或 `Web 控制台`(控制台里的隐藏会话)。对应 API 字段 `execution_place`,取值为 `im` / `web_console`;记录里没有这个字段时,作战室创建触发的运行按 `IM` 显示,其余按 `Web 控制台` 显示 | +| 执行位置 | 本次运行跑在哪里:`IM`(会话在 IM 群里,例如作战室创建触发的运行)或 `Web`(控制台里的隐藏会话)。对应 API 字段 `execution_place`,取值为 `im` / `web_console`;记录里没有这个字段时,作战室创建触发的运行按 `IM` 显示,其余按 `Web` 显示 | | 状态 | 本次运行的状态(见下表) | 运行状态的取值: @@ -251,7 +288,7 @@ curl -X POST 'https://<触发地址>' \ | `succeeded` | 成功 | | `partial` | 部分成功 | | `failed` | 失败 | -| `skipped` | 已跳过。两种情形共用这个状态:触发时判定不执行(例如规则所有者已失效、周期已停止),或该故障被并入另一个正在运行的分析(见上文“相似故障合并分析”) | +| `skipped` | 已跳过。三种情形共用这个状态:触发时判定不执行(例如规则所有者已失效、周期已停止);该故障被并入另一个正在运行的分析(见上文“相似故障合并分析”);或 **IM** 执行位置的规则触发时,绑定群聊的范围 / 会话已经变了(这类运行不换群,直接跳过,见上文“执行位置”) | | `blocked` | 已阻塞。本次运行产生了真实输出,但停在等待人工处理的连接器上——某个连接器还没配置,或需要管理员在控制台完成授权 | | `abandoned` | 已放弃(长时间未完成被系统终止) | @@ -261,7 +298,7 @@ curl -X POST 'https://<触发地址>' \ - **状态**:按上表中的运行状态过滤,或选 **全部状态**。 - **触发类型**:`全部触发类型` / `手动执行` / `定时` / `HTTP POST` / `On-call incident` / `作战室创建触发` 六选一。 -API 返回的运行记录还包含 `trigger_kind`,可能取值为 `schedule`、`manual`、`http_post`、`oncall_incident`、`war_room_created` 或 `debug`。其中 `manual` 表示通过立即执行接口启动,`oncall_incident` 表示由匹配的 On-call 故障事件启动,`war_room_created` 表示由作战室创建触发启动(会话在 IM 群里)。被并入其它分析的运行不返回自己的 `session_id`,而是返回它并入的那次分析的会话 ID `joined_session_id` 与会话名 `joined_session_name`;这两个字段为空,表示这次运行有自己的隐藏会话。 +API 返回的运行记录还包含 `trigger_kind`,可能取值为 `schedule`、`manual`、`http_post`、`oncall_incident`、`war_room_created` 或 `debug`。其中 `manual` 表示通过立即执行接口启动,`oncall_incident` 表示由匹配的 On-call 故障事件启动,`war_room_created` 表示由作战室创建触发启动(会话在 IM 群里)。`execution_place` 为 `im` 的运行不返回会话身份:`session_id` 与 `joined_session_id` 都是空的,`result_json` 也不下发——只保留状态、时间与错误字段。被并入其它分析的运行不返回自己的 `session_id`,而是返回它并入的那次分析的会话 ID `joined_session_id` 与会话名 `joined_session_name`;这两个字段为空,表示这次运行有自己的隐藏会话。 点击一行,会跳转到这次运行对应的隐藏会话对话页,让您查看该次运行完整的消息、工具调用与产物。跑在 IM 群里的运行(`execution_place=im`,或由 `war_room_created` 触发)不跳转,而是弹出一句 **本分析位于 IM,请进入 IM 查看。**——这次分析的对话在 IM 群里读。被并入其它分析的运行没有自己的会话,点击它会打开接管这个故障的那次分析。 @@ -277,6 +314,7 @@ API 返回的运行记录还包含 `trigger_kind`,可能取值为 `schedule` | 本次执行被中断(`interrupted`) | — | | 执行已结束,但没有生成最终回复(`no_final_response`) | — | | 已并入另一次分析(`similar_incident_fan_in`) | 点击该行打开接管故障的分析 | +| 绑定群聊的范围或会话已变化,本次未执行(`chat_scope_mismatch`) | 规则仍启用,仍在原群聊执行;需要换群请新建规则 | 其他原因直接显示系统记录的文本。 @@ -293,7 +331,7 @@ API 返回的运行记录还包含 `trigger_kind`,可能取值为 `schedule` | 操作 | 说明 | |---|---| | 启用 / 停用 | 行内开关。停用后规则保留,但不再触发;停用不会删除已有运行历史。 | -| 立即执行 | 在规则行手动启动一次真实运行。该操作会先做运行前检查,然后为本次运行创建一个隐藏会话;同一规则手动执行最多每分钟一次。当规则的唯一触发方式是 **作战室创建触发** 时,列表和详情页都不提供这个操作——这类规则不会产生控制台运行,调用立即执行接口会直接报错。 | +| 立即执行 | 在规则行手动启动一次真实运行,会先做运行前检查。**Web** 执行位置的规则会新建一个隐藏会话并直接打开;**IM** 执行位置的规则在绑定的 IM 群聊里新开会话,控制台只提示 **手动执行已提交,请在执行历史中查看进度**,进度在执行历史里看。同一规则手动执行最多每分钟一次。当规则的唯一触发方式是 **作战室创建触发** 时,列表和详情页都不提供这个操作——这类规则不会产生控制台运行,调用立即执行接口会直接报错。 | 点击规则行任意位置会打开该规则的详情页,在详情页里可以编辑配置、删除规则,也能看到运行历史(见上文“运行历史”一节)。 @@ -307,13 +345,14 @@ API 返回的运行记录还包含 `trigger_kind`,可能取值为 `schedule` | 维度 | 规则 | |---|---| -| 归属 | **个人规则**归创建者所有;**团队规则**归该团队。**范围创建后不可修改**,需要换范围时,在规则详情页点击**克隆**,为副本选择新范围。创建团队规则时,操作者本人必须是该团队成员,账户 Owner 和管理员也不例外。团队规则在创建者离开团队后继续运行;个人规则在创建者不再是账户有效成员时会自动停用。 | +| 归属 | **个人规则**归创建者所有;**团队规则**归该团队。**范围创建后不可修改**,需要换范围时,在规则详情页点击**克隆**,为副本选择新范围(**IM** 执行位置的规则不提供克隆,见下文)。创建团队规则时,操作者本人必须是该团队成员,账户 Owner 和管理员也不例外。团队规则在创建者离开团队后继续运行;个人规则在创建者不再是账户有效成员时会自动停用。 | | 可见 / 列表 | 账户 Owner 与管理员可见全部规则;普通成员可见自己创建的规则,以及自己所属团队的规则。 | | 编辑 / 管理(团队规则) | 仅规则归属团队的**当前成员**可操作(启用 / 停用、编辑、删除、立即执行);创建者一旦离开该团队,就不再保留任何特权。账户 Owner 与管理员没有豁免,需要先加入该团队。 | | 编辑 / 管理(个人规则) | 仅创建者本人可管理和查看。账户 Owner 与管理员也无法查看或管理他人的个人规则。 | | HTTP POST 触发 | 通过触发地址发起一次真实运行时,鉴权只看该 trigger 的 Bearer Token;持有 Token 的外部系统可以触发,运行会按规则的个人或团队作用域创建隐藏会话。 | | On-call 故障触发 | 由已注册的故障订阅触发,不使用 HTTP POST Bearer Token;运行仍按规则的个人或团队作用域创建隐藏会话。 | | 作战室创建触发 | 由已注册的作战室创建订阅触发,不使用 HTTP POST Bearer Token;会话建在作战室的 IM 群里而不是控制台,运行仍按规则的个人或团队作用域归属。 | +| IM 执行位置 | 规则在 IM 会话里创建并绑定到该会话时确定(见上文“执行位置”):绑定与范围都由创建时的来源会话固定,控制台不可修改,也不能通过 `update` 迁移。这类规则在控制台不提供 **克隆**。 | <Note> 账户 Owner / 管理员能在列表中看到其他成员的个人规则(见上表“可见 / 列表”),但点击进入详情页会被拒绝——“编辑 / 管理”权限对个人规则同样不因 Owner / 管理员身份而豁免,与团队规则一致。 diff --git a/zh/ai-sre/im.mdx b/zh/ai-sre/im.mdx index cbd017157..f0043d7dc 100644 --- a/zh/ai-sre/im.mdx +++ b/zh/ai-sre/im.mdx @@ -11,7 +11,7 @@ sidebarTitle: IM 平台 排障往往就发生在您的 IM 群里——告警推过来、大家在群里讨论、拉个作战室。AI SRE 把 Agent 直接放进这条协作链路:**您不必切换到控制台,就能在 IM 里召唤它排查**,团队成员也能全程看到它的分析过程。 -AI SRE 的 IM 集成有两种触发方式: +AI SRE 的 IM 集成有三种触发方式: <CardGroup cols={2}> <Card title="@ 提及召唤" icon="at"> @@ -20,8 +20,13 @@ AI SRE 的 IM 集成有两种触发方式: <Card title="作战室自动诊断" icon="people-group"> 为故障开启 IM 作战室时,若账户里有一条启用中的 **作战室创建触发** 自动化规则、且这条故障的协作空间与严重程度命中该规则,AI SRE 会执行一轮初步诊断,并把结论作为一条分析消息发回作战室——无需任何人手动召唤。 </Card> + <Card title="群内自动化回帖" icon="clock"> + 在群里让 AI SRE 建一条普通自动化规则,它就把**当前这个群**作为运行位置:之后按周期、API 或 On-call 故障触发时,它在原群里**新开一个会话**跑这一轮,结论直接回帖到群里。每次运行都是全新的会话,不会带入群里的历史对话;集成开启话题回复时也新开一个话题,本次运行的第一条真实输出(进展或结论)就是这条话题的根消息,后续在话题内回复——在产出内容之前不会先发一条“已开始”之类的占位消息。绑定与范围在创建时固定、不能改到别的群:运行前会复核,群的团队范围或会话已变就整次**跳过**;同一个群里同一条规则已有运行在跑时,本次也不排队、直接跳过。 + </Card> </CardGroup> +前两种方式由人发起,第三种由您配好的自动化规则发起。规则怎么建、运行位置与作用域怎么固定,见[自动化 · 配置字段](/zh/ai-sre/automations#配置字段)。 + ## 支持的 IM 平台 AI SRE 的 IM 交互覆盖四个主流平台,每个平台都支持入站的 @ 提及(webhook)、历史消息读取与出站回复: diff --git a/zh/ai-sre/sessions.mdx b/zh/ai-sre/sessions.mdx index 609ecc160..89641b661 100644 --- a/zh/ai-sre/sessions.mdx +++ b/zh/ai-sre/sessions.mdx @@ -86,6 +86,7 @@ sidebarTitle: "控制台对话" - **支持的类型**:图片、PDF、文本 / Markdown / CSV / HTML、Office 文档、压缩包(`.zip` / `.rar`),以及任何 UTF-8 编码的文本文件(如 `.go`、`.py`、`.yaml`)。空文件不能上传。 - **大小与数量**:单个文件最大 **50MB**;每条消息最多 **9 个附件**,总大小不超过 **50MB**。 + - **图片**:为保证所有视觉模型都能读取,最长边大于 **8192** 像素、短边小于 **11** 像素、或长短边比超过 **200:1** 的图片会被自动缩放、补上白边后**重新编码**——存储格式可能随之改变(例如 GIF 会存成 PNG,动图只保留第一帧),文件名扩展名也一并调整;这类需要适配的图片若超过 **4000 万像素**(约 40 兆像素),会被直接拒绝并提示换一张更小的。图片损坏、或落在无法识别的格式变体上,会直接上传失败。文件夹里的图片按原样保存,不做这一处理。 - **文件夹**:可以从加号菜单选择 **上传文件夹**,或把文件夹拖进输入区。一个文件夹最多 **50 个文件**(`node_modules` 和以 `.` 开头的文件不计入),超过时整个文件夹会被拒绝;不符合要求的单个文件会被跳过并列出原因。一个文件夹算 1 个附件,目录结构会保留。 - **Agent 如何读取**:附件以文本形式提供给 Agent;超过 64KB 的文本只直接提供开头部分,Agent 会在需要时从沙箱中读取完整文件。压缩包和文件夹不会直接展开,Agent 在沙箱中按需解包和读取。 </Accordion> diff --git a/zh/changelog/changelog.mdx b/zh/changelog/changelog.mdx index 3721f4c7b..c753100c9 100644 --- a/zh/changelog/changelog.mdx +++ b/zh/changelog/changelog.mdx @@ -4,6 +4,34 @@ description: "本页面记录 Flashduty 产品的重要更新和功能发布" keywords: ["更新日志", "产品发布", "功能更新", "Flashduty", "版本记录"] --- +<Update label="2026-10-16" description="🤖 AI SRE 自动化可绑定到发起它的 IM 会话执行、RUM Issue 新增「解决方式」、钉钉与飞书集成保存后自动关联成员"> + +### AI SRE 自动化新增「执行位置」:规则可绑定到发起它的 IM 会话 + +自动化规则现在带一个 **执行位置**,创建时固定,取 **Web**(默认)或 **IM**。在 IM 群聊或私聊里让 Agent 建规则时,规则会绑定到**当前这个会话**(经 API 调用时显式传 `run_in: current-chat` 同理,但只能从那个实时 IM 会话里发起);控制台里的两个创建入口始终创建 **Web** 执行位置的规则,IM 执行位置的规则在控制台也不提供 **克隆**,要换执行位置只能另建一条规则。创建后执行位置不能修改,编辑时范围与执行位置都是只读的,IM 规则旁的提示是「范围和 IM 执行位置在创建时已固定,不能在控制台修改。」 + +IM 执行位置的规则不在控制台新建会话:它的每一次运行都在原来的群聊里 **新开一个会话**,集成开启话题时还会新开一个话题,同一次运行的重试复用这次的会话与话题,原群聊永远不变,结论也回帖到该群。如果执行时这个群聊的范围或会话已经变了(例如 `/scope`、`/new` 改过),本次运行会被 **跳过**(运行历史里状态为「已跳过」,原因 `chat_scope_mismatch`),规则保持启用,不会转移到别的群。 + +规则列表新增 **执行位置** 一列,取值 `IM` / `Web`;一条规则同时有作战室触发和其他触发时,该列显示两枚徽标「作战室触发→IM」「其他触发→Web」。详见[AI SRE 自动化](/zh/ai-sre/automations)。 + +### RUM Issue 新增「解决方式」:已解决 / 在下一版本中解决 + +Issue 状态下拉里的 **已解决** 与 **在下一版本中解决** 是同一个「已解决」状态按复现处理方式拆出的两个选项: + +- **已解决**(下拉里提示「之后再出现就重新打开」):该错误之后再出现、即使还是同一个版本,也会把 Issue 重开为待处理并标记 **问题复现**; +- **在下一版本中解决**(提示「只有新版本再出现才重新打开」):只有 Issue 之前没见过的新版本里再次出现才重开,同一版本里的重复出现不会重开。 + +两个选项在状态下拉里可随时互相切换。新建 Issue 默认 **在下一版本中解决**,存量 Issue 同样是这个默认值;未上报版本标签的错误在两种方式下再出现都会重开。详见[Issue 状态管理](/zh/rum/error-tracking/issue-status)。 + +### 钉钉与飞书集成保存后自动关联成员 + +保存或编辑钉钉、飞书集成后,系统会立即尝试关联一次成员,之后每小时再扫描一遍所有已启用的钉钉与飞书集成:用成员个人资料里的手机号(飞书同时用邮箱)换取 IM 账号 ID 写入绑定,成员不需要手动操作,也不需要先在 IM 里登录一次。只有想立刻重试时,才在集成详情页点 **一键关联**。 + +已经被别的成员占用的平台账号 ID 不会重复写;平台答复查不到对应账号的成员 7 天内不会被重复尝试;钉钉应用缺少 `qyapi_get_member_by_mobile` 权限、服务器 IP 不在白名单,或飞书应用缺少通讯录权限时,该集成的自动关联会暂停 24 小时,修好权限或白名单后重新保存集成即可恢复。自动关联只覆盖钉钉与飞书,企业微信仍用页面上的 **一键关联**;Slack 集成不提供成员关联。详见[钉钉](/zh/on-call/integration/instant-messaging/dingtalk)与[飞书](/zh/on-call/integration/instant-messaging/lark)。 + +</Update> + + <Update label="2026-10-14" description="🧭 调查入口一键直达观测、告警聚合改版、标签面板重做、定时通知支持每周与每月、仪表盘全局搜索"> ### 调查入口:从告警一键跳到仪表盘或查询工作台 diff --git a/zh/developer/cli.mdx b/zh/developer/cli.mdx index 1999dcb5e..1081dd4eb 100644 --- a/zh/developer/cli.mdx +++ b/zh/developer/cli.mdx @@ -18,7 +18,7 @@ Flashduty CLI(`flashduty`)是一款命令行工具,可在终端中完成 curl -sSL https://static.flashcat.cloud/flashduty-cli/install.sh | sh ``` -默认安装到 `/usr/local/bin`,可通过环境变量 `FLASHDUTY_INSTALL_DIR` 自定义。 +默认安装到 `PATH` 上已有的那份 `flashduty` 所在目录,便于就地升级替换掉旧副本;`PATH` 上没有 `flashduty` 时才安装到 `/usr/local/bin`。可通过环境变量 `FLASHDUTY_INSTALL_DIR` 自定义安装目录。 </Tab> <Tab title="Windows (PowerShell)"> @@ -39,13 +39,15 @@ irm https://static.flashcat.cloud/flashduty-cli/install.ps1 | iex | 环境变量 | 说明 | 默认值 | |----------|------|--------| | `FLASHDUTY_VERSION` | 安装指定版本,如 `v1.5.12` | 最新版本 | -| `FLASHDUTY_INSTALL_DIR` | 安装目录 | `/usr/local/bin`(Shell)、`~\.flashduty\bin`(PowerShell) | +| `FLASHDUTY_INSTALL_DIR` | 安装目录 | `PATH` 上已有 `flashduty` 所在目录,否则 `/usr/local/bin`(Shell);`~\.flashduty\bin`(PowerShell) | | `MIRROR_URL` | 覆盖安装脚本的 Release 资产下载镜像前缀,需以 `https://` 开头 | `https://static.flashcat.cloud/flashduty-cli` | | `FLASHDUTY_UPDATE_BASE_URL` | 覆盖 `flashduty update` 及自动更新检查的下载基础 URL | `https://static.flashcat.cloud/flashduty-cli` | | `INSTALLED_NAME` | 安装后的命令名,例如 `fduty` | `flashduty` | 以自定义命令名安装的副本,在帮助、错误信息与 Shell 自动补全中都使用该名称;`flashduty update` 按正在运行的可执行文件名与所在目录就地替换自身,而不是另装一份默认命名的副本。 +安装脚本结束时会再核对一次 `PATH`:若当前 Shell 实际运行的 `flashduty` 不是刚装的那份(被更靠前的旧副本抢占),会在输出里提示删掉旧副本或把新目录提前。若当前进程由 flashduty-runner 托管(`FLASHDUTY_MANAGED_BY_RUNNER=1`),脚本会拒绝执行并提示改为升级 runner——runner 自带一份与它一同验证过的 CLI,就地替换会让两者失配。 + ## 认证 ### 登录 @@ -630,12 +632,17 @@ flashduty monit datasource-delete --id <datasource-id> # 删除数据源(引 - `kafka`:`sasl_mechanism`(`none` 默认 / `plain` / `scram-sha-256` / `scram-sha-512`,后三者需用户名与密码)、`username` / `password`、`timeout_ms`(默认 5000)、TLS 字段(`tls_min_version` 默认 1.2,最高 1.3)。 - 密码与 `kafka.tls_key` 支持 `${env:NAME}` 引用(在 Edge 上解析);字面值不会出现在响应中,仅 `${env:...}` 引用会回显。**更新时省略这些字段以保留已存密钥,显式传空字符串表示清除**。 -#### 仪表盘与规则分组(dashboard-* / folder-list) +#### 仪表盘与规则分组(dashboard-* / folder-*) `monit dashboard-*` 命令族管理监控仪表盘(由 OpenAPI 生成命令提供)。仪表盘本身是一份 `dashboard.v1` 文档,创建与更新时通过 `--data` 传入 `definition`;`update` / `delete` / `move` / `restore` 都要求 `--expected-revision`——传入的版本不是当前版本时以 `DashboardRevisionConflict` 拒绝,需要重新读取后再提交。 ```bash flashduty monit folder-list # 列出全部监控规则分组,用于取 folder-id(返回顶层数组,用 jq '.[]') +flashduty monit folder-health # 查看分组健康摘要,含后代分组中的问题(分页信封,用 jq '.items[]') +flashduty monit folder-create --name <folder-name> [flags] # 创建分组(--name 必填且不能含 . / ,;--parent-id 父分组,0=根;--note 备注;--team-id 团队,0=账户级) +flashduty monit folder-update --id <folder-id> --name <folder-name> # 更新分组的名称、备注与团队归属(--id 与 --name 必填) +flashduty monit folder-move <dest-parent-id> --id <folder-id> # 移动分组及其后代(dest-parent-id 是位置参数,必须显式给出,0=移到根) +flashduty monit folder-delete --id <folder-id> # 删除分组(仅限空分组:内部还有子分组、规则或仪表盘时会被拒绝) flashduty monit dashboard-list <folder-id> # 列出某个分组下的仪表盘(分页信封,用 jq '.items[]') flashduty monit dashboard-search --query "支付" # 按标题与描述搜索仪表盘(至少一个词) flashduty monit dashboard-get <dashboard-id> # 读取仪表盘详情,含 definition 与当前 revision @@ -655,6 +662,8 @@ flashduty monit dashboard-runtime-variables-preview # 预览草稿 flashduty monit dashboard-runtime-queries-resolve <panel-id> [<id2>...] # 解析面板查询:变量替换后的表达式与绑定到的数据源 ``` +`monit folder-*` 是分组本身的增删改查:`folder-health` 返回 `{items:[...]}` 分页信封(每项只有 `folder_id` 与 `has_issue`,`has_issue` 表示该分组或其可见后代存在活跃告警或规则运行问题),`folder-list` 返回顶层数组,用法都是 `--json | jq`;`folder-create` 与 `folder-update` 返回更新后的单个分组对象;`folder-move` 与 `folder-delete` 不返回分组对象。分组名不能含 `.`、`/`、`,`;`folder-move` 的 `dest-parent-id` 即使移到根(`0`)也必须显式给出;`folder-delete` 只接受空分组——内部还有子分组、规则或仪表盘时会被拒绝,需要先自行清空。 + 面板运行时与变量解析的时间窗口、变量选择都以 JSON 对象放在 `--data` 里(时间用 `from_ms` / `to_ms` 的毫秒时间戳)。`dashboard-panel-preview` 与 `dashboard-runtime-variables-preview` 需要一个 `context`:`kind: existing` 配 `dashboard_id` 指向已存仪表盘,`kind: new` 配 `folder_id` 指向尚未落库的分组。 `dashboard-runtime-queries-resolve` 另有两个影响解析结果的参数:`--max-data-points`(整数,取值 2–5000;既作降采样目标,也决定解析出的表达式里内置时间变量渲染出的步长,省略或传 `null` 时取服务端默认值 100)与 `--preserve-builtin-variables`(布尔,默认关):开启后**内置时间变量**在解析结果里原样保留,交由自带执行窗口的调用方自行渲染,用户变量仍会被解析。兄弟命令 `dashboard-panel-run` 与 `dashboard-panel-preview` 早已带 `--max-data-points`,同为 2–5000 的降采样目标。 @@ -711,11 +720,12 @@ flashduty automation fire <trigger_id> # 经 HTTP POST 触发器触 | 参数 | 说明 | |------|------| | `--name` | 规则名称(必填) | -| `--team-id` | 归属团队 ID;`0` 表示个人范围(默认)。作用域创建后不可变更 | +| `--team-id` | 归属团队 ID;显式 `0` 表示个人范围,`>0` 表示该团队;省略时不发送该字段,由服务端在可用时继承当前 IM 会话的作用域,否则取常规默认值。`--run-in current-chat` 时传入的团队 ID 必须与该会话的作用域一致,不能把会话改到别的个人或团队范围。作用域创建后不可变更 | +| `--run-in` | 执行位置:`current-chat` 把规则绑定到当前的 IM 会话,`web` 在 Web 控制台运行;省略时由服务端决定——在 IM 会话里发起选 `current-chat`,否则选 `web`。在非 IM 会话里传 `current-chat` 会被服务端拒绝 | | `--schedule` | 节奏辅助:`hourly`、`daily`、`weekly` 或 `cron`;省略时默认 `daily` | | `--at` | `HH:MM` 本地时间(按规则时区);`hourly` 只取分钟(默认 0 分),`daily`/`weekly` 取小时与分钟(默认 09:00) | | `--weekday` | `weekly` 的星期:`sun`–`sat` 或 `0`–`7`(`0` 与 `7` 均表示周日,默认周一) | -| `--cron-expr` | 精确的 5 段 cron 表达式(按规则时区解释),优先级高于 `--schedule` 辅助参数 | +| `--cron-expr` | 支持的 5 段 cron 表达式(按规则时区解释),优先级高于 `--schedule` 辅助参数。分钟位必须是 `0`–`59` 的单一整数,因此最快只能每小时触发一次;分钟位的通配符、范围、列表与步长都不支持,`*/15 * * * *`、`0,30 * * * *` 这类写法会被拒绝 | | `--timezone` | IANA 时区名(如 `Asia/Shanghai`),`--at` 与 `--cron-expr` 按该时区解释;省略时由服务端依次取调用者的成员时区、账户时区,最后回退 `Asia/Shanghai`。服务端无法加载的时区会被拒绝 | | `--disabled` | 以停用状态创建(默认启用) | | `--schedule-enabled` | 是否启用周期触发器(默认 `true`) | @@ -723,7 +733,9 @@ flashduty automation fire <trigger_id> # 经 HTTP POST 触发器触 | `--prompt` / `--prompt-file` | 任务提示词,二选一必填;`--prompt-file` 从文件读取(`-` 表示 stdin) | | `--environment-kind` / `--environment-id` | 运行环境:`cloud` 或 `byoc`(`byoc` 需配合 `--environment-id`);留空表示自动 | -`update` 可改字段:`--name`、`--prompt`/`--prompt-file`、`--schedule`/`--at`/`--weekday`/`--cron-expr`/`--timezone`、`--enable`/`--disable`、`--enable-schedule`/`--disable-schedule`、`--enable-http-post-trigger`/`--disable-http-post-trigger`、`--rotate-http-post-token`、`--environment-kind`/`--environment-id`。个人 / 团队作用域创建后不可变更,`update` 不提供改作用域的参数。 +从 IM 会话里创建规则时,省略 `--run-in` 即让服务端把规则绑定到当前会话,同时继承该会话的作用域;不需要(也不应该)自己传 chat、平台、集成或会话 ID——服务端负责解析并鉴权当前会话。绑定当前会话之后,每次普通运行都会新建一个执行会话,IM 集成建线程时也会新建线程,并始终留在创建时捕获的那个会话与不可变作用域上,而不是复用旧会话或旧线程;同一次运行的重试复用该次运行的执行身份。若运行发生时绑定会话的作用域已与规则不符,本次运行会被跳过,规则不会被搬到别的会话里执行。作战室触发的规则行为不变。由于每次运行都是全新上下文,提示词必须自带所需的聊天上下文(服务对象、团队、投递目标等),不要写「上文/上述」这类指代。执行位置与作用域一样创建后不可变更。 + +`update` 可改字段:`--name`、`--prompt`/`--prompt-file`、`--schedule`/`--at`/`--weekday`/`--cron-expr`/`--timezone`、`--enable`/`--disable`、`--enable-schedule`/`--disable-schedule`、`--enable-http-post-trigger`/`--disable-http-post-trigger`、`--rotate-http-post-token`、`--environment-kind`/`--environment-id`。个人 / 团队作用域与执行位置(`--run-in`)创建后不可变更,`update` 不提供这两类参数。`update` 的 `--cron-expr` 与 `create` 同一约束:分钟位必须是 `0`–`59` 的单一整数,最快每小时一次,不支持分钟位的通配符、范围、列表与步长。 `runs` 支持 `--status`(`queued`/`running`/`retrying`/`succeeded`/`partial`/`failed`/`skipped`/`abandoned`)、`--trigger-kind`(服务端取值 `schedule`/`debug`/`manual`/`http_post`/`oncall_incident`/`war_room_created`,其中 `war_room_created` 表示由作战室创建触发的运行)、`--since`/`--until`、`--page`、`--limit`。`fire` 用触发器的 Token 鉴权(`--token`,或环境变量 `FLASHDUTY_AUTOMATION_TRIGGER_TOKEN`),`--text` 传本次运行的上下文,`--data` 传完整 JSON 请求体(内联 JSON 或 `-` 读 stdin)。 diff --git a/zh/developer/go-sdk.mdx b/zh/developer/go-sdk.mdx index 660a0539b..6ef1690b0 100644 --- a/zh/developer/go-sdk.mdx +++ b/zh/developer/go-sdk.mdx @@ -155,7 +155,7 @@ client, err := flashduty.NewClientWithAccessToken(accessToken, | `client.Account` | 账户 | | `client.AuditLogs` | 审计日志 | | `client.AlertRules` | 告警规则 | -| `client.RuleFolders` | 规则分组;`List` 列出调用方可读的全部监控规则分组(`POST /monit/folder/list`) | +| `client.RuleFolders` | 规则分组;`ReadList` 列出调用方可读的全部分组(`POST /monit/folder/list`)、`ReadHealth` 取分组健康摘要(`POST /monit/folder/health`,含可见后代分组的活跃告警与规则运行问题)、`WriteCreate` / `WriteUpdate` / `WriteMove` / `WriteDelete` 建改移删分组;旧的 `List` 保留为 `ReadList` 的兼容别名 | | `client.AlertEnrichment` | 告警字段加工 | | `client.DataSources` | 数据源 | | `client.Dashboards` | 仪表盘;面板试跑与执行、面板查询解析(`QueryReadResolve`)、变量解析,以及仪表盘的读写、移动/恢复与修订历史 | @@ -167,7 +167,7 @@ client, err := flashduty.NewClientWithAccessToken(accessToken, | `client.Analytics` | 分析 | | `client.A2aAgents` | A2A Agents | | `client.Artifacts` | AI SRE 产物 | -| `client.Automations` | AI SRE 自动化 | +| `client.Automations` | AI SRE 自动化(`RuleReadGet` / `RuleReadList` / `RuleWriteCreate` / `RuleWriteUpdate` / `RuleWriteDelete` / `RuleWriteRun` / `RunReadList` / `TemplateReadList`);创建规则时执行位置用 `AutomationRuleCreateRequest.RunIn`(`current-chat` / `web`,省略由服务端决定),作用域用同结构的 `TeamID`(`*int64`:显式 0 表示个人作用域,省略表示继承已认证 IM 会话作用域);`AutomationRuleUpdateRequest` 已无 `TeamID` | | `client.Knowledge` | AI SRE 知识(每份知识本身与其中的知识文件) | | `client.McpServers` | MCP Servers | | `client.Sessions` | AI SRE 会话 | @@ -200,10 +200,24 @@ client, err := flashduty.NewClientWithAccessToken(accessToken, `client.Artifacts`(AI SRE 产物)对应 `/safari/artifact/*` 的 11 个 API 操作:画廊读取侧 `ReadGet`(按 ID 获取单个已发布产物)、`ReadList`(分页列出调用方可见的产物,支持标题子串搜索、`scope`(`all` / `personal` / `team`)与 `team_ids` 过滤)、`ReadGetFileState`(批量探测会话展示文件(`pf_` 前缀)是否已有上线产物,单次至多 50 个 ID);文件侧 `ReadSign`(为展示文件签发短期有效的下载/预览 URL,有效期 5 分钟,`expires_in` 固定 300 秒)与 `ReadStream`(凭签名 token 下载或预览文件,成功响应体是文件而非 JSON 信封,原始字节放在 `Response.Raw`);写入侧 `WritePublish`(把会话产生的文件发布为画廊产物)、`WriteUpdate`(重命名或转移个人/团队作用域)、`WriteDelete`(从画廊移除,源文件仍保留在会话中);公开分享 `WriteShareEnable`(开启匿名公开分享并返回公开链接,任何人凭链接即可查看、无需登录)、`WriteShareRevoke`(关闭分享,链接立即失效)、`WriteShareSync`(把公开快照刷新为最新内容——当 `share_enabled` 为 true 且 `share_file_id` 与 `file_id` 不一致时表示快照已过期,调用它刷新)。相关导出类型包括 `PublishedArtifactItem`、`ArtifactShareState`、`SignedUrLs` 以及各 `Artifact*Request` / `Artifact*Response`。 +### AI SRE 自动化规则 + +`client.Automations` 对应 `/safari/automation/*`。规则的**执行目标**(作用域与执行位置)只在创建时确定: + +- `AutomationRuleCreateRequest.RunIn`(`run_in`)取 `current-chat`(把规则绑定到已认证的当前 IM 会话)或 `web`(在 Web 控制台执行)。省略该字段时由服务端决定:已认证的 IM 调用取 `current-chat`,其他调用取 `web`;在实时 IM 会话之外传 `current-chat` 会被服务端拒绝。 +- `AutomationRuleCreateRequest.TeamID`(`team_id`)是 `*int64`:显式传 0 表示个人作用域,大于 0 表示账户内的某个团队;省略时若存在已认证的 IM 会话则继承该会话的作用域,否则由服务端取常规默认值。`current-chat` 规则的作用域必须与该会话一致。 +- `AutomationRuleUpdateRequest` 已不再包含 `TeamID`(同样没有 `RunIn`):作用域与执行位置创建后不可变。旧代码若在更新请求里设置 `TeamID`,删掉该行即可,否则无法编译。 + ### 成员邮件通知 `client.Members.MemberNotify`(`POST /member/notify`,`memberNotify`)以调用方身份向账户成员发送邮件,仅可使用 AI SRE 会话凭据调用——其他凭据(包括普通 `app_key`)一律以 `AccessDenied` 拒绝(用 `IsAccessDenied` / `ErrorCodeOf` 判定)。请求字段:`subject`(必填,1–200 字符)与 `html`(必填,收件人看到的完整邮件正文,不超过 102,400 字节),`person_ids` 可选(至多 20 个且不可重复,省略或为空时只发送给调用方本人)。`html` 中的 `script`、`meta`、`link`、`base` 标签及 `on*` 事件属性会在发送前被静默清除;而 `style`、`svg`、`iframe`、`object`、`embed`、`form`、`input`、`button` 标签,没有 `https` `src` 的 `img`,或者链接不属于 `http`/`https`/`mailto` 的,会在入队前直接以 `InvalidParameter` 拒绝调用,并在错误信息中逐一列出触发的构造。投递是异步的,`accepted` 只表示邮件已入队;响应的 `recipients[]` 按收件人逐条返回(`person_id` 与 `status`),`status` 为 `accepted` 或 `skipped`,后者带 `reason`:`not_member`、`no_email`、`email_disabled`、`duplicate`、`rate_limited`(同一收件人每小时最多 20 封)、`send_failed`。响应只有 `recipients[]` 和可选的 `agent_instructions` 两个字段,不回显清洗后的邮件 HTML;当提交的 `html` 不符合默认邮件版式(缺少 `max-width:600px` 外层包裹表格)时会返回 `agent_instructions`,内容是写给调用的 AI SRE agent 的版式对齐指引——仅为建议,调用方有意选择的格式无需改动。 +### 规则分组 + +`client.RuleFolders` 覆盖 `/monit/folder/*` 的 6 个操作:`ReadList`(`POST /monit/folder/list`)与 `ReadHealth`(`POST /monit/folder/health`)不带请求体——前者返回扁平的 `[]FolderItem`,要用 `ParentID` / `ParentPath` 自行在客户端重建目录树(仪表盘与告警规则共用这棵树),后者返回 `FolderHealthOutput`,其中 `FolderHealthItem.HasIssue` 标记该分组或其可见后代是否有活跃告警或规则运行问题;写入侧 `WriteCreate`(`/monit/folder/create`)与 `WriteUpdate`(`/monit/folder/update`)返回 `FolderItem`,`WriteMove`(`/monit/folder/move`)与 `WriteDelete`(`/monit/folder/delete`)只返回 `*Response`。相关导出类型还有 `FolderCreateRequest`、`FolderUpdateRequest`、`FolderMoveRequest` 与 `FolderDeleteRequest`。 + +请求字段:`FolderCreateRequest.Name` 必填且不能包含句点、斜杠或逗号,`ParentID` 传 0 或省略即建在顶层;`FolderUpdateRequest` 必须同时传 `ID` 与 `Name`,它替换可编辑字段——省略 `Note` 会清空备注、省略 `TeamID` 会重置为 0(账户级);`FolderMoveRequest` 即使移回顶层也必须显式传 `DestParentID`(传 0),且不能移动到自身或自己的后代之下;`FolderDeleteRequest` 只带 `ID`,只能删除空分组,分组内还有子分组、告警规则或仪表盘时返回 HTTP 409 与 `FolderNotEmpty`。 + ### 诊断查询 `client.Diagnostics.QueryData` 通过 `POST /monit/query/data` 执行同步查询,返回稳定的 `query_result.v1` 结构化结果(`result.kind` 为 `frames` / `records` / `samples` 之一),要求 monit-edge v0.65.0 及以上版本。日志模式和指标趋势分析统一使用 `client.DataSources.ToolsInvoke`,工具名称为 `prometheus.metric_trends`、`loki.log_patterns` 或 `victorialogs.log_patterns`。 diff --git a/zh/on-call/channel/create-edit.mdx b/zh/on-call/channel/create-edit.mdx index 538cf1f29..60d75dbd8 100644 --- a/zh/on-call/channel/create-edit.mdx +++ b/zh/on-call/channel/create-edit.mdx @@ -104,7 +104,7 @@ keywords: ["协作空间", "创建管理", "业务隔离", "团队协作", "告 | :--- | :--- | | **聚合字段**(仅规则聚合) | 默认 `labels.check`,可多选 `labels.check`、`labels.service`、`labels.resource`、告警标题 | | **聚合时间** | **持续到故障关闭**(默认)或 **固定 60 分钟** | -| **高级配置 → 严格聚合**(仅规则聚合) | 开启后空值标签视为不同项;默认关闭 | +| **高级配置 → 严格聚合**(仅规则聚合) | 开启后任一比较字段为空即视为不同、不聚合;关闭(默认)时两边都为空的字段视为相同,但至少要有一个字段有值——所有比较字段都为空时不聚合 | | **高级配置 → 参与判断的信息**(仅智能聚合) | 参与相似度判断的字段;默认 `title`、`description`、`labels.service`、`labels.resource` | | **高级配置 → 风暴提醒** | 开启后合入告警数达到阈值(默认 100)时记录告警风暴事件并通知;默认关闭 | diff --git a/zh/on-call/channel/noise-reduction.mdx b/zh/on-call/channel/noise-reduction.mdx index e527739c7..912a113c7 100644 --- a/zh/on-call/channel/noise-reduction.mdx +++ b/zh/on-call/channel/noise-reduction.mdx @@ -136,7 +136,7 @@ src="https://download.flashcat.cloud/flashduty/video/alert-aggr.mp4" 不可用的方式在创建向导里显示为置灰不可选,悬停提示「当前订阅暂不支持该聚合方式」。方式对应 API 字段 `group_method` 的枚举值:`i`(智能聚合)、`p`(规则聚合)、`n`(不聚合),详见 [故障 Webhook](/zh/on-call/integration/webhooks/incident-webhook)。 -页面顶部的 **当前效果** 卡片会用一句话汇总当前生效的方式:不聚合时显示「不聚合 · 每条告警创建独立故障」,智能聚合时列出参与判断的字段,规则聚合时列出聚合字段(使用「不同告警使用不同规则」时改为按分支匹配),并附带聚合窗口、字段缺失时的处理规则和风暴提醒的开关状态。切换到不同方式时会先弹出确认框,确认后页面才切换到新方式的配置项,且仍需点击 **保存** 才真正生效。 +页面顶部的 **当前效果** 卡片会用一句话汇总当前生效的方式:不聚合时显示「不聚合 · 每条告警创建独立故障」,智能聚合时列出参与判断的字段,规则聚合时列出聚合字段(使用「不同告警使用不同规则」时改为按分支匹配),并附带聚合窗口、字段缺失时的处理规则和风暴提醒的开关状态。点击另一张方式卡片,页面下方直接显示该方式需要的配置项(不再弹出确认框),切换前已填写的草稿会保留;只有点击 **保存** 才真正生效。 ### 通用配置 @@ -146,7 +146,7 @@ src="https://download.flashcat.cloud/flashduty/video/alert-aggr.mp4" | **窗口计时起点** | 仅在聚合窗口开启时可配置。**故障触发**(默认):从故障创建时开始固定计时,到达窗口时长后停止聚合;**告警合入故障**:每次有新告警合入时重置计时,窗口从最后一次合入开始重新计算 | | **窗口时长** | 仅在聚合窗口开启时可配置。设置聚合窗口的持续时间,最小 1 分钟。规则聚合与智能聚合共享同一上限开关:默认最大 24 小时,开通后可扩展至 30 天(需联系 Flashduty 团队开启) | | **风暴预警** | 当合入告警数达到设定阈值时,系统在故障时间线中记录告警风暴事件并触发预警通知,提醒您加急处理。支持配置最多 5 个阈值,每个阈值范围为 2 - 10,000 | -| **严格聚合** | 开启时,空值标签视为不同项;关闭时,空值标签视为相同项(智能聚合不支持) | +| **严格聚合** | 开启时,任一参与比较的字段缺失即视为不同,不会聚合;关闭时,两边都为空的字段视为相同(缺失值按 `null` 比较),但至少要有一个参与比较的字段有值,全部为空时不聚合(智能聚合不支持) | <Tabs> <Tab title="智能聚合"> diff --git a/zh/on-call/comparison/vs-opsgenie.mdx b/zh/on-call/comparison/vs-opsgenie.mdx index 2b13e8951..f0c7a42a1 100644 --- a/zh/on-call/comparison/vs-opsgenie.mdx +++ b/zh/on-call/comparison/vs-opsgenie.mdx @@ -124,7 +124,7 @@ Response 解决「找到人之后怎么快速闭环」:一条时间线、一 | --- | --- | --- | | **AI 摘要与复盘** | 内置 AI 故障摘要、AI 一键生成复盘 | 无对等能力 | | **自治排障 Agent** | [AI SRE](/zh/ai-sre):接入真实环境的自治 Agent loop,云端沙箱 + 自托管 Runner 动态执行诊断命令,可通过 Skills、MCP、Subagent 与 A2A 无上限扩展;账户有已启用的 Monitors 数据源时,可经告警引擎**直连数据源查询**(内置 monit-query Skill,无需 Runner) | 无对等能力 | -| **IM 原生排障** | 飞书/钉钉/企微/Slack [群聊 @ 召唤、私聊排障](/zh/ai-sre/im),作战室创建后,由匹配的自动化规则自动发起初步诊断 | 无对等能力 | +| **IM 原生排障** | 飞书/钉钉/企微/Slack [群聊 @ 召唤、私聊排障](/zh/ai-sre/im),作战室创建后,由匹配的自动化规则自动发起初步诊断;自动化规则还可以在创建时绑定到某个 IM 会话,在该群里执行并把结论回帖到该群 | 无对等能力 | | **计费** | 按 credits 用量计费(1 credit = ¥1),开通免费,每个计费周期赠送体验额度 | — | ### 平台与集成 diff --git a/zh/on-call/comparison/vs-pagerduty.mdx b/zh/on-call/comparison/vs-pagerduty.mdx index 19b0ccccb..f4fe1691e 100644 --- a/zh/on-call/comparison/vs-pagerduty.mdx +++ b/zh/on-call/comparison/vs-pagerduty.mdx @@ -150,7 +150,7 @@ Response 解决「找到人之后怎么快速闭环」:一条时间线、一 | --- | --- | --- | | **产品形态** | 自治 SRE Agent:对话式排障 + 自主规划执行 + 知识沉淀 | AIOps 事件降噪/关联;Advance 生成式 AI 助手(摘要、问答、复盘草稿);四个预置 AI Agent 各管一段:SRE(诊断+预配置修复)、Scribe(会议记录)、Shift(排班)、Insights(数据问答) | | **排障与修复方式** | 云端沙箱 + 自托管 [Runner(BYOC)](/zh/ai-sre/environments),在您的环境中动态执行诊断命令、查询监控与日志,**可排查未预设过的问题**;账户有已启用的 Monitors 数据源时,可经告警引擎**直连数据源查询**(内置 monit-query Skill,无需 Runner) | SRE Agent 可自动分析日志/指标并匹配历史事件;修复动作依赖**预先配置**的 Automation Actions 脚本 | -| **IM 原生协同** | 飞书/钉钉/企业微信/Slack [群聊 @ 召唤、私聊排障](/zh/ai-sre/im),**作战室创建后,由匹配的自动化规则自动发起初步诊断** | Slack、Teams 为主,无国内 IM | +| **IM 原生协同** | 飞书/钉钉/企业微信/Slack [群聊 @ 召唤、私聊排障](/zh/ai-sre/im),**作战室创建后,由匹配的自动化规则自动发起初步诊断**;自动化规则还可以在创建时绑定到某个 IM 会话,在该群里执行并把结论回帖到该群 | Slack、Teams 为主,无国内 IM | | **代码仓库与 K8s** | [GitHub/GitLab App](/zh/ai-sre/apps) 沙箱内访问代码仓库、提交 PR/MR/Issue;Kubernetes App 按 namespace 接入集群 | 公开资料未见 | | **AI 自动化任务** | [自动化](/zh/ai-sre/automations)按 cron、HTTP API、故障事件或作战室创建触发,内置告警噪音分析、事故复盘、值班洞察等模板;On-call 故障触发支持**相似故障合并分析**(相似度 ≥0.9 并入进行中的分析会话) | 依赖 Event Orchestration 与 Runbook Automation 独立产品线 | | **可扩展性** | [Skills 市场](/zh/ai-sre/skills)、[MCP 外部工具](/zh/ai-sre/mcp)、[Subagent 与 A2A 委派](/zh/ai-sre/agents),**扩展面不设上限** | SRE Agent 限于启停官方预置连接器(Datadog、Splunk、CloudWatch 等约 23 个)与追加提示词式 Skill;不支持为自家 Agent 挂载任意 MCP 工具,无子 Agent 派生,跨厂商 Agent 协作尚在 early access | diff --git a/zh/on-call/configuration/filter-conditions.mdx b/zh/on-call/configuration/filter-conditions.mdx index 7e05cb0b7..13a6b1d7a 100644 --- a/zh/on-call/configuration/filter-conditions.mdx +++ b/zh/on-call/configuration/filter-conditions.mdx @@ -92,6 +92,12 @@ or - `*` 可匹配零个或多个任意字符 - `?` 可匹配单个任意字符 + 除 `*` 和 `?` 之外的字符都按**字面**匹配,不会被当作正则:`host[0-9]*` 里的 `[`、`]`,`(a|b)*` 里的 `(`、`)`、`|`,`host.*` 里的 `.` 都只是普通字符——`host[0-9]*` 只匹配以字面量 `host[0-9]` 开头的值。要用字符类或分组,请写成正则,例如 `/^host[0-9]+.*$/`。 + + <Note> + 按正则写过的存量通配值会被系统改写为等价的 `/^...$/` 正则保存(例如 `BDP.*` 变成 `/^BDP.[\s\S]*$/`),匹配结果与改写前一致;重新打开这类条件时,它会以 `/.../` 形式呈现,按**正则匹配**处理。 + </Note> + **示例**: - `labels.check`:`宕机*` — check 标签以"宕机"作为前缀,即匹配 diff --git a/zh/on-call/integration/alert-integration/routing-rules.mdx b/zh/on-call/integration/alert-integration/routing-rules.mdx index f08880bdf..57e87ce31 100644 --- a/zh/on-call/integration/alert-integration/routing-rules.mdx +++ b/zh/on-call/integration/alert-integration/routing-rules.mdx @@ -35,7 +35,7 @@ keywords: ["路由规则", "告警路由", "分发策略", "协作空间", "分 | 方式 | 示例 | 识别规则 | | :------- | :----------------------- | :-------------------------------- | | **精确匹配** | `cpu.idle<10%` | 不符合其他任何格式时,字符串完全相等才算匹配 | -| **通配匹配** | `host * down` | 值包含 `*` 或 `?` 且没有 `/` 前后缀时按通配处理 | +| **通配匹配** | `host * down` | 值包含 `*` 或 `?` 且没有 `/` 前后缀时按通配处理(其它字符按字面匹配,需要正则请用 `/.../`) | | **正则匹配** | `/api-server-\d+/` | 值以 `/` 为前后缀时按 RE2 正则处理 | | **CIDR 匹配** | `cidr:192.168.1.0/24` | 值以 `cidr:` 为前缀时按 IP 段匹配 | | **数值匹配** | `num:gt:0.95` | 值以 `num:` + 比较符(`gt`/`ge`/`lt`/`le`)为前缀时按数值大小匹配 | diff --git a/zh/on-call/integration/instant-messaging/dingtalk.mdx b/zh/on-call/integration/instant-messaging/dingtalk.mdx index 3bf7af2c9..e1a0ad38f 100644 --- a/zh/on-call/integration/instant-messaging/dingtalk.mdx +++ b/zh/on-call/integration/instant-messaging/dingtalk.mdx @@ -15,7 +15,7 @@ keywords: ["钉钉", "即时消息", "告警通知", "IM集成", "钉钉机器 ## 所需权限 -在钉钉开放平台 **权限管理** 页面按需申请以下权限。基础通知需要前两项;作战室再加第 3–5 项(第 5 项也用于一键关联用户);启用钉钉 AI 流式卡片模板时再加最后两项。 +在钉钉开放平台 **权限管理** 页面按需申请以下权限。基础通知需要前两项;作战室再加第 3–5 项(第 5 项也用于自动关联成员);启用钉钉 AI 流式卡片模板时再加最后两项。 | 官方权限名称 | 用途 | | :--- | :--- | @@ -23,7 +23,7 @@ keywords: ["钉钉", "即时消息", "告警通知", "IM集成", "钉钉机器 | `qyapi_robot_sendmsg` | 发送机器人消息,用于基础通知、会话机器人回复、普通版互动卡片、作战室消息,以及下载机器人接收到的文件 | | `qyapi_chat_read` | 读取群聊信息,用于作战室群状态确认和群成员处理 | | `qyapi_chat_base_read` | 读取群聊基础信息,用于作战室群查询 | -| `qyapi_get_member_by_mobile` | 根据手机号获取钉钉用户 ID,用于一键关联用户和邀请成员进入作战室 | +| `qyapi_get_member_by_mobile` | 根据手机号获取钉钉用户 ID,用于自动关联成员、一键关联用户和邀请成员进入作战室 | | `Card.Instance.Write` | 创建并投放 AI SRE 流式卡片;仅在启用钉钉 AI 流式卡片模板时需要 | | `Card.Streaming.Write` | 更新 AI SRE 流式卡片内容;仅在启用钉钉 AI 流式卡片模板时需要 | @@ -234,9 +234,21 @@ keywords: ["钉钉", "即时消息", "告警通知", "IM集成", "钉钉机器 列表展示所有团队成员及其关联状态,可按 **全部 / 已关联 / 未关联** 筛选,也可按名称或邮箱搜索。 +### 自动关联 + +成员无需手动操作,系统会自动完成关联: + +- 保存集成后立即尝试一次 +- 之后每小时再自动扫描一次,覆盖所有已启用的钉钉集成 + +自动关联使用成员在个人中心已验证的手机号换取钉钉账号 ID(钉钉不支持按邮箱查询),效果等同于成员用同一手机号在钉钉登录 Flashduty。有两处限制会让重试延后: + +- 钉钉答复过、但没能建立绑定的成员——例如手机号在钉钉侧查不到,或该钉钉账号已经绑定到其他成员——7 天内不再重复尝试;成员的手机号发生变化时会重新尝试 +- 钉钉应用缺少 `qyapi_get_member_by_mobile` 权限(错误码 60011),或服务器 IP 不在应用白名单内(错误码 60020)时,该集成的自动关联暂停 24 小时;补齐权限或白名单后重新保存集成即可恢复 + ### 一键关联 -当存在未关联的成员时,可以点击 **一键关联** 按钮。系统将尝试通过手机号换取钉钉开放平台的账号 ID 并自动关联,效果等同于成员使用相同手机号在钉钉平台登录 Flashduty。 +当存在未关联的成员时,可以点击 **一键关联** 按钮。系统将尝试通过手机号换取钉钉开放平台的账号 ID 并自动关联,效果等同于成员使用相同手机号在钉钉平台登录 Flashduty。该按钮会忽略上面的 7 天重试窗口,立即重新查询一次;如果提示 **没有关联到新成员**,说明本次查询没有产生新的绑定(例如手机号在钉钉侧查不到,或对应钉钉账号已经绑定到其他成员)。 <Tip> 成员完成关联后,系统才能向其推送钉钉消息通知。如果关联失败,请确认成员的手机号是否与钉钉账号一致。 @@ -247,6 +259,8 @@ keywords: ["钉钉", "即时消息", "告警通知", "IM集成", "钉钉机器 <AccordionGroup> <Accordion title="消息无法投递到个人,操作记录提示「未关联应用」?"> 前往 钉钉 → 工作台 → 搜索应用名称 → **打开应用**,完成一次登录以关联钉钉与 Flashduty 账号,系统才能获取用户身份并推送消息。 + +如果成员在个人中心已经验证过手机号,系统也可能已经自动完成关联,无需成员登录;可在集成详情页的 **关联用户** 页签确认当前关联状态。 </Accordion> <Accordion title="消息卡片按钮点击无效或报错?"> diff --git a/zh/on-call/integration/instant-messaging/lark.mdx b/zh/on-call/integration/instant-messaging/lark.mdx index 42fe1da34..f6df84af3 100644 --- a/zh/on-call/integration/instant-messaging/lark.mdx +++ b/zh/on-call/integration/instant-messaging/lark.mdx @@ -155,9 +155,17 @@ keywords: ["飞书", "Lark", "即时消息", "告警通知", "IM集成"] 列表展示所有团队成员及其关联状态,可按 **全部 / 已关联 / 未关联** 筛选,也可按名称或邮箱搜索。 +### 自动关联 + +成员无需手动操作,系统会自动完成关联:保存集成后立即尝试一次,之后每小时再自动扫描一次,覆盖所有已启用的飞书集成。 + +自动关联使用成员在个人中心已验证的手机号或邮箱,分批(每批 50 个)调用飞书接口换取账号 ID。飞书对查不到的账号和不在应用 **可见范围** 内的用户都返回空 `user_id`,两者都按「未找到」处理。如果飞书应用缺少通讯录权限(错误码 99991672 / 99991679)或凭证被飞书拒绝,该集成的自动关联会暂停 24 小时,补齐权限并重新保存集成后即可恢复。 + +查询过、但没有查到对应飞书账号的成员,7 天内不会重复尝试;成员的联系方式发生变化时会重新尝试。 + ### 一键关联 -当存在未关联的成员时,可以点击 **一键关联** 按钮。系统将尝试通过手机号或邮箱换取飞书开放平台的账号 ID 并自动关联,效果等同于成员使用相同信息在飞书平台登录 Flashduty。 +当存在未关联的成员时,可以点击 **一键关联** 按钮。系统将尝试通过手机号或邮箱换取飞书开放平台的账号 ID 并自动关联,效果等同于成员使用相同信息在飞书平台登录 Flashduty。该按钮会忽略上面的 7 天重试窗口,立即重新查询一次;如果提示 **没有关联到新成员**,说明本次查询没有产生新的绑定。 <Tip> 成员完成关联后,系统才能向其推送飞书消息通知。如果关联失败,请确认成员的手机号或邮箱是否与飞书账号一致。 @@ -168,6 +176,8 @@ keywords: ["飞书", "Lark", "即时消息", "告警通知", "IM集成"] <AccordionGroup> <Accordion title="消息无法投递到个人,操作记录提示「未关联应用」?"> 前往 飞书 → 工作台 → 搜索应用名称 → **打开应用**,完成一次登录以关联飞书与 Flashduty 账号,系统才能获取用户身份进行消息推送。 + +如果成员在个人中心已经验证过手机号或邮箱,系统也可能已经自动完成关联,无需成员登录;可在集成详情页的 **关联用户** 页签确认当前关联状态。 </Accordion> <Accordion title="消息卡片按钮点击无效或报错?"> diff --git a/zh/on-call/integration/instant-messaging/slack.mdx b/zh/on-call/integration/instant-messaging/slack.mdx index daadc4e2a..99a7e0577 100644 --- a/zh/on-call/integration/instant-messaging/slack.mdx +++ b/zh/on-call/integration/instant-messaging/slack.mdx @@ -41,21 +41,13 @@ keywords: ["Slack", "即时消息", "告警通知", "IM集成", "协作工具"] 作战室创建后的自动 AI 故障分析不在本页配置:如需在作战室创建时自动发起一次,请在 [自动化](/zh/ai-sre/automations) 中新建一条规则,触发方式选择 **作战室创建触发**,并选好要监听的协作空间与严重程度。 -## 关联用户 +## 成员关联 -在集成详情页的 **关联用户** 页签中,您可以查看团队成员与 Slack 账号的关联状态,并快速完成批量关联。 +Slack 集成不提供成员关联页面:集成详情页只有配置页,没有 **关联用户** 页签,也没有 **一键关联** 按钮;Flashduty 不会用成员的手机号或邮箱去换取 Slack 账号 ID 做批量绑定。 -### 查看关联状态 +Slack 集成按**邮箱**识别成员:成员在 Slack 中操作告警卡片时,Flashduty 读取该 Slack 账号的邮箱,并与当前账户下的成员邮箱比对,匹配到即视为该成员。所以这里不需要逐个成员绑定,但要保证成员的 Slack 邮箱与 Flashduty 成员邮箱一致;邮箱不一致时,系统会在 Slack 中回复一条提示,说明未能匹配到成员。 -列表展示所有团队成员及其关联状态,可按 **全部 / 已关联 / 未关联** 筛选,也可按名称或邮箱搜索。 - -### 一键关联 - -当存在未关联的成员时,可以点击 **一键关联** 按钮。系统将尝试通过手机号或邮箱换取 Slack 开放平台的账号 ID 并自动关联,效果等同于成员使用相同信息在 Slack 平台登录 Flashduty。 - -<Tip> -成员完成关联后,系统才能向其推送 Slack 消息通知。如果关联失败,请确认成员的邮箱是否与 Slack 账号一致。 -</Tip> +Slack 的接入以**工作区**为单位:完成 [安装应用](#install-app) 的 OAuth 授权后,该工作区内的频道通知、群聊中 @ AI SRE 和作战室即可使用。 <span id="aisre-permissions"></span> <span id="war-room-scope"></span> diff --git a/zh/rum/error-tracking/error-viewing.mdx b/zh/rum/error-tracking/error-viewing.mdx index 2354bdbb4..edc8e219f 100644 --- a/zh/rum/error-tracking/error-viewing.mdx +++ b/zh/rum/error-tracking/error-viewing.mdx @@ -40,7 +40,7 @@ Issue 列表支持按**优先级**排序,筛选条件默认包含「优先级 ## Issue 状态 -Issue 有 4 种状态,流转方式如下: +Issue 有 4 种状态;其中**已解决**按复现后的处理方式分为「已解决」与「在下一版本中解决」两个可选方式,流转方式如下: <Frame> <img src="https://docs-cdn.flashcat.cloud/imges/png/d81cfab46793c24b044c8d87ef30402b.png" alt="Issue 状态流转" /> @@ -50,7 +50,7 @@ Issue 有 4 种状态,流转方式如下: |------|------| | **待处理** | 新发现的问题,需要关注 | | **处理中** | 已确认并正在修复的问题 | -| **已解决** | 问题已修复 | +| **已解决** | 问题已修复;按复现后的处理方式分为「已解决」(之后再出现,同一版本也算,即重开为待处理并标记复现)与「在下一版本中解决」(仅新版本再次出现才重开),可在状态下拉中切换 | | **已忽略** | 无需处理的问题 | <Tip> @@ -177,7 +177,7 @@ AI 会输出错误分类和简要的原因解释(不超过 100 字)。推断 </Frame> <Warning> -如果一个错误被标记为已解决,但在后续(version 不同)又产生了相同的错误,则该 Issue 的状态会从结束态重新打开,并标记为「问题复现」。 +如果一个错误被标记为已解决,但其后再次出现,则该 Issue 的状态会从结束态重新打开,并标记为「问题复现」。是否重开取决于该 Issue 的解决方式:选择**已解决**(`resolve_mode=any`)时任何再次出现都会重开(同一版本也算);选择**在下一版本中解决**(`resolve_mode=version`,默认)时只有新版本再次出现才重开。详见 [Issue 状态](./issue-status) 的「解决方式」一节。 </Warning> ## Issue 详情 diff --git a/zh/rum/error-tracking/issue-status.mdx b/zh/rum/error-tracking/issue-status.mdx index eca50faf9..4081eca46 100644 --- a/zh/rum/error-tracking/issue-status.mdx +++ b/zh/rum/error-tracking/issue-status.mdx @@ -13,7 +13,7 @@ keywords: ["RUM", "异常追踪", "用户监控", "前端监控"] | **待处理** | `for_review` | 需要关注的新问题或回归问题 | | **处理中** | `reviewed` | 已分类且需要修复的问题,可立即或稍后处理 | | **已忽略** | `ignored` | 不需要进一步调查或处理的问题 | -| **已解决** | `resolved` | 已修复且不再发生的问题 | +| **已解决** | `resolved` | 已修复且不再发生的问题;按复现后的处理方式分为**已解决**与**在下一版本中解决**两个可选方式(见 [解决方式](#解决方式)) | <Info> 所有新发现的 Issue 初始状态为**待处理(for_review)**。Flashduty 会根据特定条件自动更新状态,您也可以手动调整。 @@ -38,18 +38,21 @@ Flashduty 会自动将不活跃或已解决的 Issue 标记为**已解决(reso ## 自动重新打开 Issue -Flashduty 具备 Issue 检测功能,当已解决的 Issue 再次出现时,系统会自动重新打开并标记为<strong>待处理(for_review)</strong>状态,同时在活动时间线中记录该事件为「问题复现」状态。 +Flashduty 具备 Issue 检测功能,当已解决的 Issue 再次出现、且满足该 Issue <strong>解决方式</strong>设定的条件时,系统会自动重新打开并标记为<strong>待处理(for_review)</strong>状态,同时在活动时间线中记录该事件为「问题复现」状态。 ### 什么是问题复现? -复现指的是先前已修复的问题在代码更新后意外重新出现。Flashduty 的回归检测可自动识别这些情况,将相关 Issue 重新打开,而不是创建重复的 Issue,从而保留问题的完整上下文和历史记录。 +复现指的是先前已修复的问题再次出现,常见场景是代码更新后意外回归。Flashduty 的回归检测可自动识别这些情况,将相关 Issue 重新打开,而不是创建重复的 Issue,从而保留问题的完整上下文和历史记录。 ### 复现检测机制 +当一个错误被聚合进<strong>已解决(resolved)</strong>的 Issue 时,是否判定为复现取决于该 Issue 的<strong>解决方式</strong>(见下文 [解决方式](#解决方式)): + <Warning> -当满足以下任一条件时,复现检测将被触发: -- 如果<strong>已解决(resolved)</strong>的错误在代码的更新版本中重新出现 -- 如果在未设置版本标签的情况下,<strong>已解决(resolved)</strong>状态的错误再次出现 +- 解决方式为<strong>在下一版本中解决(`version`,默认)</strong>:只有该 Issue 之前未出现过的新版本中再次出现才触发检测 +- 解决方式为<strong>已解决(`any`)</strong>:任何再次出现都触发检测,同一版本内的重复出现同样算复现 +- 错误未携带 `version` 标签时,两种解决方式都会触发检测 +- 错误的发生时间早于该 Issue 的解决时间时不会触发(重复上报,或 SDK 离线缓存后补传的旧错误) </Warning> 一旦检测到问题复现,Flashduty 会: @@ -65,7 +68,7 @@ Flashduty 具备 Issue 检测功能,当已解决的 Issue 再次出现时, ### 关联版本配置 -复现检测会考虑错误发生的服务版本信息,只有在 Issue 标记为<strong>已解决(resolved)</strong>后的新版本中才会触发检测。 +复现检测会考虑错误发生的服务版本信息:解决方式为<strong>在下一版本中解决(`version`,默认)</strong>时,只有在 Issue 标记为<strong>已解决(resolved)</strong>之后的、之前未出现过的新版本中才会触发检测;解决方式为<strong>已解决(`any`)</strong>时不比较版本,同一版本中再次出现也会触发。 ```javascript window.FLASHCAT_RUM.init({ @@ -79,6 +82,21 @@ window.FLASHCAT_RUM.init({ 如果不设置版本标签,当已解决的 Issue 再次发生错误时,系统仍会将其标记为「问题复现」,但无法确定是否在新版本中发生。 </Note> +## 解决方式 + +在状态下拉里,**已解决**按「该错误再次出现时如何处理」拆成两个选项。两者写入的状态都是 `resolved`,区别在 Issue 的解决方式字段 `resolve_mode`: + +| 下拉选项 | 解决方式标识 | 复现时的行为 | +|------|------|------| +| **已解决** | `any` | 之后再出现就重新打开:同一版本内的再次出现同样会重开 | +| **在下一版本中解决** | `version` | 只有新版本再出现才重新打开:仅该 Issue 之前未出现过的新版本中再次出现才重开 | + +- 两个选项可随时在状态下拉里互相切换;只切换解决方式不改动 Issue 的统计数据,也不改变告警状态。 +- 新建 Issue 默认是**在下一版本中解决(`version`)**;在引入解决方式之前就已存在的 Issue 同样按 `version` 处理,行为与之前保持一致。 +- 系统自动解决 Issue 时也写入 `version`。 +- 错误未携带 `version` 标签时,两种解决方式都会重开——没有版本信息就无从区分修复前后的代码。 +- 重开时 Issue 会被置为**待处理(for_review)**并标记「问题复现」,同时记录复现发生的时间与版本。列表中状态单元格受宽度限制,两种解决方式都显示为**已解决**;详情面板会在**已解决**旁额外标出「在下一版本中解决」。 + ## 手动更新状态 您可以在任何显示 Issue 的地方手动更新其状态,包括 Issue 列表或详情面板。 @@ -87,7 +105,7 @@ window.FLASHCAT_RUM.init({ <img src="https://docs-cdn.flashcat.cloud/images/png/a57c54a6a28915dec4480a9db9411e30.png" alt="手动更新状态" style={{maxWidth: "600px", margin: "0 auto", display: "block"}} /> </Frame> -只需点击当前状态,然后从下拉菜单中选择新状态即可。 +只需点击当前状态,然后从下拉菜单中选择新状态即可。下拉中共 5 个选项:**待处理**、**处理中**、**已解决**、**在下一版本中解决**、**已忽略**;两个「已解决」选项下方会显示各自的重开说明,区别见 [解决方式](#解决方式)。 ## 最佳实践