Skip to content
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

TraceQL: Nested set intrinsics #3497

Merged
merged 7 commits into from
Mar 21, 2024

Conversation

joe-elliott
Copy link
Member

Expose nested set intrinsics into the traceql language. This allows calling applications to request structural details about spans.

Copy link
Contributor

@mdisibio mdisibio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, there are some really promising queries that can answered by accessing these columns directly. Looks very straight-forward and 99% LGTM. Can you take a look at couple q's? Probably ok but want to check.

@@ -1209,6 +1224,35 @@ func createSpanIterator(makeIter makeIterFn, primaryIter parquetquery.Iterator,
case traceql.IntrinsicStructuralSibling:
selectColumnIfNotAlready(columnPathSpanParentID)
continue

case traceql.IntrinsicNestedSetLeft:
nestedSetLeftExplicit = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check the behavior in this area, and see if these preds work ok with the nils added in the cases above? I'm thinking about a query that invokes both e.g. { nestedSetLeft = 1 } >> { } | select(nestedSetRight).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this works b/c the columns are stored in the columnPredicates and columnSelectAs maps.

if the explicit intrinsics hit first then they are added to the map and then the logic in selectColumnIfNotAlready prevents them from being overwritten with an OpNone condition.

if the structural intrinsics hit first then they are overwritten when the explicit intrinsics come along.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i did note and fix an issue in this area. if the structural intrinsic were to be added after the nested set intrinsic then it would have seen a non-empty predicate and not added the nil predicate. added to test for nil predicate

https://github.com/grafana/tempo/pull/3497/files#diff-7f3f53f3d2f4e723f54f23778f62dfa089a61ad39f1c90ca4bf63a335aacf3a5R1144

},
// fun way to get the root span
{
req: &tempopb.SearchRequest{Query: "{ nestedSetParent = -1 } | select(name)"},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a case for when we dual purpose read these columns. Similar to the other comment a query like: {nestedSetParent = -1} >> {} | select(name)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so there is kind of a bug here, but it exists for all spanset operators. for instance this:

{ span.foo = "bar" } >> {}

Will return the value of the attribute "foo" on every matched span even though the condition is on the LHS of the operator. I'm not sure if this is a bug or not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree it sounds like a bug. But pre-existing so ok for this PR, if I understand you correctly.

@@ -141,6 +141,16 @@ func (s *span) AttributeFor(a traceql.Attribute) (traceql.Static, bool) {
}

if a.Intrinsic != traceql.IntrinsicNone {
if a.Intrinsic == traceql.IntrinsicNestedSetLeft {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know if these extra checks are enough to show up in benchmarks, or would a switch be ok here? Wondering at what point this method needs another overhaul. For instance there is duplicate logic for .foo fallback to check resource-level and then span-level, between here and engine.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i will check benches but would guess these are not visible. don't mind swapping to a switch either for aesthetic or perf reasons if that's preferred.

are switches faster than a series of ifs?

Signed-off-by: Joe Elliott <number101010@gmail.com>
Signed-off-by: Joe Elliott <number101010@gmail.com>
Signed-off-by: Joe Elliott <number101010@gmail.com>
Signed-off-by: Joe Elliott <number101010@gmail.com>
Signed-off-by: Joe Elliott <number101010@gmail.com>
Signed-off-by: Joe Elliott <number101010@gmail.com>
Signed-off-by: Joe Elliott <number101010@gmail.com>
@joe-elliott joe-elliott merged commit 3d2850d into grafana:main Mar 21, 2024
14 checks passed
stoewer added a commit that referenced this pull request Apr 12, 2024
stoewer added a commit to stoewer/tempo that referenced this pull request Apr 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants