feat(dynatrace): add the Dynatrace integration - #6393
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
PR SummaryMedium Risk Overview Auth is environment URL + access token ( The block wires all operations through conditional sub-blocks, shared timeframe/pagination fields, and templates/skills for triage, deploy correlation, SLO health, entity investigation, and vulnerability audits. Docs, integration catalog, icon mappings, and DynatraceIcon are registered alongside dynatrace-errors extraction for Notable API mapping choices: ingest event exposes Reviewed by Cursor Bugbot for commit 428de53. Configure here. |
Greptile SummaryThe PR adds a complete Dynatrace integration backed by 22 Environment API v2 tools.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| apps/sim/blocks/blocks/dynatrace.ts | Defines the Dynatrace block UI, operation selection, typed shared parameters, tool mappings, and declared outputs. |
| apps/sim/tools/dynatrace/utils.ts | Centralizes environment URL normalization, query construction, authentication headers, and response-body handling. |
| apps/sim/tools/dynatrace/ingest_metrics.ts | Implements metric line-protocol ingestion and maps accepted and rejected line details from successful responses. |
| apps/sim/tools/dynatrace/ingest_logs.ts | Implements log ingestion and distinguishes full 204 acceptance from partial-success responses. |
| apps/sim/tools/dynatrace/dynatrace.test.ts | Covers URL variants, cursor behavior, identifier encoding, ingestion responses, errors, and list response mappings. |
| apps/sim/tools/registry.ts | Registers all new Dynatrace tools for runtime dispatch. |
Sequence Diagram
sequenceDiagram
participant User as Workflow user
participant Block as Dynatrace block
participant Executor as Generic executor
participant Tool as Selected Dynatrace tool
participant API as Dynatrace Environment API v2
User->>Block: Configure operation, URL, token, and parameters
Block->>Executor: Select tool and map parameters
Executor->>Tool: Execute registered tool
Tool->>API: Send authenticated HTTP request
API-->>Tool: Return API response
Tool-->>Executor: Transform declared output
Executor-->>User: Expose workflow result
Reviews (3): Last reviewed commit: "fix(dynatrace): stop three silent failur..." | Re-trigger Greptile
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 4f56e18. Configure here.
Adds a Dynatrace block backed by 22 Environment API v2 tools, covering the surfaces an observability workflow actually reaches for: - Problems: list, get, close, list comments, add comment - Metrics: query data points, list and get descriptors, ingest line protocol - Entities: list, get, list entity types - Events: list, get, ingest - Logs: search, ingest - SLOs: list, get - Application Security: list and get security problems - Audit log: read Every request path, query parameter, and response mapping is taken from the published Dynatrace API reference — no inferred fields. Auth is an access token sent as `Authorization: Api-Token ...` against a user-supplied environment URL, so SaaS, Managed, and environment ActiveGate all work. Two details worth knowing: `ingest_event` exposes Dynatrace's event timeout as `eventTimeout`, not `timeout`. The tool transport reserves `params.timeout` for the HTTP request deadline, so the obvious name would have silently retargeted the wrong knob. `get_metric` encodes its path segment with `encodeDynatracePathSegment` rather than `encodeURIComponent`, which leaves the `:` separators in metric keys and transformation operators intact, matching the docs' own examples.
Three real defects and one usability gap, all found by auditing the tools
against the Dynatrace API reference a second time.
`ingest_logs` double-encoded its payload. `logs` is a `json` param, and a
`json` param arrives as a *string* whenever it comes from a long-input field
or an LLM tool call — only a block-to-block reference hands over a parsed
value. `JSON.stringify` on that string produced `"[{...}]"`, so Dynatrace
received a quoted string where it expected an array. The block hid this in
the UI path by pre-parsing, but the parse lived in `tools.config.params` and
*threw* on malformed input, and it never covered the direct tool-call path at
all. Both tools now normalize through the shared `parseJsonParam`, so the
tool is correct regardless of who calls it, and the block just forwards the
raw value. `ingest_event.properties` had the identical bug.
Path identifiers were not trimmed. A problem or entity ID pasted with a
trailing newline became `%0A` in the URL and 404'd with nothing to suggest
whitespace was the cause.
Errors dropped the part that matters. Dynatrace's ErrorEnvelope carries
`constraintViolations[]`, which names the offending selector or parameter;
the generic `nested-error-object` extractor returns only `error.message`
("Constraints violated."), and which extractor won was left to fallback
order. Adds a `dynatrace-errors` extractor that folds the violations into the
message and pins it on all 22 tools. It sits after `nested-error-object` in
the chain, which already matches this shape, so no other service's error
handling changes.
Adds 21 tests covering URL construction for SaaS/Managed/ActiveGate, cursor
pagination dropping sibling filters, identifier trimming, metric-key colon
preservation, both JSON-param paths, the `eventTimeout` -> `timeout` mapping,
EntityStub flattening, the audit log's dotted `dt.settings.*` keys, and the
204/200 split on log ingestion.
Adds a MANUAL-CONTENT:intro block to the generated integration page covering what the block reaches, how to get an environment URL and a scoped token for SaaS vs Managed, how selectors work, and how cursor pagination behaves. Verified it survives `generate-docs.ts` byte-identically. Also closes the last silent-failure gap the validation pass left open. A wrong top-level response key does not throw — it maps to an empty array and reads as "no results", which is indistinguishable from a genuinely empty environment. Dynatrace is unusually easy to get wrong here: the SLO list returns `slo` (singular) and the metric query returns `result` (singular). Adds a table-driven test asserting the documented key for all ten list endpoints plus the scalar keys of the ingest and single-entity responses. Confirmed it bites by flipping `data.slo` to `data.slos` and watching only that row fail.
Review follow-up. `Record<string, any>` in the block's params builder dropped compile-time checking from every operation's shared params; `unknown` is enough here since the values flow straight into the tool param maps. Matches .claude/rules/sim-typescript.md, which sibling blocks (Datadog, Grafana) still violate.
All three turn a failed call into something that looks like a successful
empty one, which is the worst shape for an observability integration — you
cannot tell "nothing is wrong" from "the call did not work".
`readJsonBody` swallowed any unparseable body and returned `{}`. A gateway
HTML page, a captive-portal interstitial, or a truncated payload therefore
mapped every field to null and read as "no problems found". Only genuinely
empty bodies are tolerated now (201 from add-comment, 204 from log ingest);
anything else that will not parse raises with a truncated preview.
`ingest_logs` sent `[]` when the payload was missing or empty. Dynatrace
answers 204 to that, so the tool reported `accepted: true` for a call that
shipped no logs. It now fails loudly instead.
`encodeDynatracePathSegment` percent-encoded the whole metric key and then
regex-unescaped `%3A` back to `:`. Same output, but it undoes the encoder's
work and hides the intent. Colons are structural in a metric key, so it now
splits on them, encodes each part, and rejoins — which says that directly.
Each fix has a test, and each test was confirmed to fail in isolation with
only its own fix reverted.
4f56e18 to
428de53
Compare
|
@cursor review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 428de53. Configure here.
Summary
Authorization: Api-Token ...against a user-supplied environment URL, so SaaS, Managed, and environment ActiveGate all workdynatrace-errorsextractor so failures surfaceconstraintViolations, which names the offending selector instead of the bare "Constraints violated."Two details worth knowing:
ingest_eventexposes Dynatrace's event timeout aseventTimeout, nottimeout— the tool transport reservesparams.timeoutfor the HTTP request deadline, so the obvious name would have silently retargeted the wrong knob.get_metricencodes its path segment leaving:intact, so metric keys and transformation operators (builtin:host.cpu.usage:avg) match the docs' own examples.No triggers: Dynatrace problem notifications go out through a generic custom-webhook integration whose payload is a user-authored template, so there is no fixed schema to parse.
Type of Change
Testing
23 unit tests covering URL construction for SaaS/Managed/ActiveGate, cursor pagination dropping sibling filters, identifier trimming, metric-key colon preservation, both JSON-param paths, the
eventTimeout→timeoutmapping, error extraction, response-shape mapping, and the documented top-level response key of all ten list endpoints. Each fix was verified to go red when reverted.Full audit suite passes (
tool-metadata:check,integration-catalog:check,check:api-validation:strict, both tool-boundary checks,check:bare-icons). Type-check clean. Not yet exercised against a live Dynatrace tenant — mappings are verified against documentation, not live payloads.Checklist