class LogStash::Filters::Rest
Logstash REST Filter This filter calls a defined URL and saves the answer into a specified field.
Public Instance Methods
filter(event)
click to toggle source
# File lib/logstash/filters/rest.rb, line 278 def filter(event) return unless filter?(event) request = LogStash::Util.deep_clone(@request) @logger.debug? && @logger.debug('processing request', :request => request, :sprintf_needed => @sprintf_needed) if @sprintf_needed request = field_intrpl(request, event) @logger.debug? && @logger.debug('interpolated request', :request => request) end client_error = nil begin code, body = request_http(request) rescue StandardError => e client_error = e end if !client_error && code.between?(200, 299) @logger.debug? && @logger.debug('success received', :code => code, :body => body) process_response(body, event) else @logger.debug? && @logger.debug('http error received', :code => code, :body => body, :client_error => client_error) if @fallback.empty? @logger.error('error in rest filter', :request => request, :json => @json, :code => code, :body => body, :client_error => client_error) @tag_on_rest_failure.each { |tag| event.tag(tag) } else @logger.debug? && @logger.debug('setting fallback', :fallback => @fallback) event.set(@target, @fallback) end end filter_matched(event) end
register()
click to toggle source
# File lib/logstash/filters/rest.rb, line 133 def register @request = normalize_request(@request).deep_freeze @sprintf_fields = find_sprintf( LogStash::Util.deep_clone(@request) ).deep_freeze @sprintf_needed = !@sprintf_fields.empty? @target = normalize_target(@target).freeze end
Private Instance Methods
field_intrpl(intrpl_fields, event)
click to toggle source
# File lib/logstash/filters/rest.rb, line 256 def field_intrpl(intrpl_fields, event) case intrpl_fields when String result = event.sprintf(intrpl_fields) when Array result = [] intrpl_fields.each do |v| result << field_intrpl(v, event) end when Hash result = {} intrpl_fields.each do |k, v| result[k] = field_intrpl(v, event) end else result = intrpl_fields end result end
find_sprintf(config)
click to toggle source
# File lib/logstash/filters/rest.rb, line 198 def find_sprintf(config) field_matcher = /%\{[^}]+\}/ if config.is_a?(Hash) config.keep_if do |_k, v| find_sprintf(v) end.compact elsif config.is_a?(Array) config.keep_if do |v| find_sprintf(v) end.compact elsif config.is_a?(String) && config =~ field_matcher config end end
normalize_request(url_or_spec)
click to toggle source
# File lib/logstash/filters/rest.rb, line 154 def normalize_request(url_or_spec) if url_or_spec.is_a?(String) res = [:get, url_or_spec] elsif url_or_spec.is_a?(Hash) # The client will expect keys / values spec = Hash[url_or_spec.clone.map { |k, v| [k.to_sym, v] }] # method and url aren't really part of the options, so we pull them out method = (spec.delete(:method) || :get).to_sym.downcase url = spec.delete(:url) # if it is a post and json, it is used as body string, not params spec[:body] = spec.delete(:params) if method == :post && spec[:params] # We need these strings to be keywords! spec[:auth] = { user: spec[:auth]['user'], pass: spec[:auth]['password'] } if spec[:auth] res = [method.freeze, url, spec] else raise LogStash::ConfigurationError, "Invalid URL or request spec: '#{url_or_spec}', expected a String or Hash!" end validate_request!(url_or_spec, res) res end
normalize_target(target)
click to toggle source
# File lib/logstash/filters/rest.rb, line 144 def normalize_target(target) # make sure @target is in the format [field name] if defined, # i.e. not empty and surrounded by brakets raise LogStash::ConfigurationError, 'target config string is empty, please set a valid field name' if target.empty? target = "[#{target}]" if target && target !~ /^\[[^\[\]]+\]$/ target end
process_response(response, event)
click to toggle source
# File lib/logstash/filters/rest.rb, line 229 def process_response(response, event) if @json begin parsed = LogStash::Json.load(response) if parsed.empty? @logger.warn('rest response empty', :response => response, :event => event) @tag_on_rest_failure.each { |tag| event.tag(tag) } else event.set(@target, parsed) end rescue if @fallback.empty? @logger.warn('JSON parsing error', :response => response, :event => event) @tag_on_json_failure.each { |tag| event.tag(tag) } else event.set(@target, @fallback) end end else event.set(@target, response.strip) end end
request_http(request)
click to toggle source
# File lib/logstash/filters/rest.rb, line 215 def request_http(request) if request[2].key?(:body) && @json request[2][:body] = LogStash::Json.dump(request[2][:body]) end @logger.debug? && @logger.debug('fetching request', :request => request) method, url, *request_opts = request response = client.http(method, url, *request_opts) [response.code, response.body] end
validate_request!(url_or_spec, request)
click to toggle source
# File lib/logstash/filters/rest.rb, line 182 def validate_request!(url_or_spec, request) method, url, spec = request raise LogStash::ConfigurationError, "No URL provided for request! #{url_or_spec}" unless url raise LogStash::ConfigurationError, "Not supported request method #{method}" unless [ :get, :post ].include?( method ) if spec && spec[:auth] raise LogStash::ConfigurationError, "Auth was specified, but 'user' was not!" unless spec[:auth][:user] raise LogStash::ConfigurationError, "Auth was specified, but 'password' was not!" unless spec[:auth][:pass] end request end