def write_output(output, options = {})
      # First time thru?  We need to do some setup!
      reset_buffered_output if @buffered_output.nil?

      @buffered_output += output

      # If a) we have data to write, and
      #    b) its been > 2 seconds since we last sent
      #
      # The 2 second factor is there to allow slowly accumulating data to be sent out more regularly.
      if !@buffered_output.empty? && (!options[:buffer] || Time.now - @last_write_output > 2)
        # Ensure the output is json-able.
        # It seems some code doesn't wholly respect encoding rules.  We've found some http responses that
        # don't have the correct encoding, despite the response headers stating 'utf-8', etc.  Same goes
        # for shell output streams, that don't seem to respect the apps encoding.
        # What this code does is to try to json encode the @buffered_output.  First a direct conversion,
        # if that fails, try to force-encoding to utf-8, if that fails, try to remove all chars with
        # code > 127.  If that fails - we gave it a good shot, and maybe just insert a 'redacted' string
        # so at least the task doesn't fail :)
        begin
          @buffered_output.to_json
        rescue Exception => e1
          Maestro.log.warn("Unable to 'to_json' output [#{e1}]: #{@buffered_output}")
          begin
            test = @buffered_output
            test.force_encoding('UTF-8')
            test.to_json
            # If forcing encoding worked, updated buffered_output
            Maestro.log.warn("Had to force encoding to utf-8 for workitem stream")
            @buffered_output = test
          rescue Exception
            begin
              test = @buffered_output.gsub(/[^\x00-\x7f]/, '?')
              test.to_json
              # If worked, updated buffered_output
              Maestro.log.warn("Had to strip top-bit-set chars for workitem stream")
              @buffered_output = test
            rescue Exception
              Maestro.log.warn("Had to redact block of output, unable to 'to_json' it for workitem stream")
              @buffered_output = '?_?'
            end
          end
        end

        if !MaestroWorker.mock?
          workitem[OUTPUT_META] = @buffered_output
        else
          # Test mode, we want to retain output - normal operation clears out
          # data after it is sent
          workitem[OUTPUT_META] = '' if !workitem[OUTPUT_META]
          workitem[OUTPUT_META] = workitem[OUTPUT_META] + @buffered_output
        end

        workitem[STREAMING_META] = true
        send_workitem_message
        reset_buffered_output
      end
    rescue Exception => e
      Maestro.log.warn "Unable To Write Output To Server #{e.class} #{e}: #{e.backtrace.join("\n")}"
    ensure
      workitem.delete(STREAMING_META)
    end
def write_output(output, options = {})
      # First time thru?  We need to do some setup!
      reset_buffered_output if @buffered_output.nil?

      @buffered_output += output

      # If a) we have data to write, and
      #    b) its been > 2 seconds since we last sent
      #
      # The 2 second factor is there to allow slowly accumulating data to be sent out more regularly.
      if !@buffered_output.empty? && (!options[:buffer] || Time.now - @last_write_output > 2)
        # Ensure the output is json-able.
        # It seems some code doesn't wholly respect encoding rules.  We've found some http responses that
        # don't have the correct encoding, despite the response headers stating 'utf-8', etc.  Same goes
        # for shell output streams, that don't seem to respect the apps encoding.
        # What this code does is to try to json encode the @buffered_output.  First a direct conversion,
        # if that fails, try to force-encoding to utf-8, if that fails, try to remove all chars with
        # code > 127.  If that fails - we gave it a good shot, and maybe just insert a 'redacted' string
        # so at least the task doesn't fail :)
        begin
          @buffered_output.to_json
        rescue Exception => e1
          Maestro.log.warn("Unable to 'to_json' output [#{e1}]: #{@buffered_output}")
          begin
            test = @buffered_output
            test.force_encoding('UTF-8')
            test.to_json
            # If forcing encoding worked, updated buffered_output
            Maestro.log.warn("Had to force encoding to utf-8 for workitem stream")
            @buffered_output = test
          rescue Exception
            begin
              test = @buffered_output.gsub(/[^\x00-\x7f]/, '?')
              test.to_json
              # If worked, updated buffered_output
              Maestro.log.warn("Had to strip top-bit-set chars for workitem stream")
              @buffered_output = test
            rescue Exception
              Maestro.log.warn("Had to redact block of output, unable to 'to_json' it for workitem stream")
              @buffered_output = '?_?'
            end
          end
        end

        if !MaestroWorker.mock?
          workitem[OUTPUT_META] = @buffered_output
        else
          # Test mode, we want to retain output - normal operation clears out
          # data after it is sent
          workitem[OUTPUT_META] = '' if !workitem[OUTPUT_META]
          workitem[OUTPUT_META] = workitem[OUTPUT_META] + @buffered_output
        end

        workitem[STREAMING_META] = true
        send_workitem_message
        reset_buffered_output
      end
    rescue Exception => e
      Maestro.log.warn "Unable To Write Output To Server #{e.class} #{e}: #{e.backtrace.join("\n")}"
    ensure
      workitem.delete(STREAMING_META)
    end
Sends the specified ouput string to the server for persistence
 If called with :buffer as an option, the output will be queued up until a number of writes has occurred, or
 a reasonable period since the last sent occurred.
 Any call without the :buffer option will cause any buffered output to be sent immediately.

 Example:
   write_output("I am Sam\n")                      <-- send immediately
   write_output("Sam I am\n", :buffer => true)     <-- buffer for later
   write_output("I like Ham\n")                    <-- sends 'Sam I am\nI like Ham\n'