Repository navigation
fix(warehouse): read the current semconv key wherever we only read the legacy one #1190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
2fd8e01
fix(warehouse): read the current semconv key wherever we only read th…
Makisuo b5b57dd
fix(web): drill dependency edges named by their system or by url.auth…
Makisuo 1cd2526
fix(warehouse): group HTTP method with the same precedence the filter…
Makisuo 8ac060b
fix(web): make dependency drilldowns open the spans behind the edge
Makisuo 717ed91
fix(ui): tone rpc.response.status_code by gRPC semantics
Makisuo 0e1ad0e
fix(ui): tone rpc.response.status_code only for gRPC rows
Makisuo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| import { describe, expect, it } from "vitest" | ||
| import { parseWhereClause } from "@/lib/traces/advanced-filter-sync" | ||
| import { dependencyDrillWhereClause, type DependencyDrillKind } from "./dependency-drill" | ||
|
|
||
| const filtersOf = (kind: DependencyDrillKind, target: string, system: string) => | ||
| parseWhereClause(dependencyDrillWhereClause(kind, target, system)) | ||
|
|
||
| describe("dependencyDrillWhereClause", () => { | ||
| it("drills a messaging destination on the current key", () => { | ||
| expect(filtersOf("messaging", "orders", "kafka").filters.attributeFilters).toEqual([ | ||
| { key: "messaging.destination.name", value: "orders" }, | ||
| ]) | ||
| }) | ||
|
|
||
| it("drills a messaging edge named by its system to spans without a destination", () => { | ||
| expect(filtersOf("messaging", "kafka", "kafka").filters.attributeFilters).toEqual([ | ||
| { key: "messaging.system", value: "kafka" }, | ||
| { key: "messaging.destination.name", value: "", matchMode: "exists", negated: true }, | ||
| ]) | ||
| }) | ||
|
|
||
| // The rollup merges `destination = kafka` spans into the same edge as the | ||
| // fallback spans; without OR in the where-clause only the fallback half is | ||
| // reachable. Pinned so a parser that gains OR support flips this on purpose. | ||
| it("drills only the fallback spans when a destination shares its system's name", () => { | ||
| expect(filtersOf("messaging", "kafka", "kafka").filters.attributeFilters).toContainEqual({ | ||
| key: "messaging.destination.name", | ||
| value: "", | ||
| matchMode: "exists", | ||
| negated: true, | ||
| }) | ||
| }) | ||
|
|
||
| it("drills an rpc service, or the legacy system key when the edge is named by it", () => { | ||
| expect(filtersOf("rpc", "checkout.Cart", "grpc").filters.attributeFilters).toEqual([ | ||
| { key: "rpc.service", value: "checkout.Cart" }, | ||
| ]) | ||
| expect(filtersOf("rpc", "grpc", "grpc").filters.attributeFilters).toEqual([ | ||
| { key: "rpc.system", value: "grpc" }, | ||
| { key: "rpc.service", value: "", matchMode: "exists", negated: true }, | ||
| ]) | ||
| }) | ||
|
|
||
| it("drills http, database and service edges on their target key", () => { | ||
| expect(filtersOf("http", "api.stripe.test", "").filters.attributeFilters).toEqual([ | ||
| { key: "server.address", value: "api.stripe.test" }, | ||
| ]) | ||
| expect(filtersOf("database", "postgresql", "").filters.attributeFilters).toEqual([ | ||
| { key: "db.system.name", value: "postgresql" }, | ||
| ]) | ||
| expect(filtersOf("service", "billing", "").filters.attributeFilters).toEqual([ | ||
| { key: "server.address", value: "billing", matchMode: "contains" }, | ||
| ]) | ||
| }) | ||
|
|
||
| // A client span is almost never a trace root, and the traces page filters | ||
| // roots unless told otherwise. A dropped clause or a `SpanKind` pseudo-attribute | ||
| // used to leave every drill on an empty or unfiltered list. | ||
| it("opens the span-level list with no dropped clauses or pseudo-attributes", () => { | ||
| for (const [kind, target, system] of [ | ||
| ["service", "billing", ""], | ||
| ["database", "postgresql", ""], | ||
| ["messaging", "orders", "kafka"], | ||
| ["messaging", "kafka", "kafka"], | ||
| ["rpc", "grpc", "grpc"], | ||
| ["http", "api.stripe.test", ""], | ||
| ] as const) { | ||
| const { filters, warnings } = filtersOf(kind, target, system) | ||
| expect(warnings).toEqual([]) | ||
| expect(filters.rootOnly).toBe(false) | ||
| expect(filters.attributeFilters.map((f) => f.key)).not.toContain("SpanKind") | ||
| } | ||
| }) | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| import { quoteWhereValue } from "@maple/domain/where-clause" | ||
|
|
||
| export type DependencyDrillKind = "service" | "database" | "messaging" | "rpc" | "http" | ||
|
|
||
| /** | ||
| * Where-clause that drills from a dependency edge to the spans behind it. | ||
| * | ||
| * The traces page filters root spans unless `root_only = false`, and a client | ||
| * span is almost never a root, so every drill opens the span-level list. There | ||
| * is no span-kind filter (a `SpanKind = ...` clause becomes a span-attribute | ||
| * filter that matches nothing), and the parser drops `(a OR b)` groups, so each | ||
| * drill is one aliased key that the query engine matches under every spelling. | ||
| * | ||
| * Targets mirror how the edge rollups name them: messaging and rpc fall back to | ||
| * the system when the destination or `rpc.service` is absent, so those drills | ||
| * also require the absence, otherwise they would match every destination of the | ||
| * system. The rpc system uses the legacy key because that is what the rollup | ||
| * reads today. | ||
| * | ||
| * Known gap: when a destination or rpc.service is literally named after its | ||
| * system, the rollup merges those spans and the fallback spans into one edge. | ||
| * Matching both needs an OR the where-clause parser does not support, so the | ||
| * drill shows only the fallback spans. | ||
| */ | ||
| export function dependencyDrillWhereClause( | ||
| kind: DependencyDrillKind, | ||
| target: string, | ||
| system: string, | ||
| ): string { | ||
| const value = quoteWhereValue(target) | ||
| const namedBySystem = system !== "" && system === target | ||
| const spans = (...clauses: string[]) => ["root_only = false", ...clauses].join(" AND ") | ||
| switch (kind) { | ||
| case "service": | ||
| return spans(`server.address contains ${value}`) | ||
| case "database": | ||
| return spans(`db.system.name = ${value}`) | ||
| case "messaging": | ||
| return namedBySystem | ||
| ? spans(`messaging.system = ${value}`, "messaging.destination.name !exists") | ||
| : spans(`messaging.destination.name = ${value}`) | ||
| case "rpc": | ||
| return namedBySystem | ||
| ? spans(`rpc.system = ${value}`, "rpc.service !exists") | ||
| : spans(`rpc.service = ${value}`) | ||
| case "http": | ||
| return spans(`server.address = ${value}`) | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.