logstash-output-graphtastic 0.1.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 +15 -0
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/LICENSE +13 -0
- data/Rakefile +6 -0
- data/lib/logstash/outputs/graphtastic.rb +186 -0
- data/logstash-output-graphtastic.gemspec +26 -0
- data/rakelib/publish.rake +9 -0
- data/rakelib/vendor.rake +169 -0
- data/spec/outputs/graphtastic_spec.rb +1 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YmY2OWQ5YmJiMWNlNTRmMDcxNjBkZTg1MjJkZDUzZjhjN2E4MGYyNA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MWRiZTc5OThhMWI1N2YyMjIwM2JlOGZhNWIyODExNjVkNWE5ZmVlYQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
OTdiZTIwM2ZkNTAyMzFkMTQzNDBhYzM4NzE4MmUyYjk0MDhhYTIwNDU1ZDhj
|
10
|
+
ZDk2NzUwNjNiYjYyZDY0MWI1YTIzYjQ5MjI4NDhiMzQxMjcyMWJkNmU0ODY4
|
11
|
+
YTA1YTQ0NDczMmE2NmMwNTlkN2E3YjYxYjllZmIzZmFhNDMxZjA=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NGFjNWMzNjI1ZGE0OGQzOWYwMzBkMzdlYWIzZjY2ZWNlNmUzZDRkODNiODdm
|
14
|
+
YmE3MWJmODk5YjIyZmNhYTNkNjNmNWVmNDcyMWE0ODQzMjRmZDk0NmIwMDQ2
|
15
|
+
NjUyZWYwMDYzMzA0NTgxNDBmMjgxZDAwMGU1MGVjMmEwMDdhOTQ=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2012-2014 Elasticsearch <http://www.elasticsearch.org>
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/Rakefile
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/outputs/base"
|
3
|
+
require "logstash/namespace"
|
4
|
+
|
5
|
+
|
6
|
+
# A plugin for a newly developed Java/Spring Metrics application
|
7
|
+
# I didn't really want to code this project but I couldn't find
|
8
|
+
# a respectable alternative that would also run on any Windows
|
9
|
+
# machine - which is the problem and why I am not going with Graphite
|
10
|
+
# and statsd. This application provides multiple integration options
|
11
|
+
# so as to make its use under your network requirements possible.
|
12
|
+
# This includes a REST option that is always enabled for your use
|
13
|
+
# in case you want to write a small script to send the occasional
|
14
|
+
# metric data.
|
15
|
+
#
|
16
|
+
# Find GraphTastic here : https://github.com/NickPadilla/GraphTastic
|
17
|
+
class LogStash::Outputs::GraphTastic < LogStash::Outputs::Base
|
18
|
+
|
19
|
+
config_name "graphtastic"
|
20
|
+
milestone 2
|
21
|
+
|
22
|
+
# options are udp(fastest - default) - rmi(faster) - rest(fast) - tcp(don't use TCP yet - some problems - errors out on linux)
|
23
|
+
config :integration, :validate => ["udp","tcp","rmi","rest"], :default => "udp"
|
24
|
+
|
25
|
+
# if using rest as your end point you need to also provide the application url
|
26
|
+
# it defaults to localhost/graphtastic. You can customize the application url
|
27
|
+
# by changing the name of the .war file. There are other ways to change the
|
28
|
+
# application context, but they vary depending on the Application Server in use.
|
29
|
+
# Please consult your application server documentation for more on application
|
30
|
+
# contexts.
|
31
|
+
config :context, :validate => :string, :default => "graphtastic"
|
32
|
+
|
33
|
+
# metrics hash - you will provide a name for your metric and the metric
|
34
|
+
# data as key value pairs. so for example:
|
35
|
+
#
|
36
|
+
# metrics => { "Response" => "%{response}" }
|
37
|
+
#
|
38
|
+
# example for the logstash config
|
39
|
+
#
|
40
|
+
# metrics => [ "Response", "%{response}" ]
|
41
|
+
#
|
42
|
+
# NOTE: you can also use the dynamic fields for the key value as well as the actual value
|
43
|
+
config :metrics, :validate => :hash, :default => {}
|
44
|
+
|
45
|
+
# host for the graphtastic server - defaults to 127.0.0.1
|
46
|
+
config :host, :validate => :string, :default => "127.0.0.1"
|
47
|
+
|
48
|
+
# port for the graphtastic instance - defaults to 1199 for RMI, 1299 for TCP, 1399 for UDP, and 8080 for REST
|
49
|
+
config :port, :validate => :number
|
50
|
+
|
51
|
+
# number of attempted retry after send error - currently only way to integrate
|
52
|
+
# errored transactions - should try and save to a file or later consumption
|
53
|
+
# either by graphtastic utility or by this program after connectivity is
|
54
|
+
# ensured to be established.
|
55
|
+
config :retries, :validate => :number, :default => 1
|
56
|
+
|
57
|
+
# the number of metrics to send to GraphTastic at one time. 60 seems to be the perfect
|
58
|
+
# amount for UDP, with default packet size.
|
59
|
+
config :batch_number, :validate => :number, :default => 60
|
60
|
+
|
61
|
+
# setting allows you to specify where we save errored transactions
|
62
|
+
# this makes the most sense at this point - will need to decide
|
63
|
+
# on how we reintegrate these error metrics
|
64
|
+
# NOT IMPLEMENTED!
|
65
|
+
config :error_file, :validate => :string, :default => ""
|
66
|
+
|
67
|
+
public
|
68
|
+
def register
|
69
|
+
@batch = []
|
70
|
+
begin
|
71
|
+
if @integration.downcase == "rmi"
|
72
|
+
if RUBY_ENGINE != "jruby"
|
73
|
+
raise Exception.new("LogStash::Outputs::GraphTastic# JRuby is needed for RMI to work!")
|
74
|
+
end
|
75
|
+
require "java"
|
76
|
+
if @port.nil?
|
77
|
+
@port = 1199
|
78
|
+
end
|
79
|
+
registry = java.rmi.registry.LocateRegistry.getRegistry(@host, @port);
|
80
|
+
@remote = registry.lookup("RmiMetricService")
|
81
|
+
elsif @integration.downcase == "rest"
|
82
|
+
require "net/http"
|
83
|
+
if @port.nil?
|
84
|
+
@port = 8080
|
85
|
+
gem "mail" #outputs/email, # License: MIT License
|
86
|
+
end
|
87
|
+
@http = Net::HTTP.new(@host, @port)
|
88
|
+
end
|
89
|
+
@logger.info("GraphTastic Output Successfully Registered! Using #{@integration} Integration!")
|
90
|
+
rescue
|
91
|
+
@logger.error("*******ERROR : #{$!}")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
public
|
96
|
+
def receive(event)
|
97
|
+
return unless output?(event)
|
98
|
+
# Set Intersection - returns a new array with the items that are the same between the two
|
99
|
+
if !@tags.empty? && (event["tags"] & @tags).size == 0
|
100
|
+
# Skip events that have no tags in common with what we were configured
|
101
|
+
@logger.debug("No Tags match for GraphTastic Output!")
|
102
|
+
return
|
103
|
+
end
|
104
|
+
@retry = 1
|
105
|
+
@logger.debug("Event found for GraphTastic!", :tags => @tags, :event => event)
|
106
|
+
@metrics.each do |name, metric|
|
107
|
+
postMetric(event.sprintf(name),event.sprintf(metric),(event["@timestamp"]*1000))# unix_timestamp is what I need in seconds - multiply by 1000 to make milliseconds.
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def postMetric(name, metric, timestamp)
|
112
|
+
message = name+","+metric+","+timestamp.to_s
|
113
|
+
if @batch.length < @batch_number
|
114
|
+
@batch.push(message)
|
115
|
+
else
|
116
|
+
flushMetrics()
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def flushMetrics()
|
121
|
+
begin
|
122
|
+
if @integration.downcase == "tcp"
|
123
|
+
flushViaTCP()
|
124
|
+
elsif @integration.downcase == "rmi"
|
125
|
+
flushViaRMI()
|
126
|
+
elsif @integration.downcase == "udp"
|
127
|
+
flushViaUDP()
|
128
|
+
elsif @integration.downcase == "rest"
|
129
|
+
flushViaREST()
|
130
|
+
else
|
131
|
+
@logger.error("GraphTastic Not Able To Find Correct Integration - Nothing Sent - Integration Type : ", :@integration => @integration)
|
132
|
+
end
|
133
|
+
@batch.clear
|
134
|
+
rescue
|
135
|
+
@logger.error("*******ERROR : #{$!}")
|
136
|
+
@logger.info("*******Attempting #{@retry} out of #{@retries}")
|
137
|
+
while @retry < @retries
|
138
|
+
@retry = @retry + 1
|
139
|
+
flushMetrics()
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# send metrics via udp
|
145
|
+
def flushViaUDP()
|
146
|
+
if @port.nil?
|
147
|
+
@port = 1399
|
148
|
+
end
|
149
|
+
udpsocket.send(@batch.join(','), 0, @host, @port)
|
150
|
+
@logger.debug("GraphTastic Sent Message Using UDP : #{@batch.join(',')}")
|
151
|
+
end
|
152
|
+
|
153
|
+
# send metrics via REST
|
154
|
+
def flushViaREST()
|
155
|
+
request = Net::HTTP::Put.new("/#{@context}/addMetric/#{@batch.join(',')}")
|
156
|
+
response = @http.request(request)
|
157
|
+
if response == 'ERROR'
|
158
|
+
raise 'Error happend when sending metric to GraphTastic using REST!'
|
159
|
+
end
|
160
|
+
@logger.debug("GraphTastic Sent Message Using REST : #{@batch.join(',')}", :response => response.inspect)
|
161
|
+
end
|
162
|
+
|
163
|
+
# send metrics via RMI
|
164
|
+
def flushViaRMI()
|
165
|
+
if RUBY_ENGINE != "jruby"
|
166
|
+
raise Exception.new("LogStash::Outputs::GraphTastic# JRuby is needed for RMI to work!")
|
167
|
+
end
|
168
|
+
@remote.insertMetrics(@batch.join(','))
|
169
|
+
@logger.debug("GraphTastic Sent Message Using RMI : #{@batch.join(',')}")
|
170
|
+
end
|
171
|
+
|
172
|
+
# send metrics via tcp
|
173
|
+
def flushViaTCP()
|
174
|
+
# to correctly read the line we need to ensure we send \r\n at the end of every message.
|
175
|
+
if @port.nil?
|
176
|
+
@port = 1299
|
177
|
+
end
|
178
|
+
tcpsocket = TCPSocket.open(@host, @port)
|
179
|
+
tcpsocket.send(@batch.join(',')+"\r\n", 0)
|
180
|
+
tcpsocket.close
|
181
|
+
@logger.debug("GraphTastic Sent Message Using TCP : #{@batch.join(',')}")
|
182
|
+
end
|
183
|
+
|
184
|
+
def udpsocket; @socket ||= UDPSocket.new end
|
185
|
+
|
186
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
|
3
|
+
s.name = 'logstash-output-graphtastic'
|
4
|
+
s.version = '0.1.0'
|
5
|
+
s.licenses = ['Apache License (2.0)']
|
6
|
+
s.summary = "Send metrics to GraphTastic"
|
7
|
+
s.description = "Send metrics to GraphTastic"
|
8
|
+
s.authors = ["Elasticsearch"]
|
9
|
+
s.email = 'richard.pijnenburg@elasticsearch.com'
|
10
|
+
s.homepage = "http://logstash.net/"
|
11
|
+
s.require_paths = ["lib"]
|
12
|
+
|
13
|
+
# Files
|
14
|
+
s.files = `git ls-files`.split($\)+::Dir.glob('vendor/*')
|
15
|
+
|
16
|
+
# Tests
|
17
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
18
|
+
|
19
|
+
# Special flag to let us know this is actually a logstash plugin
|
20
|
+
s.metadata = { "logstash_plugin" => "true", "group" => "output" }
|
21
|
+
|
22
|
+
# Gem dependencies
|
23
|
+
s.add_runtime_dependency 'logstash', '>= 1.4.0', '< 2.0.0'
|
24
|
+
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require "gem_publisher"
|
2
|
+
|
3
|
+
desc "Publish gem to RubyGems.org"
|
4
|
+
task :publish_gem do |t|
|
5
|
+
gem_file = Dir.glob(File.expand_path('../*.gemspec',File.dirname(__FILE__))).first
|
6
|
+
gem = GemPublisher.publish_if_updated(gem_file, :rubygems)
|
7
|
+
puts "Published #{gem}" if gem
|
8
|
+
end
|
9
|
+
|
data/rakelib/vendor.rake
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "uri"
|
3
|
+
require "digest/sha1"
|
4
|
+
|
5
|
+
def vendor(*args)
|
6
|
+
return File.join("vendor", *args)
|
7
|
+
end
|
8
|
+
|
9
|
+
directory "vendor/" => ["vendor"] do |task, args|
|
10
|
+
mkdir task.name
|
11
|
+
end
|
12
|
+
|
13
|
+
def fetch(url, sha1, output)
|
14
|
+
|
15
|
+
puts "Downloading #{url}"
|
16
|
+
actual_sha1 = download(url, output)
|
17
|
+
|
18
|
+
if actual_sha1 != sha1
|
19
|
+
fail "SHA1 does not match (expected '#{sha1}' but got '#{actual_sha1}')"
|
20
|
+
end
|
21
|
+
end # def fetch
|
22
|
+
|
23
|
+
def file_fetch(url, sha1)
|
24
|
+
filename = File.basename( URI(url).path )
|
25
|
+
output = "vendor/#{filename}"
|
26
|
+
task output => [ "vendor/" ] do
|
27
|
+
begin
|
28
|
+
actual_sha1 = file_sha1(output)
|
29
|
+
if actual_sha1 != sha1
|
30
|
+
fetch(url, sha1, output)
|
31
|
+
end
|
32
|
+
rescue Errno::ENOENT
|
33
|
+
fetch(url, sha1, output)
|
34
|
+
end
|
35
|
+
end.invoke
|
36
|
+
|
37
|
+
return output
|
38
|
+
end
|
39
|
+
|
40
|
+
def file_sha1(path)
|
41
|
+
digest = Digest::SHA1.new
|
42
|
+
fd = File.new(path, "r")
|
43
|
+
while true
|
44
|
+
begin
|
45
|
+
digest << fd.sysread(16384)
|
46
|
+
rescue EOFError
|
47
|
+
break
|
48
|
+
end
|
49
|
+
end
|
50
|
+
return digest.hexdigest
|
51
|
+
ensure
|
52
|
+
fd.close if fd
|
53
|
+
end
|
54
|
+
|
55
|
+
def download(url, output)
|
56
|
+
uri = URI(url)
|
57
|
+
digest = Digest::SHA1.new
|
58
|
+
tmp = "#{output}.tmp"
|
59
|
+
Net::HTTP.start(uri.host, uri.port, :use_ssl => (uri.scheme == "https")) do |http|
|
60
|
+
request = Net::HTTP::Get.new(uri.path)
|
61
|
+
http.request(request) do |response|
|
62
|
+
fail "HTTP fetch failed for #{url}. #{response}" if [200, 301].include?(response.code)
|
63
|
+
size = (response["content-length"].to_i || -1).to_f
|
64
|
+
count = 0
|
65
|
+
File.open(tmp, "w") do |fd|
|
66
|
+
response.read_body do |chunk|
|
67
|
+
fd.write(chunk)
|
68
|
+
digest << chunk
|
69
|
+
if size > 0 && $stdout.tty?
|
70
|
+
count += chunk.bytesize
|
71
|
+
$stdout.write(sprintf("\r%0.2f%%", count/size * 100))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
$stdout.write("\r \r") if $stdout.tty?
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
File.rename(tmp, output)
|
80
|
+
|
81
|
+
return digest.hexdigest
|
82
|
+
rescue SocketError => e
|
83
|
+
puts "Failure while downloading #{url}: #{e}"
|
84
|
+
raise
|
85
|
+
ensure
|
86
|
+
File.unlink(tmp) if File.exist?(tmp)
|
87
|
+
end # def download
|
88
|
+
|
89
|
+
def untar(tarball, &block)
|
90
|
+
require "archive/tar/minitar"
|
91
|
+
tgz = Zlib::GzipReader.new(File.open(tarball))
|
92
|
+
# Pull out typesdb
|
93
|
+
tar = Archive::Tar::Minitar::Input.open(tgz)
|
94
|
+
tar.each do |entry|
|
95
|
+
path = block.call(entry)
|
96
|
+
next if path.nil?
|
97
|
+
parent = File.dirname(path)
|
98
|
+
|
99
|
+
mkdir_p parent unless File.directory?(parent)
|
100
|
+
|
101
|
+
# Skip this file if the output file is the same size
|
102
|
+
if entry.directory?
|
103
|
+
mkdir path unless File.directory?(path)
|
104
|
+
else
|
105
|
+
entry_mode = entry.instance_eval { @mode } & 0777
|
106
|
+
if File.exists?(path)
|
107
|
+
stat = File.stat(path)
|
108
|
+
# TODO(sissel): Submit a patch to archive-tar-minitar upstream to
|
109
|
+
# expose headers in the entry.
|
110
|
+
entry_size = entry.instance_eval { @size }
|
111
|
+
# If file sizes are same, skip writing.
|
112
|
+
next if stat.size == entry_size && (stat.mode & 0777) == entry_mode
|
113
|
+
end
|
114
|
+
puts "Extracting #{entry.full_name} from #{tarball} #{entry_mode.to_s(8)}"
|
115
|
+
File.open(path, "w") do |fd|
|
116
|
+
# eof? check lets us skip empty files. Necessary because the API provided by
|
117
|
+
# Archive::Tar::Minitar::Reader::EntryStream only mostly acts like an
|
118
|
+
# IO object. Something about empty files in this EntryStream causes
|
119
|
+
# IO.copy_stream to throw "can't convert nil into String" on JRuby
|
120
|
+
# TODO(sissel): File a bug about this.
|
121
|
+
while !entry.eof?
|
122
|
+
chunk = entry.read(16384)
|
123
|
+
fd.write(chunk)
|
124
|
+
end
|
125
|
+
#IO.copy_stream(entry, fd)
|
126
|
+
end
|
127
|
+
File.chmod(entry_mode, path)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
tar.close
|
131
|
+
File.unlink(tarball) if File.file?(tarball)
|
132
|
+
end # def untar
|
133
|
+
|
134
|
+
def ungz(file)
|
135
|
+
|
136
|
+
outpath = file.gsub('.gz', '')
|
137
|
+
tgz = Zlib::GzipReader.new(File.open(file))
|
138
|
+
begin
|
139
|
+
File.open(outpath, "w") do |out|
|
140
|
+
IO::copy_stream(tgz, out)
|
141
|
+
end
|
142
|
+
File.unlink(file)
|
143
|
+
rescue
|
144
|
+
File.unlink(outpath) if File.file?(outpath)
|
145
|
+
raise
|
146
|
+
end
|
147
|
+
tgz.close
|
148
|
+
end
|
149
|
+
|
150
|
+
desc "Process any vendor files required for this plugin"
|
151
|
+
task "vendor" do |task, args|
|
152
|
+
|
153
|
+
@files.each do |file|
|
154
|
+
download = file_fetch(file['url'], file['sha1'])
|
155
|
+
if download =~ /.tar.gz/
|
156
|
+
prefix = download.gsub('.tar.gz', '').gsub('vendor/', '')
|
157
|
+
untar(download) do |entry|
|
158
|
+
if !file['files'].nil?
|
159
|
+
next unless file['files'].include?(entry.full_name.gsub(prefix, ''))
|
160
|
+
out = entry.full_name.split("/").last
|
161
|
+
end
|
162
|
+
File.join('vendor', out)
|
163
|
+
end
|
164
|
+
elsif download =~ /.gz/
|
165
|
+
ungz(download)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'spec_helper'
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: logstash-output-graphtastic
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Elasticsearch
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: logstash
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.4.0
|
20
|
+
- - <
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.0.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.4.0
|
30
|
+
- - <
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.0
|
33
|
+
description: Send metrics to GraphTastic
|
34
|
+
email: richard.pijnenburg@elasticsearch.com
|
35
|
+
executables: []
|
36
|
+
extensions: []
|
37
|
+
extra_rdoc_files: []
|
38
|
+
files:
|
39
|
+
- .gitignore
|
40
|
+
- Gemfile
|
41
|
+
- LICENSE
|
42
|
+
- Rakefile
|
43
|
+
- lib/logstash/outputs/graphtastic.rb
|
44
|
+
- logstash-output-graphtastic.gemspec
|
45
|
+
- rakelib/publish.rake
|
46
|
+
- rakelib/vendor.rake
|
47
|
+
- spec/outputs/graphtastic_spec.rb
|
48
|
+
homepage: http://logstash.net/
|
49
|
+
licenses:
|
50
|
+
- Apache License (2.0)
|
51
|
+
metadata:
|
52
|
+
logstash_plugin: 'true'
|
53
|
+
group: output
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
requirements: []
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 2.4.1
|
71
|
+
signing_key:
|
72
|
+
specification_version: 4
|
73
|
+
summary: Send metrics to GraphTastic
|
74
|
+
test_files:
|
75
|
+
- spec/outputs/graphtastic_spec.rb
|