Splunk Search

## Overlay 2 time based grouped results in a Chart

Path Finder

Given the 2 following searches which are both over a 30 day period (and each having multiple countries in the results) how do I:

• Show the time as day range (0-30) instead of the actual dates showing
• Then overlay the 2 search results into the same line chart (as they are both over a 30 day period)

The searches are:

``````<query> earliest=-60d@d latest=-30d@d  | rex "country=(?<Country>[a-zA-Z]*)\s" | bin _time span=1d | stats count as DailyTotal by Country _time| timechart avg(DailyTotal) as AvgPerDay by Country
``````

And

``````<query> earliest=-30d@d latest=now  | rex "country=(?<Country>[a-zA-Z]*)\s" | bin _time span=1d | stats count as DailyTotal by Country _time| timechart avg(DailyTotal) as AvgPerDay by Country
``````

After hours of searching - this result produces overlaid lines BUT NOT with the 'Country' grouping and the chart time period shows 60 days not 30...

``````earliest=-60d@d latest=now  | rex "country=(?<Country>[a-zA-Z]*)\s" | bin _time span=1d | stats count as DailyTotal by Country _time| eval marker=if(_time<relative_time(now(), "-30d@d"), "Last Month", "This Month") | eval _time=if(marker=="Last Month", _time+(60*60*24*30), _time) |  timechart avg(DailyTotal) as AvgPerDay by marker
``````

How can I get the grouping back?

Tags (3)
1 Solution
Champion

First of all, you're doing unnecessary oparations - after bucketing by day and then counting by day, averaging by day is futile. So you could change your first search to the following and it should do the same, only quicker:

``````earliest=-60d@d latest=-30d@d  | rex "country=(?<Country>[a-zA-Z]*)\s" | timechart span=1d count as CountPerDay by Country
``````

Now, on to your original problem. To show a day instead of a date, you need to eval `_time` with `strftime`. In your case, that would yield something like

``````earliest=-60d@d latest=-30d@d  | rex "country=(?<Country>[a-zA-Z]*)\s" | eval day=strftime(_time, "%d") | chart avg(DailyTotal) as AvgPerDay by day Country
``````

for the first search.

To overlay two different time ranges in one timechart, you generally need to eval the `_time` field of one of the searches to the same period as the other one (so 30 days ahead in your case). See this blog post for details. The problem is, you will need to do this before you count by your new `day` field because that one can't be used to go back 30 days. So your searches could end up something like the following:

``````earliest=-30d@d latest=now | rex "country=(?<Country>[a-zA-Z]*)\s" | eval key="this month" | eval day=strftime(_time, "%d") | append [search earliest=-60d@d latest=-30d@d  | rex "country=(?<Country>[a-zA-Z]*)\s" | eval key="last month" | eval _time=_time+2592000 | eval day=strftime(_time, "%d")] | eval key=Country." ".key | chart count by day key
``````

I've had to change the calculation of `_time` to an external field sometimes, so if the above doesn't do the trick this one might:

``````earliest=-30d@d latest=now | rex "country=(?<Country>[a-zA-Z]*)\s" | eval key="this month" | eval day=strftime(_time, "%d") | append [search earliest=-60d@d latest=-30d@d  | rex "country=(?<Country>[a-zA-Z]*)\s" | eval key="last month" | eval time=_time+2592000 | eval day=strftime(_time, "%d")] | eval _time=if(key="last month",time,_time) | eval key=Country." ".key | chart count by day key
``````

See how far you get and feel free to ask questions if something doesn't work out.
PS: I've edited some of the search in this answer, it should now work.

Champion

First of all, you're doing unnecessary oparations - after bucketing by day and then counting by day, averaging by day is futile. So you could change your first search to the following and it should do the same, only quicker:

``````earliest=-60d@d latest=-30d@d  | rex "country=(?<Country>[a-zA-Z]*)\s" | timechart span=1d count as CountPerDay by Country
``````

Now, on to your original problem. To show a day instead of a date, you need to eval `_time` with `strftime`. In your case, that would yield something like

``````earliest=-60d@d latest=-30d@d  | rex "country=(?<Country>[a-zA-Z]*)\s" | eval day=strftime(_time, "%d") | chart avg(DailyTotal) as AvgPerDay by day Country
``````

for the first search.

To overlay two different time ranges in one timechart, you generally need to eval the `_time` field of one of the searches to the same period as the other one (so 30 days ahead in your case). See this blog post for details. The problem is, you will need to do this before you count by your new `day` field because that one can't be used to go back 30 days. So your searches could end up something like the following:

``````earliest=-30d@d latest=now | rex "country=(?<Country>[a-zA-Z]*)\s" | eval key="this month" | eval day=strftime(_time, "%d") | append [search earliest=-60d@d latest=-30d@d  | rex "country=(?<Country>[a-zA-Z]*)\s" | eval key="last month" | eval _time=_time+2592000 | eval day=strftime(_time, "%d")] | eval key=Country." ".key | chart count by day key
``````

I've had to change the calculation of `_time` to an external field sometimes, so if the above doesn't do the trick this one might:

``````earliest=-30d@d latest=now | rex "country=(?<Country>[a-zA-Z]*)\s" | eval key="this month" | eval day=strftime(_time, "%d") | append [search earliest=-60d@d latest=-30d@d  | rex "country=(?<Country>[a-zA-Z]*)\s" | eval key="last month" | eval time=_time+2592000 | eval day=strftime(_time, "%d")] | eval _time=if(key="last month",time,_time) | eval key=Country." ".key | chart count by day key
``````

See how far you get and feel free to ask questions if something doesn't work out.
PS: I've edited some of the search in this answer, it should now work.

Path Finder

Thanks for getting me there in the end - and I learned a lot along the way!!

Builder

If you want to optimize your search (instead of using an append), you could do a search for -60d - now and then do evals based on whether time is more than 30 days or not (case or if).

Builder

Something like this:
earliest="-60d@d" latest=now ....
| eval key=if(time > relativetime(now(), "-30d@h"),"currentPeriod","previousPeriod") | eval time=if(key="previousPeriod",time+604800,_time) | eval key=Country." ".key | timechart ..

Not using chart with day, but timechart with the _time field.

Path Finder

Your help is most appreciated! (Even when it doesn't work ๐ )

Champion

Path Finder

I think that's it - just off to check the numbers.....

Path Finder

Oh, spotted that you use 'if (key="previous month"... but the search uses "last month"

Champion

I corrected that in the answer, thanks for pointing it out.

Path Finder

Adding the search criteria back into the 2nd search (after append) helps! Better numbers coming out now...

Path Finder

Yes it works - with a caveat...

Is there any way to get it to have the numbering on the time axis being from -30 to 0?

Champion

Definitely. I assume you want -30 instead of 0 and 0 instead of 30, then simply add an eval for that somewhere:

``````... | eval day=day-30
``````
Path Finder

You're right on the first part - counting was what I should have done!

But I get some strange results using both the last answers! I was expecting 2 lines in the chart per country (one for the last 30 days, one for the previous 30 days to that). I'm left with:

3 lines: key, Country, count - none of which make sense - neither do the axes

I'm too new at this to get to grips with it, but this seems further away than at the start?

Champion

Sorry, there was a `stats` instead of a `chart` in the final version. Please try again.

Path Finder

Now I get:

Error in 'chart' command: The argument 'Country' is invalid.

๐

Champion

Damn, yeah I just noticed this can't work - chart only accepts two split-by arguments (there are only two axes). Lemme work some more on that.

Esteemed Legend

You need the `timewrap` app, for sure:

https://splunkbase.splunk.com/app/1645/

Path Finder

We can't use any additional plugins...

Esteemed Legend