Class: ScoutAgent::WireTap::LogDevice

Inherits:
Object
  • Object
show all
Defined in:
lib/scout_agent/wire_tap.rb

Overview

This Class is used to wrap a device passed to WireTap and then manage interactions with that device. These interactions are handled in a multi-Thread and multi-Process safe way.

WireTap’s LogDevice requires a bigger underlying File-like interface than Logger’s version do to the extra locking and rotation requirements. It skips these steps when the device does not support them though, to make it possible to log to something like $stdout.

Constant Summary collapse

SECONDS_IN_A_DAY =

Used in log rotation calculations.

60 * 60 * 24

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(log = nil, options = Hash.new) ⇒ LogDevice

Wraps log with options, which may include :shift_age and :shift_size. See WireTap::new() for details on these settings.



141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/scout_agent/wire_tap.rb', line 141

def initialize(log = nil, options = Hash.new)
  if log.respond_to?(:write) and log.respond_to?(:close)
    @dev      = log
    @filename = nil
  else
    @dev      = open_log(log)
    @filename = log
  end
  @shift_age  = options[:shift_age]  || 7
  @shift_size = options[:shift_size] || 1048576
  @quiet      = false
  @lock       = Mutex.new
end

Instance Attribute Details

#devObject (readonly)

The underlying device being managed.



156
157
158
# File 'lib/scout_agent/wire_tap.rb', line 156

def dev
  @dev
end

#filenameObject (readonly)

A base name for files created by this device.



158
159
160
# File 'lib/scout_agent/wire_tap.rb', line 158

def filename
  @filename
end

#quiet=(value) ⇒ Object (writeonly)

Set this to true to silence shifting failures. This keeps your logging code from throwning Exceptions due to external forces beyond the control of this object, but it may result in some data loss.



164
165
166
# File 'lib/scout_agent/wire_tap.rb', line 164

def quiet=(value)
  @quiet = value
end

Instance Method Details

#closeObject

Closes the underlying dev in a multi-Thread safe manner.



206
207
208
209
210
# File 'lib/scout_agent/wire_tap.rb', line 206

def close
  @lock.synchronize do
    @dev.close
  end
end

#quiet?Boolean

Returns true if ShiftingError’s will not be thrown.

Returns:

  • (Boolean)


167
168
169
# File 'lib/scout_agent/wire_tap.rb', line 167

def quiet?
  @quiet
end

#write(message) ⇒ Object

Writes message to dev in a multi-Thread and multi-Process safe manner.

Before any write occurs, a check is made to see if the content should be shifted. That process will be trigger, if needed.



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/scout_agent/wire_tap.rb', line 178

def write(message)
  @lock.synchronize do
    not @dev.respond_to?(:flock) or @dev.flock(File::LOCK_EX)
    begin
      begin
        shift_log if @filename and @dev.respond_to?(:stat)
      rescue Exception => error  # shifting failed for whatever reason
        unless @quiet
          raise ShiftingError, "Shifting failed:  #{error.message}"
        end
      end
      begin
        # 
        # make sure we are in the right place, even if the data has been
        # truncated() by another process as part of rotation
        # 
        @dev.seek(0, IO::SEEK_END)
      rescue Errno::ESPIPE  # illegal seek, probably $stdout or $stderr
        # do nothing:  such streams are always at the end
      end
      @dev.write(message)
    ensure
      not @dev.respond_to?(:flock) or @dev.flock(File::LOCK_UN)
    end
  end
end