hubbado-log 1.4.1 → 1.5.0

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: 99367c1895c07697aa0e83dc1e068f35cf2052d75dc6c471610b47099f27fd7f
4
- data.tar.gz: 58a148cfa36ea3709a2c36fbb228f089d3b176476d27ede4a74ec26a651bdf12
3
+ metadata.gz: 84cb20198caa8a5346b0a4d50c702b57e77f53cedc2f90e221c05a90985260a0
4
+ data.tar.gz: 1134a1d43db622684732e5550d76716c8be4dcb5ee0e23382c8aaaedf0743851
5
5
  SHA512:
6
- metadata.gz: 5a53b16af1babaa5c90125bfddec34a02c5256661004833a63b5b54066a914bf764d2c3c738d0a0d2e556d4bd9ef86d96d7e40419e7acd810f2fb7ca4fe58788
7
- data.tar.gz: 6f77c77d30c8a1ef7f89b2b73c8e09585aa3f39d6dd5d9046796220f699f2926c31debd5fb5b8f514e06c7a2fb66e2b5e20be6cf7f86b95e56bba6218a2ef5e5
6
+ metadata.gz: ac99e3a37b28025006034cd5032a350db0c3e0bf63ee1c504c4af81a589879a5d1e3dd72180592b5d1632471b0f00efe9353cc5dfc6f1b040bf6855370a1f537
7
+ data.tar.gz: 97fe613dccb476915983d4836ae3736e3fae54168872b20106a71da9e1ec70c40994a7ba79d2931f8fdfc5dd4b36defdc55bf52823de6194b2e552c2ff84f49c
data/ChangeLog.md CHANGED
@@ -4,6 +4,57 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ # [1.5.0 - 2026-08-16]
8
+ ## Added
9
+ - Three handlers, replacing eight hand-rolled copies across four projects and
10
+ two applications. Each is behind its own require; `require "hubbado/log"`
11
+ loads none of them.
12
+
13
+ ```ruby
14
+ require "hubbado/log/stderr_logger"
15
+ require "hubbado/log/notify_rollbar"
16
+
17
+ Hubbado::Log.configuration do |config|
18
+ config.loggers = [Hubbado::Log::StderrLogger, Hubbado::Log::NotifyRollbar]
19
+ end
20
+ ```
21
+
22
+ | Handler | Writes to | Needs |
23
+ |---|---|---|
24
+ | `StderrLogger` | `$stderr` | nothing |
25
+ | `RailsLogger` | `Rails.logger` | Rails, already loaded wherever a handler is registered |
26
+ | `NotifyRollbar` | `Rollbar` | `rollbar` in the consumer's own Gemfile |
27
+
28
+ Neither Rails nor Rollbar is a dependency of this gem, so installing it
29
+ installs neither. `notify_rollbar` requires `rollbar` at the top of the file,
30
+ making an absent gem a `LoadError` at boot rather than a `NameError` raised
31
+ while a failure is being reported.
32
+
33
+ Every copy discarded the `stacktrace` argument, and the Rollbar ones
34
+ discarded more:
35
+
36
+ | | Was | Is now |
37
+ |---|---|---|
38
+ | `StderrLogger`, an `error` carrying no exception | no stacktrace | prints it. A `warn` stays one line, and an exception's backtrace is never printed twice |
39
+ | `RailsLogger`, a `trace` line | `NoMethodError` in one of the two copies | written as `debug` |
40
+ | `NotifyRollbar`, the subject | dropped | a `subject` key, merged last so a line cannot claim another class |
41
+ | `NotifyRollbar`, a stacktrace with no exception | dropped | a `stacktrace` key |
42
+ | `NotifyRollbar`, data that is not a hash or exception | dropped | a `data` key holding its `inspect` |
43
+
44
+ Rollbar keeps the last hash it is handed and ignores anything that is not a
45
+ String, an Exception or a Hash, so `NotifyRollbar` merges everything into one
46
+ hash — built fresh per call, because Rollbar deletes a key from the hash it
47
+ is given.
48
+
49
+ - Controls for what a handler spec stands in for: `Controls::Rollbar`,
50
+ `Controls::RailsLogger`, `Controls::Receiver` and `Controls::Stacktrace`.
51
+
52
+ `Controls::Rollbar` reads a notification back the way Rollbar reads its
53
+ arguments, keeping the last hash — so a handler sending two would pass
54
+ against a merging control and lose data against the real thing.
55
+ `Controls::RailsLogger` does not answer to `trace`, so a handler passing it
56
+ straight through raises here as it would in Rails.
57
+
7
58
  # [1.4.1 - 2026-08-16]
8
59
  ## Fixed
9
60
  - A subclass of `Hubbado::Log` can be used as a dependency. It answered `nil`
data/README.md CHANGED
@@ -48,13 +48,143 @@ end
48
48
  Either way the logger writes through the handlers the process was configured with, at the level
49
49
  and tags it was configured for.
50
50
 
51
+ ## Handlers
52
+
53
+ A handler is what a log line is finally written *to*. The process names them, and the log system
54
+ builds each one itself with no arguments:
55
+
56
+ ```ruby
57
+ Hubbado::Log.configuration do |config|
58
+ config.loggers = [Hubbado::Log::StderrLogger]
59
+ end
60
+ ```
61
+
62
+ Handlers mostly belong to the application rather than to this gem, because what they write to is
63
+ the application's — a Rails logger, a Rollbar token. Write one by subclassing
64
+ `Hubbado::Log::LogHandler` and implementing `log`:
65
+
66
+ ```ruby
67
+ class MyHandler < Hubbado::Log::LogHandler
68
+ def log(subject, severity, message, data = nil, stacktrace = nil)
69
+ ...
70
+ end
71
+ end
72
+ ```
73
+
74
+ `data` is whatever the call site passed as the second argument, and is an `Exception` when it
75
+ logged one. `stacktrace` is the exception's `full_message` in that case, and otherwise the caller
76
+ stack, synthesised for `warn`, `error`, `fatal` and `unknown` only.
77
+
78
+ ### `Hubbado::Log::StderrLogger`
79
+
80
+ For a command-line tool, where the log is a person watching a run. It is not loaded by
81
+ `require 'hubbado/log'` — ask for it:
82
+
83
+ ```ruby
84
+ require 'hubbado/log/stderr_logger'
85
+ ```
86
+
87
+ It prints the severity, the subject and the message on one line, and anything the line carried
88
+ below it:
89
+
90
+ WARN Scanning::Sweep: rec_1 skipped, no rate
91
+ ERROR Scanning::Sweep: rec_2 refused
92
+ /app/lib/scanning/sweep.rb:41:in 'post': HTTP 400 (RequestError)
93
+ from /app/lib/scanning/sweep.rb:12:in 'call'
94
+
95
+ A stacktrace prints at `error` and above, and only when the data is not an exception — an
96
+ exception already prints its own backtrace, so honouring both would print it twice. A `warn`
97
+ stays one line: it is a condition to examine rather than a failure to trace, and a sweep that
98
+ warns per row would otherwise bury itself in Ruby stack.
99
+
100
+ Pass `io:` to write somewhere else, which is mainly how a spec reads it back:
101
+
102
+ ```ruby
103
+ Hubbado::Log::StderrLogger.new(io: StringIO.new)
104
+ ```
105
+
106
+ ### `Hubbado::Log::RailsLogger`
107
+
108
+ Writes into a Rails application's own log.
109
+
110
+ ```ruby
111
+ require "hubbado/log/rails_logger"
112
+
113
+ Hubbado::Log.configuration do |config|
114
+ config.loggers = [Hubbado::Log::RailsLogger]
115
+ end
116
+ ```
117
+
118
+ Rails is not a dependency of this gem. The constant is read lazily, and the only place a handler
119
+ is ever registered is an environment file, where Rails is loaded by definition.
120
+
121
+ The subject and message go on one line, and the data and stacktrace on lines below it, all at the
122
+ severity of the line. An exception is one line rather than two — its backtrace already carries the
123
+ message that its `inspect` would repeat. `trace` is written as `debug`, because Rails' logger has
124
+ no method below it, and a handler passing `trace` straight through raises `NoMethodError` on the
125
+ first trace line it is handed.
126
+
127
+ Unlike the stderr handler, the stacktrace is written at every severity. A Rails log is read after
128
+ the fact, and by machine as often as by a person, so there is nothing to keep readable by
129
+ withholding frames.
130
+
131
+ Pass `rails_logger:` to write somewhere else, which is mainly how a spec reads it back. Left
132
+ unset, `Rails.logger` is read on every line rather than held, so a handler built before Rails
133
+ replaced its logger still writes to the current one.
134
+
135
+ ### `Hubbado::Log::NotifyRollbar`
136
+
137
+ Forwards a line worth an incident to Rollbar: `warn` as a warning, `error`, `fatal` and
138
+ `unknown` as errors, and anything below a warning not at all.
139
+
140
+ **Rollbar is not a dependency of this gem.** It is a development dependency, so nothing about
141
+ installing `hubbado-log` installs Rollbar. A consumer that wants this handler puts `rollbar` in
142
+ its own Gemfile and requires the handler itself:
143
+
144
+ ```ruby
145
+ require "hubbado/log/notify_rollbar"
146
+
147
+ Hubbado::Log.configuration do |config|
148
+ config.loggers = [Hubbado::Log::StderrLogger, Hubbado::Log::NotifyRollbar]
149
+ end
150
+ ```
151
+
152
+ The require raises `LoadError` at boot if Rollbar is absent, which is deliberate — the
153
+ alternative is a `NameError` raised inside `log`, at the moment something is trying to report a
154
+ failure, replacing the error being reported with a worse one.
155
+
156
+ The handler configures nothing. Access token, environment and scrubbing are Rollbar's own
157
+ `Rollbar.configure`, which the application owns.
158
+
159
+ Everything the line carried travels as Rollbar's extra data, in **one** hash — Rollbar scans its
160
+ arguments by type and keeps the last hash it is given, so a second one would silently displace
161
+ the first:
162
+
163
+ | The line has | Reaches the item as |
164
+ |---|---|
165
+ | an exception as its data | the exception itself, which Rollbar groups and traces on |
166
+ | a hash as its data | those keys, stringified |
167
+ | anything else as its data | a `data` key holding its `inspect` |
168
+ | — | a `subject` key naming the class that logged it |
169
+ | a stacktrace, with no exception | a `stacktrace` key |
170
+
171
+ The handler's own keys are merged last, so a line cannot tell an item it came from a different
172
+ class. A stacktrace is sent only when there is no exception, because Rollbar reads the backtrace
173
+ off an exception itself.
174
+
175
+ The message is sent as a String whatever it was — Rollbar matches its title by type, so anything
176
+ else would leave the item with no title at all.
177
+
178
+ Pass `notifier:` to record what was sent rather than send it, which is mainly how a spec reads it
179
+ back.
180
+
51
181
  ## Level
52
182
 
53
183
  A message below the level reaches no handler.
54
184
 
55
185
  ```ruby
56
186
  Hubbado::Log.configuration do |config|
57
- config.loggers = [MyStderrHandler]
187
+ config.loggers = [Hubbado::Log::StderrLogger]
58
188
  config.level = :debug
59
189
  end
60
190
  ```
data/hubbado-log.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "hubbado-log"
3
- s.version = "1.4.1"
3
+ s.version = "1.5.0"
4
4
  s.summary = "Lightweight pluggable logging system"
5
5
 
6
6
  s.authors = ["Hubbado Devs"]
@@ -30,4 +30,8 @@ Gem::Specification.new do |s|
30
30
  s.add_development_dependency "debug"
31
31
  s.add_development_dependency "hubbado-style"
32
32
  s.add_development_dependency "test_bench"
33
+
34
+ # Development only, deliberately. `hubbado/log/notify_rollbar` requires it, and nothing else
35
+ # in the gem does — so a consumer that never asks for that handler never installs Rollbar.
36
+ s.add_development_dependency "rollbar"
33
37
  end
@@ -0,0 +1,24 @@
1
+ module Hubbado
2
+ class Log
3
+ module Controls
4
+ # Stands in for `Rails.logger`, recording the lines it was asked to write.
5
+ #
6
+ # It answers to the severities Rails' own logger answers to, and deliberately not to
7
+ # `trace`, which Rails has no method for. A handler passing the gem's lowest severity
8
+ # straight through raises here exactly as it would in a Rails application, rather than
9
+ # being quietly recorded and passing a spec.
10
+ class RailsLogger
11
+ SEVERITIES = %i[debug info warn error fatal unknown].freeze
12
+
13
+ def self.example = new
14
+
15
+ # Each entry is the severity it was written at and the text of it.
16
+ def lines = @lines ||= []
17
+
18
+ SEVERITIES.each do |severity|
19
+ define_method(severity) { |line| lines << [severity, line] }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ module Hubbado
2
+ class Log
3
+ module Controls
4
+ # A class that takes a logger, which is what the handler controls attach to.
5
+ class Receiver
6
+ include Log::Dependency
7
+
8
+ def self.example = new
9
+
10
+ # One that has the attribute but no logger behind it, for the guard that refuses to
11
+ # attach to it. The Dependency module cannot produce this — it builds a logger on first
12
+ # read — so the shape has to be written out.
13
+ def self.without_logger
14
+ Class.new { attr_accessor :logger }.new
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,50 @@
1
+ module Hubbado
2
+ class Log
3
+ module Controls
4
+ # Stands in for the Rollbar module, recording what it was handed rather than sending it.
5
+ # Every level Rollbar answers to is defined, so a handler notifying at a level it should
6
+ # have stayed quiet at is recorded and asserted against rather than raising.
7
+ class Rollbar
8
+ # Rollbar takes its arguments positionally and untyped, assigning each one it recognises
9
+ # over any earlier one of the same kind. So every reader here takes the **last** match,
10
+ # not the first: a notification is asserted on for what Rollbar would make of it, and a
11
+ # handler passing two of anything must lose the same one here that it loses there.
12
+ Notification = Struct.new(:level, :arguments) do
13
+ def message = arguments.grep(String).last
14
+
15
+ # `::Exception`, not `Exception` — this module has a control of that name, and a bare
16
+ # constant here resolves to it and matches nothing.
17
+ def exception = arguments.grep(::Exception).last
18
+
19
+ def extra = arguments.grep(Hash).last
20
+
21
+ def hashes = arguments.grep(Hash).length
22
+ end
23
+
24
+ LEVELS = %i[debug info warning warn error critical].freeze
25
+
26
+ def self.example = new
27
+
28
+ def notifications = @notifications ||= []
29
+
30
+ LEVELS.each do |level|
31
+ define_method(level) { |*arguments| notifications << Notification.new(level, arguments) }
32
+ end
33
+
34
+ # Without a level, whether anything was sent at all — which a spec asserting silence
35
+ # would otherwise have to infer from an attribute never having been set.
36
+ def notified?(level = nil)
37
+ return !notifications.empty? if level.nil?
38
+
39
+ notifications.any? { |notification| notification.level == level.to_s.to_sym }
40
+ end
41
+
42
+ # The most recent notification. Derived rather than assigned alongside `notifications`,
43
+ # so the two cannot disagree about which is the latest.
44
+ %i[level message exception extra].each do |field|
45
+ define_method(field) { notifications.last&.public_send(field) }
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,14 @@
1
+ module Hubbado
2
+ class Log
3
+ module Controls
4
+ # What the logger synthesises for a line carrying no exception: `Kernel.caller`, joined
5
+ # by newlines. Recognisably a stack, and recognisably not any other string a spec asserts
6
+ # on.
7
+ module Stacktrace
8
+ def self.example
9
+ "lib/scanning.rb:14:in 'sweep'\nlib/cli.rb:3:in 'call'"
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,7 +1,13 @@
1
1
  require_relative 'controls/data'
2
2
  require_relative 'controls/exception'
3
3
  require_relative 'controls/message'
4
+ require_relative 'controls/stacktrace'
4
5
  require_relative 'controls/subject'
5
6
 
7
+ require_relative 'controls/receiver'
8
+
6
9
  require_relative 'controls/log_handler'
7
10
  require_relative 'controls/logger'
11
+
12
+ require_relative 'controls/rails_logger'
13
+ require_relative 'controls/rollbar'
@@ -0,0 +1,70 @@
1
+ require 'rollbar'
2
+
3
+ require_relative '../log'
4
+
5
+ module Hubbado
6
+ class Log
7
+ # Forwards a log line worth an incident to Rollbar.
8
+ class NotifyRollbar < LogHandler
9
+ # Rollbar's own levels. It has none above error, so the two severities above `warn` share
10
+ # it, and anything below a warning is running commentary that reaches the handlers which
11
+ # print rather than this one.
12
+ LEVELS = { warn: :warn, error: :error, fatal: :error, unknown: :error }.freeze
13
+
14
+ def initialize(notifier: nil)
15
+ super()
16
+
17
+ @notifier = notifier
18
+ end
19
+
20
+ def log(subject, severity, message, data = nil, stacktrace = nil)
21
+ level = LEVELS[severity.to_sym]
22
+ return if level.nil?
23
+
24
+ error = data if data.is_a?(::Exception)
25
+
26
+ notifier.public_send(
27
+ level, *[error, title(message), extra(subject, data, stacktrace)].compact
28
+ )
29
+ end
30
+
31
+ private
32
+
33
+ # Read rather than stored, so a process that reconfigures Rollbar after the log system
34
+ # built its handlers is notified through what it configured.
35
+ def notifier = @notifier || ::Rollbar
36
+
37
+ # Rollbar matches its title by type: a message that is not a String is ignored, and the
38
+ # item arrives with no title at all rather than with a bad one.
39
+ def title(message) = message.to_s
40
+
41
+ # One hash, never two. Rollbar scans its arguments by type and keeps the last hash it
42
+ # finds, discarding any earlier one — so a line's own data and the fields added here have
43
+ # to arrive merged, or one of them silently never reaches the item.
44
+ #
45
+ # Built fresh every call for the same reason it is merged: Rollbar deletes a key from the
46
+ # hash it is given, and the caller still holds theirs.
47
+ #
48
+ # The handler's fields merge last. A call site names the record it is about, and an item
49
+ # that could be told its subject was something else would file under a class that never
50
+ # logged it.
51
+ def extra(subject, data, stacktrace)
52
+ extra = context(data).merge("subject" => subject)
53
+
54
+ return extra if stacktrace.nil? || data.is_a?(Exception)
55
+
56
+ extra.merge("stacktrace" => stacktrace)
57
+ end
58
+
59
+ # Rollbar matches a String to the message and an Exception to the exception, and ignores
60
+ # anything else it is handed. Data that is neither is named here rather than dropped.
61
+ def context(data)
62
+ case data
63
+ when nil, Exception then {}
64
+ when Hash then data.transform_keys(&:to_s)
65
+ else { "data" => data.inspect }
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,46 @@
1
+ require_relative '../log'
2
+
3
+ module Hubbado
4
+ class Log
5
+ # Writes a log line into a Rails application's own log.
6
+ class RailsLogger < LogHandler
7
+ # Rails has no logger method below debug, so the gem's trace is written as one. A handler
8
+ # passing it straight through raises NoMethodError on the first trace line it is handed.
9
+ RAILS_SEVERITIES = { trace: :debug }.freeze
10
+
11
+ def initialize(rails_logger: nil)
12
+ super()
13
+
14
+ @rails_logger = rails_logger
15
+ end
16
+
17
+ def log(subject, severity, message, data = nil, stacktrace = nil)
18
+ rails_severity = RAILS_SEVERITIES.fetch(severity.to_sym, severity)
19
+
20
+ rails_logger.send(rails_severity, "#{subject}: #{message}")
21
+
22
+ details(data, stacktrace).each do |detail|
23
+ rails_logger.send(rails_severity, detail)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ # Read rather than stored, because Rails replaces its logger during boot and a handler
30
+ # built before that would keep writing to the one it replaced.
31
+ def rails_logger = @rails_logger || ::Rails.logger
32
+
33
+ # A Rails log is read after the fact, and by machine as often as by a person, so the
34
+ # stacktrace is written whatever the severity — where a terminal withholds it below error
35
+ # to stay readable.
36
+ #
37
+ # An exception is one entry rather than two: its `full_message` carries the message that
38
+ # `inspect` would print, so writing both writes the message twice.
39
+ def details(data, stacktrace)
40
+ return [stacktrace || data.full_message] if data.is_a?(::Exception)
41
+
42
+ [data&.inspect, stacktrace].compact
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,54 @@
1
+ require_relative '../log'
2
+
3
+ module Hubbado
4
+ class Log
5
+ # Prints a log line where a person watching a run can see it.
6
+ class StderrLogger < LogHandler
7
+ # Where a stacktrace earns its space on a terminal. The logger synthesises one for `warn`
8
+ # too, but a warning is a condition to examine rather than a failure to trace, and its
9
+ # message already names the field and value — so a sweep that warns per row would bury
10
+ # itself in Ruby stack to solve a problem stderr does not have.
11
+ FAILURE_SEVERITIES = %i[error fatal unknown].freeze
12
+
13
+ def initialize(io: nil)
14
+ super()
15
+
16
+ @io = io
17
+ end
18
+
19
+ # One write, because a line and the detail under it belong together. Three writes let a
20
+ # second thread put its own line between them, and a stacktrace filed under the wrong
21
+ # message is worse than no stacktrace.
22
+ def log(subject, severity, message, data = nil, stacktrace = nil)
23
+ lines = ["#{severity.to_s.upcase} #{subject}: #{message}"]
24
+ lines << detail(data, stacktrace) unless data.nil?
25
+ lines << stacktrace if print_stacktrace?(severity, data, stacktrace)
26
+
27
+ io.puts(lines.join("\n"))
28
+ end
29
+
30
+ private
31
+
32
+ # Read rather than stored, so a process that rebinds $stderr after the log system built
33
+ # its handlers is written to rather than the stream it replaced.
34
+ def io = @io || $stderr
35
+
36
+ # An exception carries its own backtrace, and the logger has already rendered it into the
37
+ # stacktrace argument — so that string is reused rather than rendered a second time.
38
+ def detail(data, stacktrace)
39
+ return data.inspect unless data.is_a?(::Exception)
40
+
41
+ stacktrace || data.full_message
42
+ end
43
+
44
+ # An exception is excluded because its `full_message` is printed from the data above, so
45
+ # honouring the argument as well would print the backtrace twice.
46
+ def print_stacktrace?(severity, data, stacktrace)
47
+ return false if stacktrace.nil?
48
+ return false if data.is_a?(::Exception)
49
+
50
+ FAILURE_SEVERITIES.include?(severity.to_sym)
51
+ end
52
+ end
53
+ end
54
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hubbado-log
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hubbado Devs
@@ -79,6 +79,20 @@ dependencies:
79
79
  - - ">="
80
80
  - !ruby/object:Gem::Version
81
81
  version: '0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rollbar
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
82
96
  email:
83
97
  - devs@hubbado.com
84
98
  executables: []
@@ -97,11 +111,18 @@ files:
97
111
  - lib/hubbado/log/controls/log_handler.rb
98
112
  - lib/hubbado/log/controls/logger.rb
99
113
  - lib/hubbado/log/controls/message.rb
114
+ - lib/hubbado/log/controls/rails_logger.rb
115
+ - lib/hubbado/log/controls/receiver.rb
116
+ - lib/hubbado/log/controls/rollbar.rb
117
+ - lib/hubbado/log/controls/stacktrace.rb
100
118
  - lib/hubbado/log/controls/subject.rb
101
119
  - lib/hubbado/log/log.rb
102
120
  - lib/hubbado/log/log_handler.rb
103
121
  - lib/hubbado/log/logger.rb
104
122
  - lib/hubbado/log/logger/substitute.rb
123
+ - lib/hubbado/log/notify_rollbar.rb
124
+ - lib/hubbado/log/rails_logger.rb
125
+ - lib/hubbado/log/stderr_logger.rb
105
126
  - lib/hubbado/log/tags.rb
106
127
  homepage: https://www.github.com/hubbado/hubbado-log
107
128
  licenses: