New to Honeycomb? Get your free account today!
Earlier this year, we introduced relational fields. Relational fields enable you to query spans based on their relationship to one other within a trace, rather than only in isolation. We’ve now expanded this feature and introduced four new prefixes: child.
, none.
, any2.
, and any3.
.
Previously, you could use root.
, parent.
, and any.
to query on the root span of your target span’s trace, the parent span of your target span, and any other span in the same trace as your target span. Now, you can also query on a direct child of your target span (child.
), exclude traces where any span matches criteria you determine (none.
), and query two more additional spans within the same trace (any2.
and any3.
).
Let’s dive into how to use these new prefixes, along with showing you some examples of where they might be helpful.
none.
The none.
prefix allows you to query for a trace where no span in the trace matches your specified criteria. This can come in handy when you want to find instances where a specific function was never called, a certain error never occurred, etc.
Tips for using none.
:
- Filter for the
none.
criteria. For a trace to be included in your results, it must not include any span that matches all of yournone.
filters. none.
is not available in the GROUP BY clause.
Example
A very common use case for none.
is when searching for traces that are missing a root span. You can accomplish that with this query:
In this case, we’re finding traces where there is not a single span that has no parent ID—which means there is no root span.
child.
The child.
prefix allows you to query for a span that is a direct descendent of the span targeted by your query. Results match on the first child span found per parent to match all child.
filters, and may exclude additional matching child spans.
Tips for using child.
:
- Filter for the
child.
criteria. All filters usingchild.
will apply to a single span. - We only return the first matching child span that we find.
- When grouping by
child.
, keep in mind that there may be additional groups that won’t appear in your results (for other child spans that could also match your filters), since we only return the first one we find per parent.
Example
Let’s say you have a /cart/checkout
process that can encounter a number of errors. The specific error information is only available on the child spans where the error occurred, not on the /cart/checkout
span that kicked off the steps that had errors.
You’d like to target only a specific type of error, context canceled, but that error is a common one that can occur across various contexts, so you need to find errors of that type AND that were generated via the /cart/checkout
process.
In theory, you could do this using parent.
:
However, this poses an issue: you want to see the durations of the /cart/checkout
process altogether when these errors occurred, not the duration of just the errors themselves, and parent.
can’t be used in the VISUALIZE clause.
To solve that, you can use child.
to still filter on both of those criteria at once, while also visualizing the duration of the /cart/checkout
process that kicked those error spans off. Note the much longer durations in this result, since this visualizes the duration of those parent spans.
any2.,
any3.
Do these prefixes seem familiar? They are! We’ve introduced the ability to add multiple any
. prefixes to your queries. In addition to any.
, you can use any2.
and any3.
to target more spans within the trace that have specific attributes—you can now query for traces that contain up to three other spans, each with their own filters, that appear anywhere in the trace.
Tips for using any.
, any2.
, and any3.
:
- Filter using
any.
,any2.
, andany3.
fields. - If you include more than one filter per prefix (e.g.
any2.name = x
,any2.service_name = y
), all filters on a given prefix will apply to the same additional span in the trace. - Each color (and its associated prefix) represents a single other span in the trace otherwise targeted by your query.
- For each
any.
prefix, we will return the first matching span we find. - To use a given
any.
prefix in the GROUP BY clause, you must use at least one filter on that same prefix in the WHERE clause.
Example
Let’s say you want to look at a step where you save shipping quotes displayed to a user and you want to map that step to the specific users those quotes were displayed to. You can start with a query like this:
Unfortunately, the app.user_id
field is not populated on those spans:
You know the user ID is available somewhere in the trace, but you’re not sure where… And ideally, you’d also like to be able to start with orders where the total was high. That amount is also usually populated somewhere in the trace, but not on this span.
To get those values, you can use two of the any.
prefixes:
This will allow you to pull that data from anywhere across the traces, while still targeting that INSERT shipping.quotes
step. Once you click through to a trace from this result, you’ll see something like this:
Magic!
Conclusion
Relational fields allow you to query across traces to find spans of interest based on their relationships to one another. We’re excited to expand this feature to provide even more tools to write powerful queries in Honeycomb. Read more about the feature in our docs.
This post on relational fields was written by Quinn Leong and Lucia Okeh.