mvsum for splunk
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# put this in $SPLUNK_HOME/etc/apps/search/local/commands.conf | |
[mvsum] | |
filename = mvsum.py | |
streaming = true | |
retainsevents = true | |
supports_multivalues = true | |
supports_getinfo = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# save this as $SPLUNK_HOME/etc/apps/search/bin/mvsum.py | |
# make sure to chmod it to be executable | |
# Sums multi-valued fields within a single result. | |
# Usage: | |
# | mvsum response_time as total_response_time | |
# where "response_time" is a multi-valued numeric field. | |
import splunk.Intersplunk as si | |
import sys | |
import exceptions | |
def num(s): | |
try: | |
return int(s) | |
except exceptions.ValueError: | |
return float(s) | |
isgetinfo, sys.argv = si.isGetInfo(sys.argv) | |
keywords, options = si.getKeywordsAndOptions() | |
if len(keywords) != 3 or keywords[1] != "as": | |
si.parseError("Invalid syntax. Syntax is: mvsum input-field as output-field") | |
if isgetinfo: | |
# outputInfo automatically calls sys.exit() | |
si.outputInfo(True, False, True, False, None, False) | |
try: | |
input_field = keywords[0] | |
output_field = keywords[2] | |
results, dummyresults, settings = si.getOrganizedResults() | |
for result in results: | |
if input_field in result: | |
field_value = result[input_field] | |
if field_value: | |
if isinstance(field_value, list): | |
nums = [num(x) for x in field_value] | |
result[output_field] = str(sum(nums)) | |
else: | |
result[output_field] = int(field_value) | |
except: | |
import traceback | |
stack = traceback.format_exc() | |
results = si.generateErrorResults("Error : Traceback: " + str(stack)) | |
si.outputResults(results) |
Ryan, I'd like to put your code into an app on Splunkbase. Any objections? I think many people would benefit.
Jordan/Ryan,
I updated the code to be compatible with Splunk 8 as well as SCP2.
commands.conf:
[mvsum]
filename = mvsum.py
chunked = true
python.version = python
mvsum.py:
# save this as $SPLUNK_HOME/etc/apps/search/bin/mvsum.py
# make sure to chmod it to be executable
# Sums multi-valued fields within a single result.
# Usage:
# | mvsum total=total_response_time response_time
# where "response_time" is a multi-valued numeric field.
from __future__ import absolute_import, division, print_function, unicode_literals
#import app
import os, sys
splunkhome = os.environ['SPLUNK_HOME']
sys.path.append(os.path.join(splunkhome, 'etc', 'apps', 'mvstats', 'lib')) # Update ???
from splunklib.searchcommands import dispatch, StreamingCommand, Configuration, Option, validators
from splunklib import six
# Helper function to parse values in the <input-field> field
def getNum(value):
if value == '' or value is None or value is "NULL":
value = None
else:
try:
value = float(value)
if value.is_integer():
value = int(value)
except ValueError:
pass
return value
@Configuration()
class mvsumCommand(StreamingCommand):
""" Computes the sum of a multi-value field.
##Syntax
.. code-block::
mvsum total=<field> <mv-field>
##Description:
Computes the sum of the values in a multi-value field.
##Example:
..code-block::
index=_internal | stats values(date_hour) as hours | mvsum hours as sum
"""
result = Option(
doc='''
**Syntax:** **result=***<fieldname>*
**Description:** Name of the field that will hold the computed sum''',
require=True, validate=validators.Fieldname())
def stream(self, records):
self.logger.debug('mvsumCommand: %s', self) # logs command line
if len(self.fieldnames) != 1:
raise Exception('Please specify a field')
for record in records:
return_value = ''
for fieldname in self.fieldnames:
field_value = record[fieldname]
if field_value:
if isinstance(field_value, list):
nums = [getNum(x) for x in field_value]
return_value = str(sum(nums))
else:
return_value = str(getNum(field_value))
record[self.result] = return_value
yield record
if __name__ == "__main__":
dispatch(mvsumCommand, sys.argv, sys.stdin, sys.stdout, __name__)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey Jordan, wanted to let you know I took your code and updated it to support Splunk 6.x. Thanks for the inspiration. Here are the update files that have been working fine in 6.x across all platforms.