require 'net/http' require 'uri' require 'json' # Query Splunk with arbitrary search criteria module NagiosHerald module Helpers class SplunkQuery #include NagiosHerald::Logging # Public: Initialize a new SplunkQuery object. # # query - A string representing the query to send to Splunk. # index - Optional index to specify (else Splunk defaults to all indexes # available to the authenticated user). # output - The output format we'd like (i.e. csv, json, xml); defaults # to json. # # Example: # # splunk_query = NagiosHerald::Helpers::SplunkQuery.new('sourcetype=perf_log page=index.html') # splunk_query = NagiosHerald::Helpers::SplunkQuery.new('transaction_state=paid', {:index => 'get_paid'}) # splunk_query = NagiosHerald::Helpers::SplunkQuery.new('source=nagios-herald.log alert_type=host', {:output => 'csv'}) # # Returns a new SplunkQuery object. def initialize(query, options={}) @splunk_query = query @splunk_index = options[:index] ? options[:index] : nil @splunk_output = options[:output] ? options[:output] : 'json' # Pull the Splunk URI, username, and password from the config. splunk_url = Config.config['splunk']['url'] @splunk_username = Config.config['splunk']['username'] @splunk_password = Config.config['splunk']['password'] # Parse the URI. uri = URI.parse(splunk_url) @splunk_host = uri.host @splunk_port = uri.port @splunk_uri = uri.request_uri end # Public: Generate the parameters for the Splunk query. # # Example: # # parameters = splunk_query.parameters # # Returns the Splunk query parameters. def parameters # Earliest time we should look for events; defaults to 7 days ago. earliest_time = Config.config['splunk']['earliest_time'] ? Config.config['splunk']['earliest_time'] : '7d' # Latest time we should look for events; defaults to now. latest_time = Config.config['splunk']['latest_time'] ? Config.config['splunk']['latest_time'] : 'now' # Maximum results returned; defaults to 100. max_results = Config.config['splunk']['max_results'] ? Config.config['splunk']['max_results'] : 100 params = { 'exec_mode' => 'oneshot', 'earliest_time' => "-#{earliest_time}", 'latest_time' => latest_time, 'output_mode' => @splunk_output, 'count' => max_results } if @splunk_index.nil? params['search'] = "search #{@splunk_query}" else params['search'] = "search index=#{@splunk_index} " + @splunk_query end params end # Public: Queries Splunk. # # Example: # # results = splunk_query.query # # Returns the results of the query in the requested format, nil otherwise. def query http = Net::HTTP.new( @splunk_host, @splunk_port ) http.use_ssl = true http.open_timeout = 1 http.read_timeout = 2 http.ssl_timeout = 1 http.verify_mode = OpenSSL::SSL::VERIFY_NONE # don't validate the cert request = Net::HTTP::Post.new( @splunk_uri ) request.basic_auth( @splunk_username, @splunk_password ) request.set_form_data( parameters ) begin response = http.request( request ) rescue Exception => e logger.warn "Failed to send request: #{e.message}" return nil end if response.code.eql?( "200" ) response.body else logger.warn "Splunk query failed with HTTP #{response.code}: #{response.message}" logger.warn response.body return nil end end end end end