[PYTHON] Create Splunk custom search command Part 2

Last time is the first step to create a command to generate only one event as Splunk's Custom Search Command without taking any arguments. Did.

This time, we'll take an argument and brush up the command to generate the number of events specified by the argument.

Review up to the last time

Last time: "Creating a Splunk custom search command-first step --- Qiita"

I have created a custom search command generatehello of type Generating commands.

Created up to the last time HelloWorld.py


#!/usr/bin/env python

import sys
import os
import time

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
from splunklib.searchcommands import \
    dispatch, GeneratingCommand, Configuration, Option, validators

@Configuration()
class HelloWorldCommand(GeneratingCommand):
    """ %(synopsis)

    ##Syntax

    %(syntax)

    ##Description

    %(description)

    """
    def generate(self):
        return [{"_time": time.time(), "greeting": "hello, world"}]


dispatch(HelloWorldCommand, sys.argv, sys.stdin, sys.stdout, __name__)

This program has the following challenges:

This time, we will solve this. Splunk Official Blog "[Building custom search commands in Python part I – A simple Generating commands](https://www.splunk.com/en_us/blog/tips-and-tricks/building-custom-search-commands-in- It is based on python-part-ia-simple-generating-command.html) ". (Slightly changed)

First issue: Specifying the number of events

Allows you to specify the number of events.

Argument specification method (receipt method)

The argument is [Decorator](https://qiita.com/msi/items/acfa737842416580deaf#%E3%83%87%E3%82%B3%E3%83%AC%E3%83%BC%E3%82% BFdecorator-% E3% 81% A8% E3% 81% AF) Specify with Option.

Here, we will simply call Option as a class and specify it.

In the created class HelloWorldCommand, call it as follows.

Option( )


from splunklib.searchcommands import Option

@Configuration()
class HelloWorldCommand(GeneratingCommand):
    count = Option()

Option () also sets the use of count as a command argument in the SPL statement, as well as simply storing the value in a variable called count. In the SPL statement, specify | generatehello count = 3.

Option class"Module structure - Python classes | Documentation | Splunk Developer Program"ThereisadescriptionoftheAPIin"splunklib.searchcommands—SplunkSDKforPythonAPIReference"Although it is a reference, it is a document that is difficult to decipher.

class splunklib.searchcommands.Option(fget=None, fset=None, fdel=None, doc=None, name=None, default=None, require=None, validate=None)

Represents a search command option.

Required options must be specified on the search command line.

Example:

Short form (recommended). When you are satisfied with built-in or custom validation behaviors.

1
2
3
4
5
6
7
8
from splunklib.searchcommands.decorators import Option
from splunklib.searchcommands.validators import Fieldname

total = Option( doc=''' Syntax: total=<fieldname> Description: Name of the field that will hold the computed sum''', require=True, validate=Fieldname())

ʻOption ()hasclass splunklib.searchcommands.Option (fget = None, fset = None, fdel = None, doc = None, name = None, default = None, require = None, validate = None)` It has become.

fget, fset, and fdel are arguments that are passed inside the ʻOption ()to the Python built-in function (decorator)property, which are referenced, assigned, and released (del`), respectively. Specify the function for, but for now it's best to keep it in the corner of your head. (If you're used to using Python property, you probably know it.)

doc, name, default, require, and validate are arguments to remember.

argument Description
doc Write a description of the arguments.
name Specify the name of the argument. If omitted, the same name as the variable name of the assignment destination is set.
default Sets the default value when the argument is omitted.
require Sets whether the argument is required. boolean type(True/False)
validate Sets the argument type.

If ** name ** is omitted, the same name as the variable name of the assignment destination will be the argument name of the search command, but conversely, by specifying ** name **, it will be different from the variable name. Argument names can be set.

** validate ** is defined in splunklib.searchcommands.validators, but SDK It seems that there is no choice but to look into .py). (Explanation omitted)

Is defined. (When read with ʻimport *, only Boolean, Code, Duration, File, ʻInteger, List, Map, RegularExpression, Set)

Referenced Blog, Let's change it a little and set require = False to an integer value, default = 1.

argument&nbsp;count&nbsp;settings of


count = Option(require=False, validate=validators.Integer(), default=1)

Repeated output

Since count is given as an argument (default is 1), the output is repeated accordingly.

last time

        return [{"_time": time.time(), "greeting": "hello, world"}]

But this time I want to return the value without waiting for all the processing, so instead of returning the list with return, I will return the individual event with yield.

        for i in range(0, self.count):
            yield {"_time": time.time(), "greeting": "hello, world"}

The entire

After integrating up to this point, the program looks like this: Rename it to HelloWorld2.py.

Arguments can be specified&nbsp;HelloWorld2.py


#!/usr/bin/env python

import sys
import os
import time

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
from splunklib.searchcommands import \
    dispatch, GeneratingCommand, Configuration, Option, validators

@Configuration()
class HelloWorldCommand(GeneratingCommand):
    """ %(synopsis)

    ##Syntax

    %(syntax)

    ##Description

    %(description)

    """
    count = Option(require=False, validate=validators.Integer(), default=1)

    def generate(self):

        for i in range(0, self.count):
            yield {"_time": time.time(), "greeting": "hello, world"}


dispatch(HelloWorldCommand, sys.argv, sys.stdin, sys.stdout, __name__)

Operation test

Perform an operation test in the development environment.

HelloWorld2.py&nbsp;Operation check


$ python3 HelloWorld2.py __EXECUTE__ count=3 < /dev/null

_time,__mv__time,greeting,__mv_greeting
1584952340.0804844,,"hello, world",
1584952340.0816362,,"hello, world",
1584952340.0816433,,"hello, world",

Installation in Splunk environment and operation check

Since we did the App registration in the Splunk environment last time, copy the modified HelloWorld2.py to helloword / bin. Just like last time, be careful about owners, groups, and permissions.

Splunk&nbsp;Copy to environment


cp HelloWorld2.py /opt/splunk/etc/apps/helloworld/bin/

Since we changed the name, we also modify default / commands.conf. The custom search command name is generatehello2.

commands.conf


# [commands.conf]($SPLUNK_HOME/etc/system/README/commands.conf.spec)
# Configuration for Search Commands Protocol version 2

[generatehello]
filename = HelloWorld.py
chunked = true
python.version = python3

[generatehello2]
filename = HelloWorld2.py
chunked = true
python.version = python3

[Check with btool](https://qiita.com/msi/items/02d029d655e1f9285806#btool-%E3%81%AB%E3%82%88%E3%82%8B%E3%83%81%E3% After doing 82% A7% E3% 83% 83% E3% 82% AF), either debug / refresh or restart Splunk.

Operation check on Splunk

Try typing | generatehello count = 3 in the search.

image.png

3 events have been output.

Second challenge: "hello, world" event output

So far, there is a greeting in the" Related Fields "part on the left, and when I click on it, the words" hello, world "appear, but not in the event display.

This can be displayed by explicitly specifying the _raw field. Here, we simply put the same greeting as in _raw and output it.

_raw&nbsp;Field settings


        greeting_msg = "hello, world"
        for i in range(0, self.count):
            yield {"_time": time.time(), "greeting": greeting_msg, "_raw": greeting_msg}

The whole is as follows.

_raw&nbsp;I set the field&nbsp;HelloWorld2.py


#!/usr/bin/env python

import sys
import os
import time

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "lib"))
from splunklib.searchcommands import \
    dispatch, GeneratingCommand, Configuration, Option, validators

@Configuration()
class HelloWorldCommand(GeneratingCommand):
    """ %(synopsis)

    ##Syntax

    %(syntax)

    ##Description

    %(description)

    """
    count = Option(require=False, validate=validators.Integer(), default=1)

    def generate(self):

        greeting_msg = "hello, world"
        for i in range(0, self.count):
            yield {"_time": time.time(), "greeting": greeting_msg, "_raw": greeting_msg}


dispatch(HelloWorldCommand, sys.argv, sys.stdin, sys.stdout, __name__)

As in the first case, check the operation in the development environment → copy to the Splunk environment → check with btool → check with Splunk search.

Operation check in development environment


$ python3 HelloWorld2.py __EXECUTE__ count=3 < /dev/null

_time,__mv__time,greeting,__mv_greeting,_raw,__mv__raw
1584954369.7098827,,"hello, world",,"hello, world",
1584954369.7099497,,"hello, world",,"hello, world",
1584954369.7099597,,"hello, world",,"hello, world",

Notice that the _raw field is increasing.

Splunk&nbsp;Copy to environment


cp HelloWorld2.py /opt/splunk/etc/apps/helloworld/bin/

($ SPLUNK_HOME = / opt / splunk)

Check the operation by searching Splunk. (" | generatehello2 count = 3 ")

image.png

It is now displayed in the Events field.

Summary

Brush the Generating commands type custom search command created in the previous "Splunk custom search command creation-first step --- Qiita" It's up.

If you can do this, it will be easier to proceed to Eventing commands.

Recommended Posts

Create Splunk custom search command Part 2
Create a custom search command in Splunk (Streaming Command)
Create a Splunk custom search command-the first step-
Creating custom search commands for Splunk EventingCommand
[Linux] Search command
Create a command to encode / decode Splunk base64
Create command shortcuts on Ubuntu 16.04
Create custom rules with ElastAlert
Create custom Django commands and run them from the command line