loggerstash 0.0.8 → 0.0.9
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 +4 -4
- data/.editorconfig +7 -0
- data/.rubocop.yml +3 -0
- data/lib/loggerstash.rb +83 -91
- data/loggerstash.gemspec +3 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f20d5ce8da4dbfec707d7b7ccd2dd6dba95a7f911980c3c4791e342a290034c0
|
4
|
+
data.tar.gz: 5a335fdc5d9632439e9d75b3e141b5e09123b2de8d233acf70da8d5efee52a0c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1e713734296868661da7ee81e9487dbce2173d41353abd9f9b665cb21e363d16929082fa1e4d5ab1c29b26075b7ae0126e9eaaec8c43b5dd57c57004084fc5b
|
7
|
+
data.tar.gz: 2402ff129f1e76086a2f4c51bdc026f4a0a180b526644c70dd6ec7b595ef9e9324dc8c1852a36356a8a41c44c748cab170a0c0d1b102b74e207943e4aad95579
|
data/.editorconfig
ADDED
data/.rubocop.yml
CHANGED
data/lib/loggerstash.rb
CHANGED
@@ -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(:@
|
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
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|
-
|
125
|
+
loggerstash_log_message(s, t, p, m)
|
181
126
|
|
182
127
|
super
|
183
128
|
end
|
184
129
|
|
185
|
-
#
|
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
|
193
|
-
|
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
|
data/loggerstash.gemspec
CHANGED
@@ -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", "
|
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.
|
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:
|
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:
|
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:
|
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
|
-
|
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
|