class LogStash::Filters::Xml
XML filter. Takes a field that contains XML and expands it into an actual datastructure.
Constants
- XMLPARSEFAILURE_TAG
Public Instance Methods
filter(event)
click to toggle source
# File lib/logstash/filters/xml.rb, line 124 def filter(event) matched = false @logger.debug? && @logger.debug("Running xml filter", :event => event) value = event.get(@source) return unless value if value.is_a?(Array) if value.length != 1 event.tag(XMLPARSEFAILURE_TAG) @logger.warn("XML filter expects single item array", :source => @source, :value => value) return end value = value.first end unless value.is_a?(String) event.tag(XMLPARSEFAILURE_TAG) @logger.warn("XML filter expects a string but received a #{value.class}", :source => @source, :value => value) return end # Do nothing with an empty string. return if value.strip.empty? if @xpath begin doc = Nokogiri::XML::Document.parse(value, nil, value.encoding.to_s, xml_parse_options) rescue => e event.tag(XMLPARSEFAILURE_TAG) @logger.warn("Error parsing xml", :source => @source, :value => value, :exception => e, :backtrace => e.backtrace) return else doc.errors.any? && @logger.debug? && @logger.debug("Parsed xml with #{doc.errors.size} errors") end doc.remove_namespaces! if @remove_namespaces @xpath.each do |xpath_src, xpath_dest| nodeset = @namespaces.empty? ? doc.xpath(xpath_src) : doc.xpath(xpath_src, @namespaces) # If asking xpath for a String, like "name(/*)", we get back a # String instead of a NodeSet. We normalize that here. normalized_nodeset = nodeset.kind_of?(Nokogiri::XML::NodeSet) ? nodeset : [nodeset] # Initialize empty resultset data = [] normalized_nodeset.each do |value| # some XPath functions return empty arrays as string next if value.is_a?(Array) && value.length == 0 if value matched = true data << value.to_s end end # set the destination attribute, if it's an array with a bigger size than one, leave as is. otherwise make it a string. added force_array param to provide same functionality as writing it in an xml target if data.size == 1 && !@force_array event.set(xpath_dest, data[0]) else event.set(xpath_dest, data) unless data.nil? || data.empty? end end end if @store_xml begin xml_options = {"ForceArray" => @force_array, "ForceContent" => @force_content} xml_options["SuppressEmpty"] = true if @suppress_empty event.set(@target, XmlSimple.xml_in(value, xml_options)) matched = true rescue => e event.tag(XMLPARSEFAILURE_TAG) @logger.warn("Error parsing xml with XmlSimple", :source => @source, :value => value, :exception => e, :backtrace => e.backtrace) return end end filter_matched(event) if matched @logger.debug? && @logger.debug("Event after xml filter", :event => event) rescue => e event.tag(XMLPARSEFAILURE_TAG) log_payload = { :exception => e.message, :source => @source } log_payload[:value] = value unless value.nil? log_payload[:backtrace] = e.backtrace if @logger.debug? @logger.warn("XML Parse Error", log_payload) end
register()
click to toggle source
# File lib/logstash/filters/xml.rb, line 109 def register require "nokogiri" require "xmlsimple" if @store_xml && (!@target || @target.empty?) raise LogStash::ConfigurationError, I18n.t( "logstash.runner.configuration.invalid_plugin_register", :plugin => "filter", :type => "xml", :error => "When the 'store_xml' configuration option is true, 'target' must also be set" ) end xml_parse_options # validates parse_options => ... end
Private Instance Methods
xml_parse_options()
click to toggle source
# File lib/logstash/filters/xml.rb, line 219 def xml_parse_options return Nokogiri::XML::ParseOptions::DEFAULT_XML unless @parse_options # (RECOVER | NONET) @xml_parse_options ||= begin parse_options = @parse_options.split(/,|\|/).map do |opt| name = opt.strip.tr('_', '').upcase if name.empty? nil else begin Nokogiri::XML::ParseOptions.const_get(name) rescue NameError raise LogStash::ConfigurationError, "unsupported parse option: #{opt.inspect}" end end end parse_options.compact.inject(0, :|) # e.g. NOERROR | NOWARNING end end