logstash-output-graphite 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/lib/logstash/outputs/graphite.rb +79 -21
- data/logstash-output-graphite.gemspec +1 -1
- data/spec/outputs/graphite_spec.rb +52 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aaa1548ced5cd4e3cc3f3724c078a13e9c507fe5
|
4
|
+
data.tar.gz: 9c2309ed86b7c371bd35ad4d21ed7bb96536b48d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 26aedf2dae122c104225a6297484edd858457e553b340113d2458c2c4ec963a80133e8505f52cc0e348135db0ab5eb6ee654e8b15419906a1ba7a3f2f62dc7f4
|
7
|
+
data.tar.gz: dd176d82e9c199bb713dc8c8e3ecdda2b30117692994b9beef372d6531c125a6ff1056ae13d6bec070fc62d33f80b4637f8b567dd9404fef663d843a2f9a7571
|
data/CHANGELOG.md
CHANGED
@@ -67,6 +67,18 @@ class LogStash::Outputs::Graphite < LogStash::Outputs::Base
|
|
67
67
|
# NOTE: If no metrics_format is defined, the name of the metric will be used as fallback.
|
68
68
|
config :metrics_format, :validate => :string, :default => DEFAULT_METRICS_FORMAT
|
69
69
|
|
70
|
+
# When hashes are passed in as values they are broken out into a dotted notation
|
71
|
+
# For instance if you configure this plugin with
|
72
|
+
# # [source,ruby]
|
73
|
+
# metrics => "mymetrics"
|
74
|
+
#
|
75
|
+
# and "mymetrics" is a nested hash of '{a => 1, b => { c => 2 }}'
|
76
|
+
# this plugin will generate two metrics: a => 1, and b.c => 2 .
|
77
|
+
# If you've specified a 'metrics_format' it will respect that,
|
78
|
+
# but you still may want control over the separator within these nested key names.
|
79
|
+
# This config setting changes the separator from the '.' default.
|
80
|
+
config :nested_object_separator, :validate => :string, :default => "."
|
81
|
+
|
70
82
|
def register
|
71
83
|
@include_metrics.collect!{|regexp| Regexp.new(regexp)}
|
72
84
|
@exclude_metrics.collect!{|regexp| Regexp.new(regexp)}
|
@@ -106,26 +118,9 @@ class LogStash::Outputs::Graphite < LogStash::Outputs::Base
|
|
106
118
|
|
107
119
|
# Graphite message format: metric value timestamp\n
|
108
120
|
|
109
|
-
messages =
|
110
|
-
|
111
|
-
|
112
|
-
if @fields_are_metrics
|
113
|
-
@logger.debug("got metrics event", :metrics => event.to_hash)
|
114
|
-
event.to_hash.each do |metric,value|
|
115
|
-
next if EXCLUDE_ALWAYS.include?(metric)
|
116
|
-
next unless @include_metrics.empty? || @include_metrics.any? { |regexp| metric.match(regexp) }
|
117
|
-
next if @exclude_metrics.any? {|regexp| metric.match(regexp)}
|
118
|
-
messages << "#{construct_metric_name(metric)} #{event.sprintf(value.to_s).to_f} #{timestamp}"
|
119
|
-
end
|
120
|
-
else
|
121
|
-
@metrics.each do |metric, value|
|
122
|
-
@logger.debug("processing", :metric => metric, :value => value)
|
123
|
-
metric = event.sprintf(metric)
|
124
|
-
next unless @include_metrics.any? {|regexp| metric.match(regexp)}
|
125
|
-
next if @exclude_metrics.any? {|regexp| metric.match(regexp)}
|
126
|
-
messages << "#{construct_metric_name(event.sprintf(metric))} #{event.sprintf(value).to_f} #{timestamp}"
|
127
|
-
end
|
128
|
-
end
|
121
|
+
messages = @fields_are_metrics ?
|
122
|
+
messages_from_event_fields(event, @include_metrics, @exclude_metrics) :
|
123
|
+
messages_from_event_metrics(event, @metrics)
|
129
124
|
|
130
125
|
if messages.empty?
|
131
126
|
@logger.debug("Message is empty, not sending anything to Graphite", :messages => messages, :host => @host, :port => @port)
|
@@ -145,6 +140,69 @@ class LogStash::Outputs::Graphite < LogStash::Outputs::Base
|
|
145
140
|
retry if @resend_on_failure
|
146
141
|
end
|
147
142
|
end
|
148
|
-
|
149
143
|
end # def receive
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def messages_from_event_fields(event, include_metrics, exclude_metrics)
|
148
|
+
timestamp = event_timestamp(event)
|
149
|
+
@logger.debug? && @logger.debug("got metrics event", :metrics => event.to_hash)
|
150
|
+
event.to_hash.flat_map do |metric,value|
|
151
|
+
next if EXCLUDE_ALWAYS.include?(metric)
|
152
|
+
next unless include_metrics.empty? || include_metrics.any? { |regexp| metric.match(regexp) }
|
153
|
+
next if exclude_metrics.any? {|regexp| metric.match(regexp)}
|
154
|
+
|
155
|
+
metrics_lines_for_event(event, metric, value, timestamp)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def messages_from_event_metrics(event, metrics)
|
160
|
+
timestamp = event_timestamp(event)
|
161
|
+
metrics.flat_map do |metric, value|
|
162
|
+
@logger.debug("processing", :metric => metric, :value => value)
|
163
|
+
metric = event.sprintf(metric)
|
164
|
+
next unless @include_metrics.any? {|regexp| metric.match(regexp)}
|
165
|
+
next if @exclude_metrics.any? {|regexp| metric.match(regexp)}
|
166
|
+
|
167
|
+
metrics_lines_for_event(event, metric, value, timestamp)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def event_timestamp(event)
|
172
|
+
event[@timestamp_field].to_i
|
173
|
+
end
|
174
|
+
|
175
|
+
def metrics_lines_for_event(event, metric, value, timestamp)
|
176
|
+
if event[metric].is_a?(Hash)
|
177
|
+
dotify(event[metric], metric).map do |k,v|
|
178
|
+
metrics_line(k, v, timestamp)
|
179
|
+
end
|
180
|
+
else
|
181
|
+
metrics_line(event.sprintf(metric), event.sprintf(value).to_f, timestamp)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def metrics_line(name, value, timestamp)
|
186
|
+
"#{construct_metric_name(name)} #{value} #{timestamp}"
|
187
|
+
end
|
188
|
+
|
189
|
+
# Take a nested ruby hash of the form {:a => {:b => 2}, c: => 3} and
|
190
|
+
# turn it into a hash of the form
|
191
|
+
# { "a.b" => 2, "c" => 3}
|
192
|
+
def dotify(hash,prefix=nil)
|
193
|
+
hash.reduce({}) do |acc,kv|
|
194
|
+
k,v = kv
|
195
|
+
pk = prefix ? "#{prefix}#{@nested_object_separator}#{k}" : k.to_s
|
196
|
+
if v.is_a?(Hash)
|
197
|
+
acc.merge!(dotify(v, pk))
|
198
|
+
elsif v.is_a?(Array)
|
199
|
+
# There's no right answer here, so we do nothing
|
200
|
+
@logger.warn("Array values not supported for graphite metrics! Ignoring #{hash} @ #{prefix}")
|
201
|
+
else
|
202
|
+
acc[pk] = v
|
203
|
+
end
|
204
|
+
acc
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
150
208
|
end # class LogStash::Outputs::Graphite
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
|
3
3
|
s.name = 'logstash-output-graphite'
|
4
|
-
s.version = '1.0.
|
4
|
+
s.version = '1.0.1'
|
5
5
|
s.licenses = ['Apache License (2.0)']
|
6
6
|
s.summary = "This output allows you to pull metrics from your logs and ship them to Graphite"
|
7
7
|
s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
|
@@ -36,15 +36,25 @@ describe LogStash::Outputs::Graphite do
|
|
36
36
|
let(:event) { LogStash::Event.new("foo" => "123") }
|
37
37
|
|
38
38
|
context "match one key" do
|
39
|
-
it "generate one element" do
|
39
|
+
it "should generate one element" do
|
40
40
|
expect(server.size).to eq(1)
|
41
41
|
end
|
42
42
|
|
43
|
-
it "match the generated key" do
|
43
|
+
it "should match the generated key" do
|
44
44
|
line = server.pop
|
45
45
|
expect(line).to match(/^foo.bar.sys.data.foo 123.0 \d{10,}\n$/)
|
46
46
|
end
|
47
47
|
end
|
48
|
+
|
49
|
+
context "when matching a nested hash" do
|
50
|
+
let(:event) { LogStash::Event.new("foo" => {"a" => 3, "c" => {"d" => 2}}) }
|
51
|
+
|
52
|
+
it "should create the proper formatted lines" do
|
53
|
+
lines = [server.pop, server.pop].sort # Put key 'a' first
|
54
|
+
expect(lines[0]).to match(/^foo.bar.sys.data.foo.a 3 \d{10,}\n$/)
|
55
|
+
expect(lines[1]).to match(/^foo.bar.sys.data.foo.c.d 2 \d{10,}\n$/)
|
56
|
+
end
|
57
|
+
end
|
48
58
|
end
|
49
59
|
|
50
60
|
context "match all keys" do
|
@@ -124,6 +134,16 @@ describe LogStash::Outputs::Graphite do
|
|
124
134
|
line = server.pop
|
125
135
|
expect(line).to match(/^custom.foo 123.0 \d{10,}\n$/)
|
126
136
|
end
|
137
|
+
|
138
|
+
context "when matching a nested hash" do
|
139
|
+
let(:event) { LogStash::Event.new("custom.foo" => {"a" => 3, "c" => {"d" => 2}}) }
|
140
|
+
|
141
|
+
it "should create the proper formatted lines" do
|
142
|
+
lines = [server.pop, server.pop].sort # Put key 'a' first
|
143
|
+
expect(lines[0]).to match(/^custom.foo.a 3 \d{10,}\n$/)
|
144
|
+
expect(lines[1]).to match(/^custom.foo.c.d 2 \d{10,}\n$/)
|
145
|
+
end
|
146
|
+
end
|
127
147
|
end
|
128
148
|
end
|
129
149
|
end
|
@@ -144,4 +164,34 @@ describe LogStash::Outputs::Graphite do
|
|
144
164
|
expect(line).to match(/^foo 1.0 #{timestamp_new}\n$/)
|
145
165
|
end
|
146
166
|
end
|
167
|
+
|
168
|
+
describe "dotifying a hash" do
|
169
|
+
let(:event) { LogStash::Event.new( "metrics" => hash) }
|
170
|
+
let(:dotified) { LogStash::Outputs::Graphite.new().send(:dotify, hash) }
|
171
|
+
|
172
|
+
context "with a complex hash" do
|
173
|
+
let(:hash) { {:a => 2, :b => {:c => 3, :d => 4, :e => {:f => 5}}} }
|
174
|
+
|
175
|
+
it "should dottify correctly" do
|
176
|
+
expect(dotified).to eql({"a" => 2, "b.c" => 3, "b.d" => 4, "b.e.f" => 5})
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context "with a simple hash" do
|
181
|
+
let(:hash) { {:a => 2, 5 => 4} }
|
182
|
+
|
183
|
+
it "should do nothing more than stringify the keys" do
|
184
|
+
expect(dotified).to eql("a" => 2, "5" => 4)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "with an array value" do
|
189
|
+
let(:hash) { {:a => 2, 5 => 4, :c => [1,2,3]} }
|
190
|
+
|
191
|
+
it "should ignore array values" do
|
192
|
+
expect(dotified).to eql("a" => 2, "5" => 4)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
147
197
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-output-graphite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06
|
11
|
+
date: 2015-08-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: logstash-core
|
@@ -127,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
127
|
version: '0'
|
128
128
|
requirements: []
|
129
129
|
rubyforge_project:
|
130
|
-
rubygems_version: 2.
|
130
|
+
rubygems_version: 2.1.9
|
131
131
|
signing_key:
|
132
132
|
specification_version: 4
|
133
133
|
summary: This output allows you to pull metrics from your logs and ship them to Graphite
|