Splunk Search

How to use eval to sum a large set of fields with field name matching a pattern?

driekhof
Path Finder

I have several fields like this:

types.events.1
types.events.2
types.events.3
etc

I can use eval to sum them like this

eval totalDomainEvents = 'types.events.1' + 'types.events.2' + 'types.events.3' + etc

But I have a lot of these fields. Is there a way to do something like this?

eval totalDomainEvents = sum('types.events.*')

That doesn't work, but hopefully conveys the idea. I'd like to avoid including every field I want included in the eval if possible by just using some kind of wildcard matching to indicate the fields to include in the eval.

0 Karma

driekhof
Path Finder

I also noticed that when I'm trying to sum a large number of fields with eval, I get erroneous values. For example, the total is correct as long as I'm summing 2 or 3 fields, but as I try to sum more and more the total starts missing some fields, and eventually around 20 fields the total becomes less that some individual fields.

0 Karma

DalJeanis
SplunkTrust
SplunkTrust

Here's some run-anywhere code that shows you an example after generating random data...

| makeresults count=5
| eval "types.events.1" = tonumber(substr(tostring(random()),1,2))
| eval "types.events.2" = tonumber(substr(tostring(random()),1,3))
| eval "types.events.3" = tonumber(substr(tostring(random()),2,2))
| table types.events.*
| eventstats sum("types.events."*) as sum.*
| addtotals row=f col=t

producing this...

types.events.1  types.events.2  types.events.3  sum.1  sum.2  sum.3  
18              651             28              132    2139   243    
67              169             49              132    2139   243    
16              440             49              132    2139   243    
11              149             60              132    2139   243    
20              730             57              132    2139   243    
132             2139            243             660    10695  1215   

...but you probably wanted this

| makeresults count=5
| eval "types.events.1" = tonumber(substr(tostring(random()),1,2))
| eval "types.events.2" = tonumber(substr(tostring(random()),1,3))
| eval "types.events.3" = tonumber(substr(tostring(random()),2,2))
| table types.events.*    | addtotals row=t col=f fieldname="types.events.total" "types.events.*"

... which produces this ...

types.events.1  types.events.2  types.events.3  types.events.total      
16              380             87              483                     
18              168             42              228                     
15              134             49              198                     
10              167             10              187                     
15              511             16              542  

driekhof
Path Finder

Thanks. I'm trying to get that to feed into a timechart, but not having any luck so far. I've got events coming in every second, and I'd like to sum them over 1 minute spans.

0 Karma

DalJeanis
SplunkTrust
SplunkTrust

You need _time for that, which is a different "event faker" command. This generates test data...

| gentimes start="01/25/2017:23:00:00" end="01/27/2017:01:00:00" increment=23m 
| streamstats count as baseEvent | eval series="A"
| append[| gentimes start="01/26/2017:03:00:00" end="01/26/2017:21:00:00" increment=47m | streamstats count as baseEvent | eval series="B"]
| append[| gentimes start="01/26/2017:01:17:00" end="01/26/2017:23:18:00" increment=21m | streamstats count as baseEvent | eval series="C"]
 | eval _time=starttime
 | eval "types.events.1" = tonumber(substr(tostring(random()),1,2))
 | eval "types.events.2" = tonumber(substr(tostring(random()),1,3))
 | eval "types.events.3" = tonumber(substr(tostring(random()),2,2))
 | table _time types.events.*    

... this adds the totals...

| addtotals row=t col=f fieldname="types.events.total" "types.events.*"

... then this timecharts the results...

| timechart span=1h sum("types.events.*") as "types.events.*"

That's spanned at the 1h level because my transaction faker is set up to generate transactions every few minutes across a few days, but you can use it however you want.

0 Karma

niketn
Legend

You can use foreach command for template search
(Refer to documentation: https://docs.splunk.com/Documentation/Splunk/latest/SearchReference/Foreach)

<Your Base Search>| foreach "types.events."* [eval totalDomainResults=totalDomainResults + '<<FIELD>>']

Both the fieldname as well as field string <<FIELD>> need to be escaped with double quotes and single quotes respectively, since your field name contains special character dot (.) which is used for concatenation in eval statements.

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

driekhof
Path Finder

I tried this but nothing is returned for totalDomainResults. Am I supposed to substitute something for FIELD?

0 Karma

somesoni2
SplunkTrust
SplunkTrust

Just declare a field totalDomainResults before foreach command, like this

<Your Base Search> | eval totalDomainResults=0 | foreach "types.events.*" [eval totalDomainResults=totalDomainResults + '<<FIELD>>']
Get Updates on the Splunk Community!

Routing logs with Splunk OTel Collector for Kubernetes

The Splunk Distribution of the OpenTelemetry (OTel) Collector is a product that provides a way to ingest ...

Welcome to the Splunk Community!

(view in My Videos) We're so glad you're here! The Splunk Community is place to connect, learn, give back, and ...

Tech Talk | Elevating Digital Service Excellence: The Synergy of Splunk RUM & APM

Elevating Digital Service Excellence: The Synergy of Real User Monitoring and Application Performance ...