class QueryRunner(object):
    """ Query Runner.
    a class to handle query to splunkd.
    It grabs a splunkd object according to the splunkrc params provided:
        - If splunkrc is a dictionary, it will create a new splunkd object.
        - If given other object type, it will do do Dependency Injection on _splunkd
    """
    def __init__(self,
                 splunkrc,
                 index_name=INSTRUMENTATION_INDEX_NAME,
                 owner='-',
                 app=INST_APP_NAME,
                 result_reader=QueryRunnerResult):
        self.splunkrc = splunkrc or SPLUNKRC
        self.result_reader = result_reader

        if type(self.splunkrc) is dict:
            self._splunkd = Splunkd(**self.splunkrc)
        else:
            self._splunkd = splunkrc

        self._splunkd.namespace['owner'] = owner
        self._splunkd.namespace['app'] = app

        if self._splunkd.has_index(index_name):
            self._index = self._splunkd.get_index(index_name)
        else:
            logging.error('ERROR: INDEX IS NOT AVAILABLE')
            raise (Exception("ERROR INDEX UNAVAILABLE"))

    def search(self, search_cmd, **kwargs):
        """Submit a new search.
        It is a wrapper to the private method _query.
        """
        return self._query(search_cmd, **kwargs)

    def _query(self, search_cmd, **kwargs):
        """Query.

        Note that earliest is inclusive & latest is exclusive:
                                                        [earliest, latest)
        (Prevents getting last-second events again during the next query)
        """
        job = self._splunkd.search(search_cmd, **kwargs)

        while not job.is_done():
            time.sleep(0.2)
        result = self.result_reader(job.results(count=0))
        if hasattr(result, 'job'):
            result.job = job
        return result
class EventWriter(object):
    """ Event Writer class
    This class handles writing to the index.
    It grabs a splunkd object according to the splunkrc params provided:
        - If splunkrc is a dictionary, it will create a new splunkd object.
        - If given other object type, it will do do Dependency Injection on _splunkd

    """
    def __init__(self, splunkrc=None, index_name=None):
        self.splunkrc = splunkrc or SPLUNKRC
        self.socket = None
        self._index = None

        if type(self.splunkrc) is dict:
            self._splunkd = Splunkd(**self.splunkrc)
        else:
            self._splunkd = splunkrc

        if index_name:
            if self._splunkd.has_index(index_name):
                self._index = self._splunkd.get_index(index_name)
            else:
                logging.error('ERROR: INDEX IS NOT AVAILABLE')
                raise Exception("ERROR INDEX UNAVAILABLE")

    def submit(self, event, host=None, source=None, sourcetype=INSTRUMENTATION_SOURCETYPE):
        # Note: We used to use the ordinary index.submit method from splunklib,
        #       instead of using a socket. However, that method uses receivers/simple,
        #       an endpoint that bypasses index time field extraction (which we rely on).
        temp_socket = self._index.attach(host=host, source=source, sourcetype=sourcetype)
        temp_socket.send(self.marshal_event(event))
        temp_socket.close()

    def open_socket(self, host=None, source=None, sourcetype=INSTRUMENTATION_SOURCETYPE):
        '''
        Opens a socket to stream events to be indexed, saving it as
        an instance variable for later use when submit_via_socket is called.
        :param host:
        :param source:
        :param sourcetype:
        :return:
        '''
        self.socket = self._index.attach(host=host, source=source, sourcetype=sourcetype)
        return self.socket

    def close_socket(self):
        '''
        Closes socket and set it to none
        '''
        if self.socket:
            self.socket.close()
        self.socket = None

    def submit_via_socket(self, event):
        """
        Submit the event provided using socket connection.
        """
        event = self.marshal_event(event)
        if not self.socket:
            self.open_socket()
        self.socket.send(event)

    @staticmethod
    def marshal_event(event):
        '''
        Marshals the given event into a json string, suitable for passing
        to an open receivers/stream socket.
        '''
        if not isinstance(event, (str, bytes)):
            event = json.dumps(event, default=json_serial)
        if isinstance(event, str) and sys.version_info >= (3, 0):
            event = event.encode()
        return event
Example #3
0
class EventWriter(object):
    """ Event Writer class
    This class handles writing to the index.
    It grabs a splunkd object according to the splunkrc params provided:
        - If splunkrc is a dictionary, it will create a new splunkd object.
        - If given other object type, it will do do Dependency Injection on _splunkd

    """
    def __init__(self, splunkrc=None, index_name=None):
        self.splunkrc = splunkrc or SPLUNKRC
        self.socket = None
        self._index = None

        if type(self.splunkrc) is dict:
            self._splunkd = Splunkd(**self.splunkrc)
        else:
            self._splunkd = splunkrc

        if index_name:
            if self._splunkd.has_index(index_name):
                self._index = self._splunkd.get_index(index_name)
            else:
                logging.error('ERROR: INDEX IS NOT AVAILABLE')
                raise (Exception("ERROR INDEX UNAVAILABLE"))

    def submit(self, event, host=None, source=None, sourcetype=None):
        """Submit a new event directly to the index."""
        if self._index:
            self._index.submit(event,
                               host=host,
                               source=source,
                               sourcetype=sourcetype)
        else:
            logging.error('ERROR: INDEX IS NOT AVAILABLE')
            raise Exception("ERROR INDEX UNAVAILABLE")

    def open_socket(self, host=None, source=None, sourcetype=None):
        '''
        Opens a socket to stream events to be indexed
        :param host:
        :param source:
        :return:
        '''
        self.socket = self._index.attach(host=host,
                                         source=source,
                                         sourcetype=INSTRUMENTATION_SOURCETYPE)
        return self.socket

    def close_socket(self):
        '''
        Closes socket and set it to none
        '''
        if self.socket:
            self.socket.close()
        self.socket = None

    def submit_via_socket(self, event):
        """
        Submit the event provided using socket connection.
        """
        if not isinstance(event, str):
            event = json.dumps(event, default=json_serial)
        if not self.socket:
            self.open_socket()
        self.socket.send(event)