Class: Loggability::LogDevice

Inherits:
Object
  • Object
show all
Defined in:
lib/loggability/log_device.rb

Overview

An abstract base class for logging devices. A device manages the actual writing of messages to whatever destination logs are supposed to be shipped to, along with any buffering, encoding, or serialization that needs to be done.

Log devices are loadable by name via the ::create method if they are declared in a directory named ‘loggability/log_device/` in the gem path.

Concrete log devices are required to implement two methods: #write and #close.

write

Takes one argument, which is the message that needs to be written.

close

Close any open filehandles or connections established by the device.

Direct Known Subclasses

Appending, File, Http

Defined Under Namespace

Classes: Appending, Datadog, File, Http

Constant Summary collapse

DEVICE_TARGET_REGEX =

Regexp used to split up logging devices in config lines

/^([\s*a-z]\w*)(?:\[(.*)\])?/

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.create(target, *target_args) ⇒ Object

Requires the subclass and instantiates it with the passed-in arguments and then returns an instance of it.



53
54
55
56
57
58
59
60
61
62
# File 'lib/loggability/log_device.rb', line 53

def self::create( target, *target_args )
  modname = target.to_s.capitalize

  self.load_device_type( target ) unless self.const_defined?( modname, false )
  subclass = self.const_get( modname, false )

  return subclass.new( *target_args )
rescue NameError => err
  raise LoadError, "failed to load %s LogDevice: %s" % [ target, err.message ]
end

.load_device_type(type) ⇒ Object

Attempt to load a LogDevice of the given type.



66
67
68
69
# File 'lib/loggability/log_device.rb', line 66

def self::load_device_type( type )
  require_path = "loggability/log_device/%s" % [ type.to_s.downcase ]
  require( require_path )
end

.parse_device_spec(target_spec) ⇒ Object

Parses out the target class name and its arguments from the target_spec then requires the subclass and instantiates it by passing the arguments. The target_spec comes from a config file in the format of:

logging:
  datadog[data_dog_api_key]

In the above example:

  • “datadog” is the log device to send logs to

  • “data_dog_api_key” is the argument that will be passed onto the datadog log device’s constructor



40
41
42
43
44
45
46
47
48
# File 'lib/loggability/log_device.rb', line 40

def self::parse_device_spec( target_spec )
  targets = target_spec.split( ';' ).compact
  return targets.map do |t|
    target_subclass = t[ DEVICE_TARGET_REGEX, 1 ]&.strip.to_sym
    target_subclass_args = t[ DEVICE_TARGET_REGEX, 2 ]

    self.create( target_subclass, target_subclass_args )
  end
end

Instance Method Details

#closeObject

Close the device. This needs to be overridden by concrete subclasses; calling this implementation will raise an NotImplementedError.

Raises:

  • (NotImplementedError)


81
82
83
# File 'lib/loggability/log_device.rb', line 81

def close
  raise NotImplementedError, "%s is not implemented by %s" % [ __callee__, self.class.name ]
end

#write(message) ⇒ Object

Write a message to the device. This needs to be overridden by concrete subclasses; calling this implementation will raise an NotImplementedError.

Raises:

  • (NotImplementedError)


74
75
76
# File 'lib/loggability/log_device.rb', line 74

def write( message )
  raise NotImplementedError, "%s is not implemented by %s" % [ __callee__, self.class.name ]
end