loggerstash 0.0.1
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 +7 -0
- data/.gitignore +7 -0
- data/.rubocop.yml +116 -0
- data/.travis.yml +11 -0
- data/.yardopts +1 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/CONTRIBUTING.md +13 -0
- data/LICENCE +674 -0
- data/README.md +150 -0
- data/lib/loggerstash.rb +116 -0
- data/loggerstash.gemspec +44 -0
- metadata +238 -0
data/README.md
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
Ever wanted to have your loggers send their data direct to logstash, without
|
2
|
+
going through a dozen intermediate processing steps? Do you worry your log
|
3
|
+
entries are being dropped because you're forced to use UDP for sending log
|
4
|
+
events? Would you like to have actionable metrics showing exactly how your
|
5
|
+
log forwarding system is working? Do you dream of being able to use modern
|
6
|
+
DNS record types, such as SRV (standardised in the year 2000!), to indicate
|
7
|
+
where your logstash servers are?
|
8
|
+
|
9
|
+
If so, you're in the right place.
|
10
|
+
|
11
|
+
|
12
|
+
# Installation
|
13
|
+
|
14
|
+
It's a gem:
|
15
|
+
|
16
|
+
gem install loggerstash
|
17
|
+
|
18
|
+
There's also the wonders of [the Gemfile](http://bundler.io):
|
19
|
+
|
20
|
+
gem 'loggerstash'
|
21
|
+
|
22
|
+
If you're the sturdy type that likes to run from git:
|
23
|
+
|
24
|
+
rake install
|
25
|
+
|
26
|
+
Or, if you've eschewed the convenience of Rubygems entirely, then you
|
27
|
+
presumably know what to do already.
|
28
|
+
|
29
|
+
|
30
|
+
# Logstash Configuration
|
31
|
+
|
32
|
+
In order for logstash to receive the events being written, it must have a
|
33
|
+
`json_lines` TCP input configured. Something like this will do the trick:
|
34
|
+
|
35
|
+
input {
|
36
|
+
tcp {
|
37
|
+
id => "json_lines"
|
38
|
+
port => 5151
|
39
|
+
codec => "json_lines"
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
|
44
|
+
# Usage
|
45
|
+
|
46
|
+
Start by including the necessary file:
|
47
|
+
|
48
|
+
require 'loggerstash'
|
49
|
+
|
50
|
+
next, create a new instance of `Loggerstash`, pointing to the logstash
|
51
|
+
server you wish to use:
|
52
|
+
|
53
|
+
ls = Loggerstash.new(logstash_server: "192.0.2.42:5151")
|
54
|
+
|
55
|
+
Anything that is a valid [logstash_writer
|
56
|
+
`server_name`](https://github.com/discourse/logstash_writer#usage) can be
|
57
|
+
specified as the `logstash_server`.
|
58
|
+
|
59
|
+
Once you have a Loggerstash, you just need to attach your `Loggerstash`
|
60
|
+
instance to either the `Logger` class (to have all loggers forward to
|
61
|
+
logstash), or to individual instances of Logger that you wish to forward:
|
62
|
+
|
63
|
+
# Forward just this logger's messages to logstash
|
64
|
+
l = Logger.new($stderr)
|
65
|
+
ls.attach(l)
|
66
|
+
|
67
|
+
# Forward all Logger instances' messages to logstash
|
68
|
+
ls.attach(Logger)
|
69
|
+
|
70
|
+
# Forward multiple loggers' messages to logstash
|
71
|
+
some_logger = Logger.new($stderr)
|
72
|
+
another_logger = Logger.new($stderr)
|
73
|
+
|
74
|
+
ls.attach(some_logger)
|
75
|
+
ls.attach(another_logger)
|
76
|
+
|
77
|
+
You can, in *theory*, attach Loggerstash to other things, but since it hooks
|
78
|
+
into the deep internals of Logger, it's unlikely to work very well on
|
79
|
+
anything else.
|
80
|
+
|
81
|
+
If you'd like to provide a richer event to logstash than the default (which
|
82
|
+
basically just maps progname, timestamp, severity, and message into a hash),
|
83
|
+
you can extend the default formatter:
|
84
|
+
|
85
|
+
ls.formatter = ->(s, t, p, m) do
|
86
|
+
default_formatter.call(s, t, p, m).merge(some_tag: "ohai!")
|
87
|
+
end
|
88
|
+
|
89
|
+
Of course, you can do entirely your own thing, and not call the default
|
90
|
+
formatter at all if you'd prefer.
|
91
|
+
|
92
|
+
You can also specify the formatter as a parameter to the constructor:
|
93
|
+
|
94
|
+
ls = Loggerstash.new(logstash_server: "...", formatter: ->(s, t, p, m) { ... }
|
95
|
+
|
96
|
+
If you want to expose the metrics maintained by the underlying
|
97
|
+
LogstashWriter instance, you can specify a `Prometheus::Client::Registry` to
|
98
|
+
register the metrics:
|
99
|
+
|
100
|
+
Loggerstash.new(logstash_server: "...", metrics_registry: @metrics_server.registry)
|
101
|
+
|
102
|
+
# ... OR ...
|
103
|
+
ls.metrics_registry = @metrics_server.registry
|
104
|
+
|
105
|
+
You can only pass a given metrics registry to one instance of `Loggerstash`,
|
106
|
+
because otherwise the registered metrics will conflict and everything will
|
107
|
+
be awful. If anyone ever comes up with a real-world use-case for needing
|
108
|
+
multiple Loggerstashes pointing to the same metrics registry, a PR would be
|
109
|
+
accepted to specify a prefix on the registered metrics.
|
110
|
+
|
111
|
+
Note that once you have attached a `Loggerstash` instance to a logger, you
|
112
|
+
can't change the `Loggerstash` configuration -- calls to any of the
|
113
|
+
configuration setters will raise an exception.
|
114
|
+
|
115
|
+
|
116
|
+
## Prometheus Metrics
|
117
|
+
|
118
|
+
If you specify a metrics registry to use, a set of metrics with a
|
119
|
+
`logstash_writer_` prefix will be included and maintained. For the complete
|
120
|
+
set of metrics and their meanings, refer to [the `LogstashWriter`
|
121
|
+
documentation](https://github.com/discourse/logstash_writer#prometheus-metrics).
|
122
|
+
|
123
|
+
|
124
|
+
# Contributing
|
125
|
+
|
126
|
+
Patches can be sent as [a Github pull
|
127
|
+
request](https://github.com/discourse/loggerstash). This project is
|
128
|
+
intended to be a safe, welcoming space for collaboration, and contributors
|
129
|
+
are expected to adhere to the [Contributor Covenant code of
|
130
|
+
conduct](CODE_OF_CONDUCT.md).
|
131
|
+
|
132
|
+
|
133
|
+
# Licence
|
134
|
+
|
135
|
+
Unless otherwise stated, everything in this repo is covered by the following
|
136
|
+
copyright notice:
|
137
|
+
|
138
|
+
Copyright (C) 2018 Civilized Discourse Construction Kit, Inc.
|
139
|
+
|
140
|
+
This program is free software: you can redistribute it and/or modify it
|
141
|
+
under the terms of the GNU General Public License version 3, as
|
142
|
+
published by the Free Software Foundation.
|
143
|
+
|
144
|
+
This program is distributed in the hope that it will be useful,
|
145
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
146
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
147
|
+
GNU General Public License for more details.
|
148
|
+
|
149
|
+
You should have received a copy of the GNU General Public License
|
150
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/lib/loggerstash.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'logstash_writer'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
# A sidecar class to augment a Logger with super-cow-logstash-forwarding
|
5
|
+
# powers.
|
6
|
+
#
|
7
|
+
class Loggerstash
|
8
|
+
# Base class of all Loggerstash errors
|
9
|
+
#
|
10
|
+
class Error < StandardError; end
|
11
|
+
|
12
|
+
# Raised if any configuration setter methods are called (`Loggerstash#<anything>=`)
|
13
|
+
# after the loggerstash instance has been attached to a logger.
|
14
|
+
#
|
15
|
+
class AlreadyRunningError < Error; end
|
16
|
+
|
17
|
+
attr_writer :formatter
|
18
|
+
|
19
|
+
def initialize(logstash_server:, metrics_registry: nil, formatter: nil)
|
20
|
+
@logstash_server = logstash_server
|
21
|
+
@metrics_registry = metrics_registry
|
22
|
+
@formatter = formatter
|
23
|
+
|
24
|
+
@op_mutex = Mutex.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def attach(obj)
|
28
|
+
@op_mutex.synchronize do
|
29
|
+
obj.instance_variable_set(:@loggerstash, self)
|
30
|
+
|
31
|
+
if obj.is_a?(Module)
|
32
|
+
obj.prepend(Mixin)
|
33
|
+
else
|
34
|
+
obj.singleton_class.prepend(Mixin)
|
35
|
+
end
|
36
|
+
|
37
|
+
run_writer
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
%i{logstash_server metrics_registry}.each do |sym|
|
42
|
+
define_method(:"#{sym}=") do |v|
|
43
|
+
@op_mutex.synchronize do
|
44
|
+
if @logstash_writer
|
45
|
+
raise AlreadyRunningError,
|
46
|
+
"Cannot change #{sym} once writer is running"
|
47
|
+
end
|
48
|
+
instance_variable_set(:"@#{sym}", v)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def log_message(s, t, p, m)
|
54
|
+
@op_mutex.synchronize do
|
55
|
+
if @logstash_writer.nil?
|
56
|
+
run_writer
|
57
|
+
end
|
58
|
+
|
59
|
+
@logstash_writer.send_event((@formatter || default_formatter).call(s, t, p, m))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
private
|
63
|
+
|
64
|
+
def run_writer
|
65
|
+
unless @op_mutex.owned?
|
66
|
+
raise RuntimeError,
|
67
|
+
"Must call run_writer while holding @op_mutex"
|
68
|
+
end
|
69
|
+
|
70
|
+
if @logstash_writer.nil?
|
71
|
+
{}.tap do |opts|
|
72
|
+
opts[:server_name] = @logstash_server
|
73
|
+
if @metrics_registry
|
74
|
+
opts[:metrics_registry] = @metrics_registry
|
75
|
+
end
|
76
|
+
|
77
|
+
@logstash_writer = LogstashWriter.new(**opts)
|
78
|
+
@logstash_writer.run
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def default_formatter
|
84
|
+
@default_formatter ||= ->(s, t, p, m) do
|
85
|
+
{
|
86
|
+
"@timestamp" => t.utc.strftime("%FT%T.%NZ"),
|
87
|
+
message: m,
|
88
|
+
severity: s.downcase,
|
89
|
+
}.tap do |ev|
|
90
|
+
ev[:progname] = p if p
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
module Mixin
|
96
|
+
private
|
97
|
+
|
98
|
+
# Hooking into this specific method may seem... unorthodox, but
|
99
|
+
# it seemingly has an extremely stable interface and is the most
|
100
|
+
# appropriate place to inject ourselves.
|
101
|
+
def format_message(s, t, p, m)
|
102
|
+
loggerstash.log_message(s, t, p, m)
|
103
|
+
|
104
|
+
super
|
105
|
+
end
|
106
|
+
|
107
|
+
def loggerstash
|
108
|
+
([self] + self.class.ancestors).find { |m| m.instance_variable_defined?(:@loggerstash) }.instance_variable_get(:@loggerstash).tap do |ls|
|
109
|
+
if ls.nil?
|
110
|
+
raise RuntimeError,
|
111
|
+
"Cannot find loggerstash instance. CAN'T HAPPEN."
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/loggerstash.gemspec
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
begin
|
2
|
+
require 'git-version-bump'
|
3
|
+
rescue LoadError
|
4
|
+
nil
|
5
|
+
end
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "loggerstash"
|
9
|
+
|
10
|
+
s.version = GVB.version rescue "0.0.0.1.NOGVB"
|
11
|
+
s.date = GVB.date rescue Time.now.strftime("%Y-%m-%d")
|
12
|
+
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
|
15
|
+
s.summary = "Monkeypatch Logger to send log entries to logstash"
|
16
|
+
s.description = <<~EOF
|
17
|
+
Provides a module you can prepend into any instance of Logger to cause
|
18
|
+
it to send all logged entries to a Logstash server, in addition to
|
19
|
+
however the message would have been handled otherwise.
|
20
|
+
EOF
|
21
|
+
|
22
|
+
s.authors = ["Matt Palmer"]
|
23
|
+
s.email = ["matt.palmer@discourse.org"]
|
24
|
+
s.homepage = "https://github.com/discourse/loggerstash"
|
25
|
+
|
26
|
+
s.files = `git ls-files -z`.split("\0").reject { |f| f =~ /^(G|spec|Rakefile)/ }
|
27
|
+
|
28
|
+
s.required_ruby_version = ">= 2.3.0"
|
29
|
+
|
30
|
+
s.add_runtime_dependency "logstash_writer", "~> 0.0"
|
31
|
+
|
32
|
+
s.add_development_dependency 'bundler'
|
33
|
+
s.add_development_dependency 'github-release'
|
34
|
+
s.add_development_dependency 'git-version-bump'
|
35
|
+
s.add_development_dependency 'guard-rspec'
|
36
|
+
s.add_development_dependency 'guard-rubocop'
|
37
|
+
s.add_development_dependency 'rack-test'
|
38
|
+
s.add_development_dependency 'rake', "~> 12.0"
|
39
|
+
s.add_development_dependency 'redcarpet'
|
40
|
+
s.add_development_dependency 'rspec'
|
41
|
+
s.add_development_dependency 'rubocop'
|
42
|
+
s.add_development_dependency 'simplecov'
|
43
|
+
s.add_development_dependency 'yard'
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,238 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: loggerstash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Palmer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: logstash_writer
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: github-release
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: git-version-bump
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard-rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard-rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rack-test
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '12.0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '12.0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: redcarpet
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rspec
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rubocop
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: simplecov
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: yard
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
description: |
|
196
|
+
Provides a module you can prepend into any instance of Logger to cause
|
197
|
+
it to send all logged entries to a Logstash server, in addition to
|
198
|
+
however the message would have been handled otherwise.
|
199
|
+
email:
|
200
|
+
- matt.palmer@discourse.org
|
201
|
+
executables: []
|
202
|
+
extensions: []
|
203
|
+
extra_rdoc_files: []
|
204
|
+
files:
|
205
|
+
- ".gitignore"
|
206
|
+
- ".rubocop.yml"
|
207
|
+
- ".travis.yml"
|
208
|
+
- ".yardopts"
|
209
|
+
- CODE_OF_CONDUCT.md
|
210
|
+
- CONTRIBUTING.md
|
211
|
+
- LICENCE
|
212
|
+
- README.md
|
213
|
+
- lib/loggerstash.rb
|
214
|
+
- loggerstash.gemspec
|
215
|
+
homepage: https://github.com/discourse/loggerstash
|
216
|
+
licenses: []
|
217
|
+
metadata: {}
|
218
|
+
post_install_message:
|
219
|
+
rdoc_options: []
|
220
|
+
require_paths:
|
221
|
+
- lib
|
222
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
223
|
+
requirements:
|
224
|
+
- - ">="
|
225
|
+
- !ruby/object:Gem::Version
|
226
|
+
version: 2.3.0
|
227
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
228
|
+
requirements:
|
229
|
+
- - ">="
|
230
|
+
- !ruby/object:Gem::Version
|
231
|
+
version: '0'
|
232
|
+
requirements: []
|
233
|
+
rubyforge_project:
|
234
|
+
rubygems_version: 2.7.7
|
235
|
+
signing_key:
|
236
|
+
specification_version: 4
|
237
|
+
summary: Monkeypatch Logger to send log entries to logstash
|
238
|
+
test_files: []
|