Class: Splunk::ResultsReader

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/splunk-sdk-ruby/resultsreader.rb

Overview

ResultsReader parses Splunk’s XML format for results into Ruby objects.

You can use both Nokogiri and REXML. By default, the ResultsReader will try to use Nokogiri, and if it is not available will fall back to REXML. If you want other behavior, see xml_shim.rb for how to set the XML library.

+ResultsReader is an Enumerable, so it has methods such as each and each_with_index. However, since it’s a stream parser, once you iterate through it once, it will thereafter be empty.

Do not use ResultsReader with the results of the create_export or create_stream methods on Service or Jobs. These methods use endpoints which return a different set of data structures. Use MultiResultsReader instead for those cases. If you do use ResultsReader, it will return a concatenation of all non-preview events in the stream, but that behavior should be considered deprecated, and will result in a warning.

The ResultsReader object has two additional methods:

  • is_preview? returns a Boolean value that indicates whether these results are a preview from an unfinished search or not

  • fields returns an array of all the fields that may appear in a result in this set, in the order they should be displayed (if you’re going to make a table or the like)

The values yielded by calling each and similar methods on ResultsReader are of class Event, which is a subclass of Hash with one extra method, segmented_raw. The fields of the event are available as values in the hash, with no escaped characters and no XML tags. The _raw field, however, is returned with extra XML specifying how terms should be highlighted for display, and this full XML form is available by called the segmented_raw method. The XML returned looks something like:

"<v xml:space=\"preserve\" trunc=\"0\">127.0.0.1 - admin
[11/Feb/2013:10:42:49.790 -0800] \"POST /services/search/jobs/export
HTTP/1.1\" 200 440404 - - - 257ms</v>"

Example:

require 'splunk-sdk-ruby'

service = Splunk::connect(:username => "admin", :password => "changeme")

stream = service.jobs.create_oneshot("search index=_internal | head 10")
reader = Splunk::ResultsReader.new(stream)
puts reader.is_preview?
# Prints: false
reader.each do |result|
  puts result # Prints the fields in the result as a Hash
  puts result.segmented_raw() # Prints the XML version of the _raw field
end
# Prints a sequence of Hashes containing events.

Direct Known Subclasses

PuppetResultsReader

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(text_or_stream) ⇒ ResultsReader

Returns a new instance of ResultsReader.



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/splunk-sdk-ruby/resultsreader.rb', line 150

def initialize(text_or_stream)
  if text_or_stream.nil?
    stream = StringIO.new("")
  elsif text_or_stream.is_a?(ExportStream)
    # The sensible behavior on streams from the export endpoints is to
    # skip all preview results and concatenate all others. The export
    # functions wrap their streams in ExportStream to mark that they need
    # this special handling.
    @is_export = true
    @reader = MultiResultsReader.new(text_or_stream).final_results()
    @is_preview = @reader.is_preview?
    @fields = @reader.fields
    return
  elsif !text_or_stream.respond_to?(:read)
    # Strip because the XML libraries can be pissy.
    stream = StringIO.new(text_or_stream.strip)
  else
    stream = text_or_stream
  end

  if !stream.nil? and stream.eof?
    @is_preview = nil
    @fields = []
  else
    # We use a SAX parser. +listener+ is the event handler, but a SAX
    # parser won't usually transfer control during parsing. 
    # To incrementally return results as we parse, we have to put
    # the parser into a +Fiber+ from which we can yield.
    listener = ResultsListener.new()
    @iteration_fiber = Fiber.new do
      if $splunk_xml_library == :nokogiri
        parser = Nokogiri::XML::SAX::Parser.new(listener)
        parser.parse(stream)
      else # Use REXML
        REXML::Document.parse_stream(stream, listener)
      end
    end

    @is_preview = @iteration_fiber.resume
    @fields = @iteration_fiber.resume
    @reached_end = false
  end
end

Instance Attribute Details

#fieldsObject (readonly)

An Array of all the fields that may appear in each result.

Note that any given result will contain a subset of these fields.

Returns: an Array of Strings.



148
149
150
# File 'lib/splunk-sdk-ruby/resultsreader.rb', line 148

def fields
  @fields
end

Instance Method Details

#eachObject



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/splunk-sdk-ruby/resultsreader.rb', line 194

def each()
  # If we have been passed a stream from an export endpoint, it should be
  # marked as such, and we handle it differently.
  if @is_export
    warn "[DEPRECATED] Do not use ResultsReader on the output of the " +
             "export endpoint. Use MultiResultsReader instead."
    enum = @reader.each()
  else
    enum = Enumerator.new() do |yielder|
      if !@iteration_fiber.nil? # Handle the case of empty files
        @reached_end = false
        while true
          result = @iteration_fiber.resume
          break if result.nil? or result == :end_of_results_set
          yielder << result
        end
      end
      @reached_end = true
    end
  end

  if block_given? # Apply the enumerator to a block if we have one
    enum.each() { |e| yield e }
  else
    enum # Otherwise return the enumerator itself
  end
end

#is_preview?Boolean

Are the results in this reader a preview from an unfinished search?

Returns: true or false, or nil if the stream is empty.

Returns:

  • (Boolean)


137
138
139
# File 'lib/splunk-sdk-ruby/resultsreader.rb', line 137

def is_preview?
  return @is_preview
end

#skip_remaining_resultsObject

Skips the rest of the events in this ResultsReader.



225
226
227
228
229
# File 'lib/splunk-sdk-ruby/resultsreader.rb', line 225

def skip_remaining_results()
  if !@reached_end
    each() { |result|}
  end
end