For quite some time I was thinking about putting together a few things I've learned and come across regularly, since I joined the Dashboarding and Data explorer band wagon.
So rather than wait until I get the time to write a proper blog post, I thought why not start small and iterate. So here we are:
Shift the timeframe for METRICs relative to the selected timeframe (aka :timeshift transformation)
Something we even documented by now, pls check out https://www.dynatrace.com/support/help/shortlink/explorer-advanced-query-editor#example-compare-a-me... and let us know whether something isn't clear or missing.
The TLTR; with the :timeshift transformation in the Data explorer code mode you can shift single metrics in comparison to others. So that on a dashboard you choose last 7 days, for example, your first metric (line) shows you the traffic from this week, while your shifted metric 2 shows you the line from last week. Both use the global timeframe selector as a reference and both metrics (shifted and unshifted) dynamically change based on that.
When to use the :timeshift transformation? When you want to compare two or more metrics for a different timeframe in a single visualization. E.g in a graph/line chart.
A static shift would be to use the TILE settings on the dashboard tile, where you define either a certain timeframe or relative timeframe for the whole tile. This applies to all metrics in that tile.
When to use the tile settings: When you need different timeframes for different visualizations. E.g. State visualizations (last day, last 2 h,...) vs. trend based visualizations (last 30 days) on the same dashboard. Tip: obviously querying smaller timeframes should also be more performant, so you might end up
Working with rates
Sometimes you are not interested in the absolute count but in the rate (common for APM cases). This is how you can transform it:
The original metric:
The :rate transformation applied, tells the Metrics API, pls transform this to a per minute number, so you don't have to do the math. Tipp: should your metric not support rate automatically (its no number by default) than use :auto:rate(..) to fix it.
Finally :toUnit (silently available since 1.228) to set the unit accordingly and have the beloved /m... in the charts
While with Custom charting we provided a naive matching between the metric key and the "category" of our metrics, I'd argue you can do pretty much the same with the Data explorer and probably most of you just don't know this yet! But let's talk examples:
E.g. when you look for certain "application" metrics you sometimes end up with "premature" results like the following:
Since the search term provided is matched against the display name as well as the key by adding additional words like, app or web will do the trick here and only display you the desired and relevant builtin metrics. This of course works for all others - e.g. add additional words like "services".. or "process" or any other entity type to refine your search result and get to relevant metrics faster.
The basis a synthetic based event metric:
Naive missing value replacement strategy - connect gaps (use build mode):
What if you want to set all missing values to 0? Easy with the code mode and the :default() transformation:
I often come across the request to filter all entities that do not match a certain name.
Use not and any other condition such as prefix() or an entity selector in combination to achieve that. An example with an entity selector:
<host metric> : filter( not( in("dt.entity.host", entitySelector("type(~"HOST~")")) ) )
Thanks for this! We're using code more and more and examples of specific use cases is of great help.
Special request for volume 2 (which I hope is coming soon): filter on relations (example: response time of all the services related to a specific process group).
The advanced filtering capabilities are really cool indeed. Especially when you get familiar with the entity selectors.
For example, the following query will show you the failure of services which are called from services running in a process group named prodCluster tagged with a tag named TAG1. Such queries are really cool with honeycomb visualizations.
builtin:service.errors.total.rate :splitBy("dt.entity.service") :filter(in("dt.entity.service",entitySelector("type(SERVICE),toRelationships.calls(type(SERVICE),tag(TAG1),fromRelationships.runsOn(type(PROCESS_GROUP),entityName(prodCluster)))"))) :avg :auto :sort(value(avg,descending)) :limit(100)