loggerstash 0.0.8 → 0.0.9

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: e8eb55e42f97396acbdf11494af9948941bb8736c4726287c3b762869a82b28b
4
- data.tar.gz: 618b63be291e7bbe849c67d80294f26bc52663a1b23f5e93fe2553e1f48703ea
3
+ metadata.gz: f20d5ce8da4dbfec707d7b7ccd2dd6dba95a7f911980c3c4791e342a290034c0
4
+ data.tar.gz: 5a335fdc5d9632439e9d75b3e141b5e09123b2de8d233acf70da8d5efee52a0c
5
5
  SHA512:
6
- metadata.gz: 9ca77a67d2b5ac773e75aa016e0019e521e085643d39b20fc5b458aaf927245b8c6b43898c8b73b621f0ee66b1d0592265806443d6367822e189fea0f700f0f8
7
- data.tar.gz: c207d626c99a6eb3caed82493ba5e5c24550df36916c28169c2fcbc74e1ad179274baca8136d395f3e955e0f73b8c1dd52c91b928b2ebd29a1b0b8252a5547f2
6
+ metadata.gz: a1e713734296868661da7ee81e9487dbce2173d41353abd9f9b665cb21e363d16929082fa1e4d5ab1c29b26075b7ae0126e9eaaec8c43b5dd57c57004084fc5b
7
+ data.tar.gz: 2402ff129f1e76086a2f4c51bdc026f4a0a180b526644c70dd6ec7b595ef9e9324dc8c1852a36356a8a41c44c748cab170a0c0d1b102b74e207943e4aad95579
@@ -0,0 +1,7 @@
1
+ [*.rb]
2
+ indent_style = space
3
+ indent_size = 2
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+ charset = utf-8
7
+ trim_trailing_whitespace = true
@@ -1 +1,4 @@
1
1
  inherit_from: https://raw.githubusercontent.com/discourse/discourse/master/.rubocop.yml
2
+
3
+ Layout/AlignHash:
4
+ Enabled: false
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'logstash_writer'
2
4
  require 'thread'
3
5
 
@@ -14,31 +16,29 @@ class Loggerstash
14
16
  #
15
17
  class AlreadyRunningError < Error; end
16
18
 
17
- # Set the formatter proc to a new proc.
18
- #
19
- # The passed in proc must take four arguments: `severity`, `timestamp`,
20
- # `progname` and `message`. `timestamp` is a `Time`, all over arguments
21
- # are `String`s, and `progname` can possibly be `nil`. It must return a
22
- # Hash containing the parameters you wish to send to logstash.
23
- #
24
- attr_writer :formatter
25
-
26
19
  # A new Loggerstash!
27
20
  #
28
21
  # @param logstash_server [String] an address:port, hostname:port, or srvname
29
22
  # to which a `json_lines` logstash connection can be made.
23
+ #
30
24
  # @param metrics_registry [Prometheus::Client::Registry] where the metrics
31
25
  # which are used by the underlying `LogstashWriter` should be registered,
32
26
  # for later presentation by the Prometheus client.
27
+ #
33
28
  # @param formatter [Proc] a formatting proc which takes the same arguments
34
29
  # as the standard `Logger` formatter, but rather than emitting a string,
35
30
  # it should pass back a Hash containing all the fields you wish to send
36
31
  # to logstash.
32
+ #
37
33
  # @param logstash_writer [LogstashWriter] in the event that you've already
38
34
  # got a LogstashWriter instance configured, you can pass it in here. Note
39
35
  # that any values you've set for logstash_server and metrics_registry
40
36
  # will be ignored.
41
37
  #
38
+ # @param logger [Logger] passed to the LogstashWriter we create. May or
39
+ # may not, itself, be attached to the Loggerstash for forwarding to
40
+ # logstash (Logception!).
41
+ #
42
42
  def initialize(logstash_server:, metrics_registry: nil, formatter: nil, logstash_writer: nil, logger: nil)
43
43
  @logstash_server = logstash_server
44
44
  @metrics_registry = metrics_registry
@@ -61,20 +61,21 @@ class Loggerstash
61
61
  # benefit from the attachment; that's up to you to ensure.
62
62
  #
63
63
  def attach(obj)
64
+ run_writer
65
+
64
66
  @op_mutex.synchronize do
65
- obj.instance_variable_set(:@loggerstash, self)
67
+ obj.instance_variable_set(:@logstash_writer, @logstash_writer)
68
+ obj.instance_variable_set(:@loggerstash_formatter, @formatter)
66
69
 
67
70
  if obj.is_a?(Module)
68
71
  obj.prepend(Mixin)
69
72
  else
70
73
  obj.singleton_class.prepend(Mixin)
71
74
  end
72
-
73
- run_writer
74
75
  end
75
76
  end
76
77
 
77
- %i{logstash_server metrics_registry}.each do |sym|
78
+ %i{formatter logger logstash_server metrics_registry}.each do |sym|
78
79
  define_method(:"#{sym}=") do |v|
79
80
  @op_mutex.synchronize do
80
81
  if @logstash_writer
@@ -86,111 +87,67 @@ class Loggerstash
86
87
  end
87
88
  end
88
89
 
89
- # Send a logger message to logstash.
90
- #
91
- # @private
92
- #
93
- def log_message(s, t, p, m)
94
- @op_mutex.synchronize do
95
- if @logstash_writer.nil?
96
- #:nocov:
97
- run_writer
98
- #:nocov:
99
- end
100
-
101
- @logstash_writer.send_event((@formatter || default_formatter).call(s, t, p, m))
102
- end
103
- end
104
-
105
90
  private
106
91
 
107
92
  # Do the needful to get the writer going.
108
93
  #
109
- # This will error out unless the @op_mutex is held at the time the
110
- # method is called; we can't acquire it ourselves because some calls
111
- # to run_writer already need to hold the mutex.
112
- #
113
94
  def run_writer
114
- unless @op_mutex.owned?
115
- #:nocov:
116
- raise RuntimeError,
117
- "Must call run_writer while holding @op_mutex"
118
- #:nocov:
119
- end
120
-
121
- if @logstash_writer.nil?
122
- {}.tap do |opts|
123
- opts[:server_name] = @logstash_server
124
- if @metrics_registry
125
- opts[:metrics_registry] = @metrics_registry
126
- end
127
- if @logger
128
- opts[:logger] = @logger
95
+ @op_mutex.synchronize do
96
+ if @logstash_writer.nil?
97
+ {}.tap do |opts|
98
+ opts[:server_name] = @logstash_server
99
+ if @metrics_registry
100
+ opts[:metrics_registry] = @metrics_registry
101
+ end
102
+ if @logger
103
+ opts[:logger] = @logger
104
+ end
105
+
106
+ @logstash_writer = LogstashWriter.new(**opts)
107
+ @logstash_writer.start!
129
108
  end
130
-
131
- @logstash_writer = LogstashWriter.new(**opts)
132
- @logstash_writer.run
133
109
  end
134
110
  end
135
111
  end
136
112
 
137
- # Mangle the standard sev/time/prog/msg set into a minimal logstash
138
- # event.
139
- #
140
- def default_formatter
141
- @default_formatter ||= ->(s, t, p, m) do
142
- caller = caller_locations.find { |loc| ! [__FILE__, logger_filename].include? loc.absolute_path }
143
-
144
- {
145
- "@timestamp": t.utc.strftime("%FT%T.%NZ"),
146
- "@metadata": { event_type: "loggerstash" },
147
- message: m,
148
- severity_name: s.downcase,
149
- hostname: Socket.gethostname,
150
- pid: $$,
151
- thread_id: Thread.current.object_id,
152
- caller: {
153
- absolute_path: caller.absolute_path,
154
- base_label: caller.base_label,
155
- label: caller.label,
156
- lineno: caller.lineno,
157
- path: caller.path,
158
- },
159
- }.tap do |ev|
160
- ev[:progname] = p if p
161
- end
162
- end
163
- end
164
-
165
- # Identify the absolute path of the file that defines the Logger class.
166
- #
167
- def logger_filename
168
- @logger_filename ||= Logger.instance_method(:format_message).source_location.first
169
- end
170
-
171
113
  # The methods needed to turn any Logger into a Loggerstash Logger.
172
114
  #
173
115
  module Mixin
116
+ attr_writer :logstash_writer, :loggerstash_formatter
117
+
174
118
  private
175
119
 
176
120
  # Hooking into this specific method may seem... unorthodox, but
177
121
  # it seemingly has an extremely stable interface and is the most
178
122
  # appropriate place to inject ourselves.
123
+ #
179
124
  def format_message(s, t, p, m)
180
- loggerstash.log_message(s, t, p, m)
125
+ loggerstash_log_message(s, t, p, m)
181
126
 
182
127
  super
183
128
  end
184
129
 
185
- # Find where our associated Loggerstash object is being held captive.
130
+ # Send a logger message to logstash.
131
+ #
132
+ def loggerstash_log_message(s, t, p, m)
133
+ logstash_writer.send_event(loggerstash_formatter.call(s, t, p, m))
134
+ end
135
+
136
+ # The current formatter for logstash-destined messages.
137
+ #
138
+ def loggerstash_formatter
139
+ @loggerstash_formatter ||= self.class.ancestors.find { |m| m.instance_variable_defined?(:@loggerstash_formatter) }.instance_variable_get(:@loggerstash_formatter) || default_loggerstash_formatter
140
+ end
141
+
142
+ # Find the relevant logstash_writer for this Logger.
186
143
  #
187
144
  # We're kinda reimplementing Ruby's method lookup logic here, but there's
188
145
  # no other way to store our object *somewhere* in the object + class
189
146
  # hierarchy and still be able to get at it from a module (class variables
190
- # don't like being accessed from modules).
191
- #
192
- def loggerstash
193
- ([self] + self.class.ancestors).find { |m| m.instance_variable_defined?(:@loggerstash) }.instance_variable_get(:@loggerstash).tap do |ls|
147
+ # don't like being accessed from modules). This is necessary because you
148
+ # can attach Loggerstash to the Logger class, not just to an instance.
149
+ def logstash_writer
150
+ @logstash_writer ||= self.class.ancestors.find { |m| m.instance_variable_defined?(:@logstash_writer) }.instance_variable_get(:@logstash_writer).tap do |ls|
194
151
  if ls.nil?
195
152
  #:nocov:
196
153
  raise RuntimeError,
@@ -199,5 +156,40 @@ class Loggerstash
199
156
  end
200
157
  end
201
158
  end
159
+
160
+ # Mangle the standard sev/time/prog/msg set into a logstash
161
+ # event.
162
+ #
163
+ def default_loggerstash_formatter
164
+ ->(s, t, p, m) do
165
+ caller = caller_locations.find { |loc| ! [__FILE__, logger_filename].include? loc.absolute_path }
166
+
167
+ {
168
+ "@timestamp": t.utc.strftime("%FT%T.%NZ"),
169
+ "@metadata": { event_type: "loggerstash" },
170
+ message: m,
171
+ severity_name: s.downcase,
172
+ hostname: Socket.gethostname,
173
+ pid: $$,
174
+ thread_id: Thread.current.object_id,
175
+ caller: {
176
+ absolute_path: caller.absolute_path,
177
+ base_label: caller.base_label,
178
+ label: caller.label,
179
+ lineno: caller.lineno,
180
+ path: caller.path,
181
+ },
182
+ }.tap do |ev|
183
+ ev[:progname] = p if p
184
+ ev[:thread_name] = Thread.current.name if Thread.current.name
185
+ end
186
+ end
187
+ end
188
+
189
+ # Identify the absolute path of the file that defines the Logger class.
190
+ #
191
+ def logger_filename
192
+ @logger_filename ||= Logger.instance_method(:format_message).source_location.first
193
+ end
202
194
  end
203
195
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  begin
2
4
  require 'git-version-bump'
3
5
  rescue LoadError
@@ -27,7 +29,7 @@ Gem::Specification.new do |s|
27
29
 
28
30
  s.required_ruby_version = ">= 2.3.0"
29
31
 
30
- s.add_runtime_dependency "logstash_writer", "~> 0.0"
32
+ s.add_runtime_dependency "logstash_writer", ">= 0.0.11"
31
33
 
32
34
  s.add_development_dependency 'bundler'
33
35
  s.add_development_dependency 'github-release'
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loggerstash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Palmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-24 00:00:00.000000000 Z
11
+ date: 2019-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: logstash_writer
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0.0'
19
+ version: 0.0.11
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0.0'
26
+ version: 0.0.11
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -202,6 +202,7 @@ executables: []
202
202
  extensions: []
203
203
  extra_rdoc_files: []
204
204
  files:
205
+ - ".editorconfig"
205
206
  - ".gitignore"
206
207
  - ".rubocop.yml"
207
208
  - ".travis.yml"
@@ -230,8 +231,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
230
231
  - !ruby/object:Gem::Version
231
232
  version: '0'
232
233
  requirements: []
233
- rubyforge_project:
234
- rubygems_version: 2.7.7
234
+ rubygems_version: 3.0.1
235
235
  signing_key:
236
236
  specification_version: 4
237
237
  summary: Monkeypatch Logger to send log entries to logstash