loggability 0.15.1 → 0.18.2

Sign up to get free protection for your applications and to get access to all the features.
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