loggability 0.15.1 → 0.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4dd5d6f5605a1a639a0143107b4079272e35bb7ffba9e2b76b150c1fab57e11f
4
- data.tar.gz: aef9016eb5f208d0d168d8e4aac0b03047851b582f8afcb437b37bb9f9b5ad4d
3
+ metadata.gz: 1b2c4fcb2846387b2e46bb742c60358c79cad2569644325e3db8995bfc4f1367
4
+ data.tar.gz: 8ee45fa6eaf6cfea8d84d8410877bd90053d71a4d692f0a391209d14702430d7
5
5
  SHA512:
6
- metadata.gz: e14c6919279635835bd126a7c878ef69149811640cd4c632022e1677c18abfb3ebadc67fe8a12e9d35e35a94296e2c3ca32614c0c998ed9089b8e9b72d25ec56
7
- data.tar.gz: d2481edb5e1a26dcc7f2a78420831d127b9951dd36e02e898bbd7fded829895083071627d9d78616fbad692937eb05edbdd39456efa0034aae4647cce597c484
6
+ metadata.gz: bcc3cc14f69340ca900ccd458c57e6a85d1b6b895614843ca9427e061f43320ccc7149034091afb0c4ff2bf3ada6a6dcbd05e4f94432224e3bd38b0a6ad1c6b1
7
+ data.tar.gz: c451e216cd87c63794169f0932650f34f78ae99a0eda842497fbef91df1eaf2564500a6160bdf10eb73f81d900cb320f81d4f207e03f0360c8b3df98a92345cb
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -2,6 +2,53 @@
2
2
 
3
3
  ---
4
4
 
5
+ == v0.18.2 [2020-12-28] Michael Granger <ged@faeriemud.org>
6
+
7
+ Improvements:
8
+
9
+ - Make the version spec even less specific.
10
+
11
+
12
+ == v0.18.1 [2020-12-28] Michael Granger <ged@faeriemud.org>
13
+
14
+ Improvements:
15
+
16
+ - Change version spec to work with Ruby 3 versions.
17
+
18
+
19
+ == v0.18.0 [2020-12-24] Michael Granger <ged@faeriemud.org>
20
+
21
+ Improvements:
22
+
23
+ - Add memory management to the http log device
24
+ - Add a dead-simple log server example
25
+ - Update for Ruby 3, add my updated gem cert
26
+
27
+ Thanks again to Mahmood Khan <mkhan1484@gmail.com> for the patch.
28
+
29
+
30
+ == v0.17.0 [2020-02-27] Michael Granger <ged@faeriemud.org>
31
+
32
+ Bugfixes:
33
+
34
+ - Fix the construction of the client in the http log device
35
+
36
+ Improvements:
37
+
38
+ - Add support for log devices to the aggregate #output_to
39
+
40
+
41
+
42
+ == v0.16.0 [2020-02-24] Michael Granger <ged@faeriemud.org>
43
+
44
+ Improvements:
45
+
46
+ - Expose a "log device" API and add the ability to write to multiple devices
47
+ - Add a device for logging to an HTTP service
48
+
49
+ Thanks to Mahmood Khan <mkhan1484@gmail.com> for the patch.
50
+
51
+
5
52
  == v0.15.1 [2020-01-09] Michael Granger <ged@faeriemud.org>
6
53
 
7
54
  Bugfixes:
@@ -1,9 +1,5 @@
1
1
  .simplecov
2
- ChangeLog
3
2
  History.rdoc
4
- Manifest.txt
5
- README.md
6
- Rakefile
7
3
  lib/loggability.rb
8
4
  lib/loggability/constants.rb
9
5
  lib/loggability/formatter.rb
@@ -14,8 +10,16 @@ lib/loggability/formatter/structured.rb
14
10
  lib/loggability/logclient.rb
15
11
  lib/loggability/logger.rb
16
12
  lib/loggability/loghost.rb
13
+ lib/loggability/log_device.rb
14
+ lib/loggability/log_device/appending.rb
15
+ lib/loggability/log_device/datadog.rb
16
+ lib/loggability/log_device/file.rb
17
+ lib/loggability/log_device/http.rb
17
18
  lib/loggability/override.rb
18
19
  lib/loggability/spechelpers.rb
20
+ Manifest.txt
21
+ Rakefile
22
+ README.md
19
23
  spec/helpers.rb
20
24
  spec/loggability/formatter/color_spec.rb
21
25
  spec/loggability/formatter/default_spec.rb
@@ -24,6 +28,10 @@ spec/loggability/formatter/structured_spec.rb
24
28
  spec/loggability/formatter_spec.rb
25
29
  spec/loggability/logger_spec.rb
26
30
  spec/loggability/loghost_spec.rb
31
+ spec/loggability/log_device/appending_spec.rb
32
+ spec/loggability/log_device/datadog_spec.rb
33
+ spec/loggability/log_device/file_spec.rb
34
+ spec/loggability/log_device/http_spec.rb
27
35
  spec/loggability/override_spec.rb
28
36
  spec/loggability/spechelpers_spec.rb
29
37
  spec/loggability_spec.rb
data/Rakefile CHANGED
@@ -3,7 +3,7 @@
3
3
  require 'rake/deveiate'
4
4
 
5
5
  Rake::DevEiate.setup( 'loggability' ) do |project|
6
- project.required_ruby_version = '~> 2.5'
6
+ project.required_ruby_version = ['>= 2.5']
7
7
  project.publish_to = 'deveiate:/usr/local/www/public/code'
8
8
  end
9
9
 
@@ -9,7 +9,7 @@ require 'date'
9
9
  module Loggability
10
10
 
11
11
  # Package version constant
12
- VERSION = '0.15.1'
12
+ VERSION = '0.18.2'
13
13
 
14
14
  # The key for the global logger (Loggability's own logger)
15
15
  GLOBAL_KEY = :__global__
@@ -29,7 +29,7 @@ module Loggability
29
29
  (?<severity>(?i:debug|info|warn|error|fatal))
30
30
  (?:
31
31
  \s+
32
- (?<target>(?:[\w\-/:\.]|\\[ ])+)
32
+ (?<target>(?:[\w\-/:\.\[\]]|\\[ ])+)
33
33
  )?
34
34
  (?: \s+\(
35
35
  (?<format>\w+)
@@ -38,10 +38,16 @@ module Loggability
38
38
  $
39
39
  }x
40
40
 
41
- require 'loggability/constants'
42
- include Loggability::Constants
43
41
 
44
- require 'loggability/logger'
42
+ # Automatically load subordinate classes/modules
43
+ autoload :Constants, 'loggability/constants'
44
+ autoload :LogDevice, 'loggability/log_device'
45
+ autoload :Logger, 'loggability/logger'
46
+ autoload :LogHost, 'loggability/loghost'
47
+ autoload :LogClient, 'loggability/logclient'
48
+ autoload :Override, 'loggability/override'
49
+
50
+ include Loggability::Constants
45
51
 
46
52
 
47
53
  ##
@@ -55,10 +61,6 @@ module Loggability
55
61
  @config = CONFIG_DEFAULTS.dup.freeze
56
62
 
57
63
 
58
- # Automatically log the log host and log client mixins when they're referenced
59
- autoload :LogHost, 'loggability/loghost'
60
- autoload :LogClient, 'loggability/logclient'
61
- autoload :Override, 'loggability/override'
62
64
 
63
65
 
64
66
  ### Cast the given +device+ to a Loggability::Logger, if possible, and return it. If
@@ -144,12 +146,12 @@ module Loggability
144
146
 
145
147
  ### Call the method with the given +methodname+ across the loggers of all loghosts with
146
148
  ### the given +arg+ and/or +block+.
147
- def self::aggregate( methodname, arg, &block )
149
+ def self::aggregate( methodname, *args, &block )
148
150
  # self.log.debug "Aggregating a call to %p with %p to %d log hosts" %
149
151
  # [ methodname, arg, Loggability.log_hosts.length ]
150
152
  Loggability.log_hosts.values.each do |loghost|
151
153
  # self.log.debug " %p.logger.%s( %p )" % [ loghost, methodname, arg ]
152
- loghost.logger.send( methodname, arg, &block )
154
+ loghost.logger.send( methodname, *args, &block )
153
155
  end
154
156
  end
155
157
 
@@ -189,8 +191,8 @@ module Loggability
189
191
  #
190
192
  # Aggregate method: set all loggers to log to +destination+. See Loggability::Logger#output_to
191
193
  # for more info.
192
- def self::output_to( newdevice )
193
- self.aggregate( :output_to, newdevice )
194
+ def self::output_to( newdevice, *args )
195
+ self.aggregate( :output_to, newdevice, *args )
194
196
  end
195
197
  class << self
196
198
  alias_method :write_to, :output_to
@@ -321,6 +323,7 @@ module Loggability
321
323
  target = case target
322
324
  when 'STDOUT' then $stdout
323
325
  when 'STDERR' then $stderr
326
+ when /:/ then Loggability::LogDevice.parse_device_spec( target )
324
327
  else
325
328
  target
326
329
  end
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
4
+
5
+ require 'loggability' unless defined?( Loggability )
6
+
7
+
8
+ # An abstract base class for logging devices. A device manages the actual writing of messages
9
+ # to whatever destination logs are supposed to be shipped to, along with any buffering,
10
+ # encoding, or serialization that needs to be done.
11
+ #
12
+ # Log devices are loadable by name via the ::create method if they are declared in a
13
+ # directory named `loggability/log_device/` in the gem path.
14
+ #
15
+ # Concrete log devices are required to implement two methods: #write and #close.
16
+ #
17
+ # [write]
18
+ # Takes one argument, which is the message that needs to be written.
19
+ #
20
+ # [close]
21
+ # Close any open filehandles or connections established by the device.
22
+ class Loggability::LogDevice
23
+
24
+
25
+ # Regexp used to split up logging devices in config lines
26
+ DEVICE_TARGET_REGEX = /^([\s*a-z]\w*)(?:\[(.*)\])?/
27
+
28
+
29
+ ### Parses out the target class name and its arguments from the +target_spec+
30
+ ### then requires the subclass and instantiates it by passing the arguments.
31
+ ### The +target_spec+ comes from a config file in the format of:
32
+ ###
33
+ ### logging:
34
+ ### datadog[data_dog_api_key]
35
+ ###
36
+ ### In the above example:
37
+ ### * "datadog" is the log device to send logs to
38
+ ### * "data_dog_api_key" is the argument that will be passed onto the datadog
39
+ ### log device's constructor
40
+ def self::parse_device_spec( target_spec )
41
+ targets = target_spec.split( ';' ).compact
42
+ return targets.map do |t|
43
+ target_subclass = t[ DEVICE_TARGET_REGEX, 1 ]&.strip.to_sym
44
+ target_subclass_args = t[ DEVICE_TARGET_REGEX, 2 ]
45
+
46
+ self.create( target_subclass, target_subclass_args )
47
+ end
48
+ end
49
+
50
+
51
+ ### Requires the subclass and instantiates it with the passed-in arguments and
52
+ ### then returns an instance of it.
53
+ def self::create( target, *target_args )
54
+ modname = target.to_s.capitalize
55
+
56
+ self.load_device_type( target ) unless self.const_defined?( modname, false )
57
+ subclass = self.const_get( modname, false )
58
+
59
+ return subclass.new( *target_args )
60
+ rescue NameError => err
61
+ raise LoadError, "failed to load %s LogDevice: %s" % [ target, err.message ]
62
+ end
63
+
64
+
65
+ ### Attempt to load a LogDevice of the given +type+.
66
+ def self::load_device_type( type )
67
+ require_path = "loggability/log_device/%s" % [ type.to_s.downcase ]
68
+ require( require_path )
69
+ end
70
+
71
+
72
+ ### Write a +message+ to the device. This needs to be overridden by concrete
73
+ ### subclasses; calling this implementation will raise an NotImplementedError.
74
+ def write( message )
75
+ raise NotImplementedError, "%s is not implemented by %s" % [ __callee__, self.class.name ]
76
+ end
77
+
78
+
79
+ ### Close the device. This needs to be overridden by concrete subclasses;
80
+ ### calling this implementation will raise an NotImplementedError.
81
+ def close
82
+ raise NotImplementedError, "%s is not implemented by %s" % [ __callee__, self.class.name ]
83
+ end
84
+
85
+ end # class Loggability::LogDevice
86
+
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
4
+
5
+ require 'loggability/logger' unless defined?( Loggability::Logger )
6
+
7
+ # A log device that appends to the object it's constructed with instead of writing
8
+ # to a file descriptor or a file.
9
+ class Loggability::LogDevice::Appending < Loggability::LogDevice
10
+
11
+ ### Create a new +Appending+ log device that will append content to +array+.
12
+ def initialize( target )
13
+ @target = target || []
14
+ end
15
+
16
+
17
+ ######
18
+ public
19
+ ######
20
+
21
+ # The target of the log device
22
+ attr_reader :target
23
+
24
+
25
+ ### Append the specified +message+ to the target.
26
+ def write( message )
27
+ @target << message
28
+ end
29
+
30
+
31
+ ### No-op -- this is here just so Logger doesn't complain
32
+ def close; end
33
+
34
+ end # class Loggability::LogDevice::Appending
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
4
+
5
+ require 'uri'
6
+ require 'socket'
7
+ require 'net/https'
8
+ require 'json'
9
+ require 'concurrent'
10
+ require 'loggability/logger' unless defined?( Loggability::Logger )
11
+
12
+ require 'loggability/log_device/http'
13
+
14
+
15
+ # A log device that sends logs to Datadog's HTTP endpoint
16
+ # for receiving logs
17
+ class Loggability::LogDevice::Datadog < Loggability::LogDevice::Http
18
+
19
+ ### Datadog's HTTP endpoint URL for sending logs to
20
+ DEFAULT_ENDPOINT = URI( "https://http-intake.logs.datadoghq.com/v1/input" )
21
+
22
+ ### The max number of messages that can be sent to datadog in a single payload
23
+ MAX_BATCH_SIZE = 480
24
+
25
+ ### The max size in bytes for a single message.
26
+ ### Limiting the message size to 200kB to leave room for other info such as
27
+ ### tags, metadata, etc.
28
+ ### DataDog's max size for a single log entry is 256kB
29
+ MAX_MESSAGE_BYTESIZE = 204_800
30
+
31
+ ### The max size in bytes of all messages in the batch.
32
+ ### Limiting the total messages size to 4MB to leave room for other info such as
33
+ ### tags, metadata, etc.
34
+ ### Datadog's max size for the entire payload is 5MB
35
+ MAX_BATCH_BYTESIZE = 4_194_304
36
+
37
+ # Override the default HTTP device options for sending logs to DD
38
+ DEFAULT_OPTIONS = {
39
+ max_batch_size: MAX_BATCH_SIZE,
40
+ max_message_bytesize: MAX_MESSAGE_BYTESIZE,
41
+ max_batch_bytesize: MAX_BATCH_BYTESIZE,
42
+ }
43
+
44
+
45
+ ### Create a new Datadog
46
+ def initialize( api_key, endpoint=DEFAULT_ENDPOINT, options={} )
47
+ if endpoint.is_a?( Hash )
48
+ options = endpoint
49
+ endpoint = DEFAULT_ENDPOINT
50
+ end
51
+
52
+ super( endpoint, options )
53
+
54
+ @api_key = api_key
55
+ @hostname = Socket.gethostname
56
+ end
57
+
58
+
59
+ ######
60
+ public
61
+ ######
62
+
63
+ ##
64
+ # The name of the current host
65
+ attr_reader :hostname
66
+
67
+ ##
68
+ # The configured Datadog API key
69
+ attr_reader :api_key
70
+
71
+
72
+ ### Format an individual log +message+ for Datadog.
73
+ def format_log_message( message )
74
+ return {
75
+ hostname: self.hostname,
76
+ message: message
77
+ }.to_json
78
+ end
79
+
80
+
81
+ ### Overridden to add the configured API key to the headers of each request.
82
+ def make_batch_request
83
+ request = super
84
+
85
+ request[ 'DD-API-KEY' ] = self.api_key
86
+
87
+ return request
88
+ end
89
+
90
+ end # class Loggability::LogDevice::Datadog
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set nosta noet ts=4 sw=4:
3
+ # encoding: utf-8
4
+
5
+ require 'logger'
6
+ require 'loggability/logger' unless defined?( Loggability::Logger )
7
+
8
+ # A log device that delegates to the ruby's default Logger's file device and writes
9
+ # to a file descriptor or a file.
10
+ class Loggability::LogDevice::File < Loggability::LogDevice
11
+
12
+ ### Create a new +File+ device that will write to the file using the built-in ruby's +File+ log device
13
+ def initialize( target )
14
+ @target = ::Logger::LogDevice.new( target )
15
+ end
16
+
17
+
18
+ ######
19
+ public
20
+ ######
21
+
22
+ # The target of the log device
23
+ attr_reader :target
24
+
25
+
26
+ ### Append the specified +message+ to the target.
27
+ def write( message )
28
+ self.target.write( message )
29
+ end
30
+
31
+
32
+ ### close the file
33
+ def close
34
+ self.target.close
35
+ end
36
+
37
+ end # class Loggability::LogDevice::File