logstash-output-sumologic 1.0.4 → 1.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 +4 -4
- data/CHANGELOG.md +4 -22
- data/DEVELOPER.md +25 -0
- data/README.md +50 -39
- data/lib/logstash/outputs/sumologic.rb +266 -41
- data/lib/logstash/plugin_mixins/http_client.rb +187 -0
- data/logstash-output-sumologic.gemspec +5 -5
- data/spec/outputs/sumologic_spec.rb +340 -9
- data/spec/spec_helper.rb +53 -0
- metadata +31 -30
@@ -0,0 +1,187 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/config/mixin"
|
3
|
+
|
4
|
+
# This module makes it easy to add a very fully configured HTTP client to logstash
|
5
|
+
# based on [Manticore](https://github.com/cheald/manticore).
|
6
|
+
# For an example of its usage see https://github.com/logstash-plugins/logstash-input-http_poller
|
7
|
+
module LogStash::PluginMixins::HttpClient
|
8
|
+
class InvalidHTTPConfigError < StandardError; end
|
9
|
+
|
10
|
+
def self.included(base)
|
11
|
+
require 'manticore'
|
12
|
+
base.extend(self)
|
13
|
+
base.setup_http_client_config
|
14
|
+
end
|
15
|
+
|
16
|
+
public
|
17
|
+
def setup_http_client_config
|
18
|
+
# Timeout (in seconds) for the entire request
|
19
|
+
config :request_timeout, :validate => :number, :default => 60
|
20
|
+
|
21
|
+
# Timeout (in seconds) to wait for data on the socket. Default is `10s`
|
22
|
+
config :socket_timeout, :validate => :number, :default => 10
|
23
|
+
|
24
|
+
# Timeout (in seconds) to wait for a connection to be established. Default is `10s`
|
25
|
+
config :connect_timeout, :validate => :number, :default => 10
|
26
|
+
|
27
|
+
# Should redirects be followed? Defaults to `true`
|
28
|
+
config :follow_redirects, :validate => :boolean, :default => true
|
29
|
+
|
30
|
+
# Max number of concurrent connections. Defaults to `50`
|
31
|
+
config :pool_max, :validate => :number, :default => 50
|
32
|
+
|
33
|
+
# Max number of concurrent connections to a single host. Defaults to `25`
|
34
|
+
config :pool_max_per_route, :validate => :number, :default => 25
|
35
|
+
|
36
|
+
# Turn this on to enable HTTP keepalive support. We highly recommend setting `automatic_retries` to at least
|
37
|
+
# one with this to fix interactions with broken keepalive implementations.
|
38
|
+
config :keepalive, :validate => :boolean, :default => true
|
39
|
+
|
40
|
+
# How many times should the client retry a failing URL. We highly recommend NOT setting this value
|
41
|
+
# to zero if keepalive is enabled. Some servers incorrectly end keepalives early requiring a retry!
|
42
|
+
# Note: if `retry_non_idempotent` is set only GET, HEAD, PUT, DELETE, OPTIONS, and TRACE requests will be retried.
|
43
|
+
config :automatic_retries, :validate => :number, :default => 1
|
44
|
+
|
45
|
+
# If `automatic_retries` is enabled this will cause non-idempotent HTTP verbs (such as POST) to be retried.
|
46
|
+
config :retry_non_idempotent, :validate => :boolean, :default => false
|
47
|
+
|
48
|
+
# How long to wait before checking if the connection is stale before executing a request on a connection using keepalive.
|
49
|
+
# # You may want to set this lower, possibly to 0 if you get connection errors regularly
|
50
|
+
# Quoting the Apache commons docs (this client is based Apache Commmons):
|
51
|
+
# 'Defines period of inactivity in milliseconds after which persistent connections must be re-validated prior to being leased to the consumer. Non-positive value passed to this method disables connection validation. This check helps detect connections that have become stale (half-closed) while kept inactive in the pool.'
|
52
|
+
# See https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.html#setValidateAfterInactivity(int)[these docs for more info]
|
53
|
+
config :validate_after_inactivity, :validate => :number, :default => 200
|
54
|
+
|
55
|
+
config :ssl_certificate_validation, :deprecated => "This never worked correctly and is now deprecated and a noop"
|
56
|
+
|
57
|
+
# If you need to use a custom X.509 CA (.pem certs) specify the path to that here
|
58
|
+
config :cacert, :validate => :path
|
59
|
+
|
60
|
+
# If you'd like to use a client certificate (note, most people don't want this) set the path to the x509 cert here
|
61
|
+
config :client_cert, :validate => :path
|
62
|
+
# If you're using a client certificate specify the path to the encryption key here
|
63
|
+
config :client_key, :validate => :path
|
64
|
+
|
65
|
+
# If you need to use a custom keystore (`.jks`) specify that here. This does not work with .pem keys!
|
66
|
+
config :keystore, :validate => :path
|
67
|
+
|
68
|
+
# Specify the keystore password here.
|
69
|
+
# Note, most .jks files created with keytool require a password!
|
70
|
+
config :keystore_password, :validate => :password
|
71
|
+
|
72
|
+
# Specify the keystore type here. One of `JKS` or `PKCS12`. Default is `JKS`
|
73
|
+
config :keystore_type, :validate => :string, :default => "JKS"
|
74
|
+
|
75
|
+
# If you need to use a custom truststore (`.jks`) specify that here. This does not work with .pem certs!
|
76
|
+
config :truststore, :validate => :path
|
77
|
+
|
78
|
+
# Specify the truststore password here.
|
79
|
+
# Note, most .jks files created with keytool require a password!
|
80
|
+
config :truststore_password, :validate => :password
|
81
|
+
|
82
|
+
# Specify the truststore type here. One of `JKS` or `PKCS12`. Default is `JKS`
|
83
|
+
config :truststore_type, :validate => :string, :default => "JKS"
|
84
|
+
|
85
|
+
# Enable cookie support. With this enabled the client will persist cookies
|
86
|
+
# across requests as a normal web browser would. Enabled by default
|
87
|
+
config :cookies, :validate => :boolean, :default => true
|
88
|
+
|
89
|
+
# If you'd like to use an HTTP proxy . This supports multiple configuration syntaxes:
|
90
|
+
#
|
91
|
+
# 1. Proxy host in form: `http://proxy.org:1234`
|
92
|
+
# 2. Proxy host in form: `{host => "proxy.org", port => 80, scheme => 'http', user => 'username@host', password => 'password'}`
|
93
|
+
# 3. Proxy host in form: `{url => 'http://proxy.org:1234', user => 'username@host', password => 'password'}`
|
94
|
+
config :proxy
|
95
|
+
|
96
|
+
# Username to use for HTTP auth.
|
97
|
+
config :user, :validate => :string
|
98
|
+
|
99
|
+
# Password to use for HTTP auth
|
100
|
+
config :password, :validate => :password
|
101
|
+
end
|
102
|
+
|
103
|
+
public
|
104
|
+
def client_config
|
105
|
+
c = {
|
106
|
+
connect_timeout: @connect_timeout,
|
107
|
+
socket_timeout: @socket_timeout,
|
108
|
+
request_timeout: @request_timeout,
|
109
|
+
follow_redirects: @follow_redirects,
|
110
|
+
automatic_retries: @automatic_retries,
|
111
|
+
retry_non_idempotent: @retry_non_idempotent,
|
112
|
+
check_connection_timeout: @validate_after_inactivity,
|
113
|
+
pool_max: @pool_max,
|
114
|
+
pool_max_per_route: @pool_max_per_route,
|
115
|
+
cookies: @cookies,
|
116
|
+
keepalive: @keepalive
|
117
|
+
}
|
118
|
+
|
119
|
+
if @proxy
|
120
|
+
# Symbolize keys if necessary
|
121
|
+
c[:proxy] = @proxy.is_a?(Hash) ?
|
122
|
+
@proxy.reduce({}) {|memo,(k,v)| memo[k.to_sym] = v; memo} :
|
123
|
+
@proxy
|
124
|
+
end
|
125
|
+
|
126
|
+
if @user
|
127
|
+
if !@password || !@password.value
|
128
|
+
raise ::LogStash::ConfigurationError, "User '#{@user}' specified without password!"
|
129
|
+
end
|
130
|
+
|
131
|
+
# Symbolize keys if necessary
|
132
|
+
c[:auth] = {
|
133
|
+
:user => @user,
|
134
|
+
:password => @password.value,
|
135
|
+
:eager => true
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
c[:ssl] = {}
|
140
|
+
if @cacert
|
141
|
+
c[:ssl][:ca_file] = @cacert
|
142
|
+
end
|
143
|
+
|
144
|
+
if @truststore
|
145
|
+
c[:ssl].merge!(
|
146
|
+
:truststore => @truststore,
|
147
|
+
:truststore_type => @truststore_type,
|
148
|
+
:truststore_password => @truststore_password.value
|
149
|
+
)
|
150
|
+
|
151
|
+
if c[:ssl][:truststore_password].nil?
|
152
|
+
raise LogStash::ConfigurationError, "Truststore declared without a password! This is not valid, please set the 'truststore_password' option"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
if @keystore
|
157
|
+
c[:ssl].merge!(
|
158
|
+
:keystore => @keystore,
|
159
|
+
:keystore_type => @keystore_type,
|
160
|
+
:keystore_password => @keystore_password.value
|
161
|
+
)
|
162
|
+
|
163
|
+
if c[:ssl][:keystore_password].nil?
|
164
|
+
raise LogStash::ConfigurationError, "Keystore declared without a password! This is not valid, please set the 'keystore_password' option"
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
if @client_cert && @client_key
|
169
|
+
c[:ssl][:client_cert] = @client_cert
|
170
|
+
c[:ssl][:client_key] = @client_key
|
171
|
+
elsif !!@client_cert ^ !!@client_key
|
172
|
+
raise InvalidHTTPConfigError, "You must specify both client_cert and client_key for an HTTP client, or neither!"
|
173
|
+
end
|
174
|
+
|
175
|
+
c
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
def make_client
|
180
|
+
Manticore::Client.new(client_config)
|
181
|
+
end
|
182
|
+
|
183
|
+
public
|
184
|
+
def client
|
185
|
+
@client ||= make_client
|
186
|
+
end
|
187
|
+
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "logstash-output-sumologic"
|
3
|
-
s.version = "1.0
|
3
|
+
s.version = "1.1.0"
|
4
4
|
s.licenses = ["Apache-2.0"]
|
5
5
|
s.summary = "Deliever the log to Sumo Logic cloud service."
|
6
|
-
s.description = "This gem is a Logstash output plugin to deliver the log to Sumo Logic cloud service. Go to https://github.com/SumoLogic/logstash-output-sumologic for getting help, reporting issues, etc."
|
6
|
+
s.description = "This gem is a Logstash output plugin to deliver the log or metrics to Sumo Logic cloud service. Go to https://github.com/SumoLogic/logstash-output-sumologic for getting help, reporting issues, etc."
|
7
7
|
s.authors = ["Sumo Logic"]
|
8
|
-
s.email = "
|
8
|
+
s.email = "collection@sumologic.com "
|
9
9
|
s.homepage = "https://github.com/SumoLogic/logstash-output-sumologic"
|
10
10
|
s.require_paths = ["lib"]
|
11
11
|
|
@@ -19,6 +19,6 @@ Gem::Specification.new do |s|
|
|
19
19
|
|
20
20
|
# Gem dependencies
|
21
21
|
s.add_runtime_dependency "logstash-core-plugin-api", "~> 2.0"
|
22
|
-
s.add_runtime_dependency "logstash-codec-plain"
|
23
|
-
s.add_development_dependency "logstash-devutils"
|
22
|
+
s.add_runtime_dependency "logstash-codec-plain", "~> 0"
|
23
|
+
s.add_development_dependency "logstash-devutils", "~> 0"
|
24
24
|
end
|
@@ -1,22 +1,353 @@
|
|
1
|
+
|
1
2
|
# encoding: utf-8
|
2
3
|
require "logstash/devutils/rspec/spec_helper"
|
3
4
|
require "logstash/outputs/sumologic"
|
4
|
-
require "logstash/codecs/plain"
|
5
5
|
require "logstash/event"
|
6
6
|
|
7
|
+
require_relative '../spec_helper'
|
8
|
+
|
7
9
|
describe LogStash::Outputs::SumoLogic do
|
8
|
-
let(:sample_event) { LogStash::Event.new }
|
9
|
-
let(:output) { LogStash::Outputs::SumoLogic.new }
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
let(:server) { subject.server }
|
12
|
+
|
13
|
+
before :each do
|
14
|
+
subject.register
|
15
|
+
subject.receive(event)
|
16
|
+
end
|
17
|
+
|
18
|
+
# For log
|
19
|
+
context "log sent in default format" do
|
20
|
+
|
21
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234") }
|
22
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
|
23
|
+
|
24
|
+
it "generate one element" do
|
25
|
+
expect(server.size).to eq(1)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "include all content" do
|
29
|
+
expect(server.pop).to include("myHost Hello world")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
context "log sent as @json" do
|
35
|
+
|
36
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "format" => "%{@json}") }
|
37
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
|
38
|
+
|
39
|
+
it "generate one element" do
|
40
|
+
expect(server.size).to eq(1)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "include all content" do
|
44
|
+
received = server.pop
|
45
|
+
expect(received).to include("\"host\":\"myHost\"")
|
46
|
+
expect(received).to include("\"message\":\"Hello world\"")
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
context "log sent in customized format" do
|
52
|
+
|
53
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "format" => "%{foo} %{bar}" ) }
|
54
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
|
55
|
+
|
56
|
+
it "generate one element" do
|
57
|
+
expect(server.size).to eq(1)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "include all content" do
|
61
|
+
expect(server.pop).to eq("fancy 24")
|
62
|
+
end
|
63
|
+
|
13
64
|
end
|
14
65
|
|
15
|
-
|
16
|
-
|
66
|
+
context "log sent with customized json_mapping" do
|
67
|
+
|
68
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "format" => "%{host} %{@json}", "json_mapping" => { "foo" => "%{foo}", "bar" => "%{bar}", "%{foo}" => "%{bar}" } ) }
|
69
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
|
70
|
+
|
71
|
+
it "generate one element" do
|
72
|
+
expect(server.size).to eq(1)
|
73
|
+
end
|
17
74
|
|
18
|
-
it "
|
19
|
-
expect(
|
75
|
+
it "include all content" do
|
76
|
+
expect(server.pop).to eq("myHost {\"foo\":\"fancy\",\"bar\":\"24\",\"fancy\":\"24\"}")
|
20
77
|
end
|
78
|
+
|
21
79
|
end
|
80
|
+
|
81
|
+
# For headers
|
82
|
+
context "check default headers" do
|
83
|
+
|
84
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234") }
|
85
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
|
86
|
+
|
87
|
+
it "check header" do
|
88
|
+
expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip, "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"text/plain"})
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
context "override source_category" do
|
94
|
+
|
95
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "source_category" => "my source category") }
|
96
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
|
97
|
+
|
98
|
+
it "check header" do
|
99
|
+
expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip, "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"text/plain", "X-Sumo-Category"=>"my source category"})
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
context "override source_name" do
|
105
|
+
|
106
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "source_name" => "my source name") }
|
107
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
|
108
|
+
|
109
|
+
it "check header" do
|
110
|
+
expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip, "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"text/plain", "X-Sumo-Name"=>"my source name"})
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
context "override source_host" do
|
116
|
+
|
117
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "source_host" => "my source host") }
|
118
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
|
119
|
+
|
120
|
+
it "check header" do
|
121
|
+
expect(server.header).to eq({"X-Sumo-Host"=>"my source host", "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"text/plain"})
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
context "with extra_headers" do
|
127
|
+
|
128
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "extra_headers" => {"foo" => "bar"}) }
|
129
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
|
130
|
+
|
131
|
+
it "check header" do
|
132
|
+
expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip, "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"text/plain", "foo"=>"bar"})
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
context "with compress" do
|
138
|
+
|
139
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "compress" => true) }
|
140
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
|
141
|
+
|
142
|
+
it "check header" do
|
143
|
+
expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip, "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"text/plain", "Content-Encoding"=>"deflate"})
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
context "with gzip" do
|
149
|
+
|
150
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "compress" => true, "compress_encoding"=>"gzip") }
|
151
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "message" => "Hello world") }
|
152
|
+
|
153
|
+
it "check header" do
|
154
|
+
expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip, "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"text/plain", "Content-Encoding"=>"gzip"})
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
# For metrics
|
160
|
+
context "with metrics sent in graphite" do
|
161
|
+
|
162
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "metrics" => { "hurray.%{foo}" => "%{bar}"}, "metrics_format" => "graphite") }
|
163
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
|
164
|
+
|
165
|
+
it "generate one element" do
|
166
|
+
expect(server.size).to eq(1)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "check header" do
|
170
|
+
expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip, "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"application/vnd.sumologic.graphite"})
|
171
|
+
end
|
172
|
+
|
173
|
+
it "include all content" do
|
174
|
+
expect(server.pop).to match(/^hurray.fancy 24 \d{10,}$/)
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
context "with metrics sent in carbon2" do
|
180
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "metrics" => { "hurray.%{foo}" => "%{bar}" }) }
|
181
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
|
182
|
+
|
183
|
+
it "generate one element" do
|
184
|
+
expect(server.size).to eq(1)
|
185
|
+
end
|
186
|
+
|
187
|
+
it "check header" do
|
188
|
+
expect(server.header).to eq({"X-Sumo-Host"=>`hostname`.strip, "X-Sumo-Client"=>"logstash-output-sumologic", "Content-Type"=>"application/vnd.sumologic.carbon2"})
|
189
|
+
end
|
190
|
+
|
191
|
+
it "include all content" do
|
192
|
+
expect(server.pop).to match(/^metric=hurray.fancy 24 \d{10,}$/)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context "with metrics_name override" do
|
197
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "metrics" => { "hurray.%{foo}" => "%{bar}" }, "metrics_name" => "mynamespace.*") }
|
198
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
|
199
|
+
|
200
|
+
it "include all content" do
|
201
|
+
expect(server.pop).to match(/^metric=mynamespace.hurray.fancy 24 \d{10,}$/)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
context "with intrinsic_tags override" do
|
206
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "metrics" => { "bar" => "%{bar}" }, "intrinsic_tags" => {"host"=>"%{host}"}) }
|
207
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
|
208
|
+
|
209
|
+
it "include all content" do
|
210
|
+
expect(server.pop).to match(/^host=myHost metric=bar 24 \d{10,}$/)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
context "with meta_tags override" do
|
215
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "metrics" => { "bar" => "%{bar}" }, "intrinsic_tags" => {"host"=>"%{host}"}, "meta_tags" => {"foo" => "%{foo}"}) }
|
216
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "bar" => 24) }
|
217
|
+
|
218
|
+
it "include all content" do
|
219
|
+
expect(server.pop).to match(/^host=myHost metric=bar foo=fancy 24 \d{10,}$/)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
context "with multiple metrics mapping" do
|
224
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "metrics" => { "cpu1" => "%{cpu1}", "cpu2" => "%{cpu2}" }, "intrinsic_tags" => {"host"=>"%{host}"}, "meta_tags" => {"foo" => "%{foo}"}) }
|
225
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "cpu1" => 0.24, "cpu2" => 0.11) }
|
226
|
+
|
227
|
+
it "include content" do
|
228
|
+
expect(server.pop).to match(/^host=myHost metric=cpu1 foo=fancy 0\.24 \d{10,}$/)
|
229
|
+
expect(server.pop).to match(/^host=myHost metric=cpu2 foo=fancy 0\.11 \d{10,}$/)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
context "metrics with non-number value should be dropped (carbon2)" do
|
234
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "metrics" => { "cpu1" => "%{cpu1}", "cpu2" => "%{cpu2}", "cpu3" => "%{cpu3}" }, "intrinsic_tags" => {"host"=>"%{host}"}, "meta_tags" => {"foo" => "%{foo}"}) }
|
235
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "cpu1" => 0.24, "cpu2" => "abc", "cpu3" => 0.11) }
|
236
|
+
|
237
|
+
it "include content" do
|
238
|
+
expect(server.pop).to match(/^host=myHost metric=cpu1 foo=fancy 0\.24 \d{10,}$/)
|
239
|
+
expect(server.pop).to match(/^host=myHost metric=cpu3 foo=fancy 0\.11 \d{10,}$/)
|
240
|
+
expect(server.empty?).to eq(true)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
context "metrics with non-number value should be dropped (graphite)" do
|
245
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "metrics" => { "cpu1" => "%{cpu1}", "cpu2" => "%{cpu2}", "cpu3" => "%{cpu3}" }, "metrics_format" => "graphite") }
|
246
|
+
let(:event) { LogStash::Event.new("host" => "myHost", "foo" => "fancy", "cpu1" => 0.24, "cpu2" => "abc", "cpu3" => 0.11) }
|
247
|
+
|
248
|
+
it "include content" do
|
249
|
+
expect(server.pop).to match(/^cpu1 0\.24 \d{10,}$/)
|
250
|
+
expect(server.pop).to match(/^cpu3 0\.11 \d{10,}$/)
|
251
|
+
expect(server.empty?).to eq(true)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
context "fields_as_metrics (carbon2)" do
|
256
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "fields_as_metrics" => true, "intrinsic_tags" => {"host"=>"%{host}"}, "meta_tags" => {"foo" => "%{foo}"}) }
|
257
|
+
let(:event) { LogStash::Event.new(
|
258
|
+
"host" => "myHost",
|
259
|
+
"foo" => "fancy",
|
260
|
+
"cpu" => [0.24, 0.11, 0.75, 0.28],
|
261
|
+
"storageRW" => 51,
|
262
|
+
"bar" => "blahblah",
|
263
|
+
"blkio" => {
|
264
|
+
"write_ps" => 5,
|
265
|
+
"read_ps" => 2,
|
266
|
+
"total_ps" => 0
|
267
|
+
})}
|
268
|
+
|
269
|
+
it "include content" do
|
270
|
+
expect(server.pop).to match(/^host=myHost metric=blkio\.write_ps foo=fancy 5 \d{10,}$/)
|
271
|
+
expect(server.pop).to match(/^host=myHost metric=blkio\.read_ps foo=fancy 2 \d{10,}$/)
|
272
|
+
expect(server.pop).to match(/^host=myHost metric=blkio\.total_ps foo=fancy 0 \d{10,}$/)
|
273
|
+
expect(server.pop).to match(/^host=myHost metric=cpu\.0 foo=fancy 0\.24 \d{10,}$/)
|
274
|
+
expect(server.pop).to match(/^host=myHost metric=cpu\.1 foo=fancy 0\.11 \d{10,}$/)
|
275
|
+
expect(server.pop).to match(/^host=myHost metric=cpu\.2 foo=fancy 0\.75 \d{10,}$/)
|
276
|
+
expect(server.pop).to match(/^host=myHost metric=cpu\.3 foo=fancy 0\.28 \d{10,}$/)
|
277
|
+
expect(server.pop).to match(/^host=myHost metric=storageRW foo=fancy 51 \d{10,}$/)
|
278
|
+
expect(server.empty?).to eq(true)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
context "fields_as_metrics (graphite)" do
|
283
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "fields_as_metrics" => true, "metrics_format" => "graphite") }
|
284
|
+
let(:event) { LogStash::Event.new(
|
285
|
+
"host" => "myHost",
|
286
|
+
"foo" => "fancy",
|
287
|
+
"cpu" => [0.24, 0.11, 0.75, 0.28],
|
288
|
+
"storageRW" => 51,
|
289
|
+
"bar" => "blahblah",
|
290
|
+
"blkio" => {
|
291
|
+
"write_ps" => 0,
|
292
|
+
"read_ps" => 0,
|
293
|
+
"total_ps" => 0
|
294
|
+
})}
|
295
|
+
|
296
|
+
it "include content" do
|
297
|
+
expect(server.pop).to match(/^blkio.write_ps 0 \d{10,}$/)
|
298
|
+
expect(server.pop).to match(/^blkio.read_ps 0 \d{10,}$/)
|
299
|
+
expect(server.pop).to match(/^blkio.total_ps 0 \d{10,}$/)
|
300
|
+
expect(server.pop).to match(/^cpu\.0 0\.24 \d{10,}$/)
|
301
|
+
expect(server.pop).to match(/^cpu\.1 0\.11 \d{10,}$/)
|
302
|
+
expect(server.pop).to match(/^cpu\.2 0\.75 \d{10,}$/)
|
303
|
+
expect(server.pop).to match(/^cpu\.3 0\.28 \d{10,}$/)
|
304
|
+
expect(server.pop).to match(/^storageRW 51 \d{10,}$/)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
context "fields_include is honored when fields_as_metrics (carbon2)" do
|
309
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "fields_as_metrics" => true, "intrinsic_tags" => {"host"=>"%{host}"}, "meta_tags" => {"foo" => "%{foo}"}, "fields_include" => ["cpu*"]) }
|
310
|
+
let(:event) { LogStash::Event.new(
|
311
|
+
"host" => "myHost",
|
312
|
+
"foo" => "fancy",
|
313
|
+
"cpu" => [0.24, 0.11, 0.75, 0.28],
|
314
|
+
"storageRW" => 51,
|
315
|
+
"bar" => "blahblah",
|
316
|
+
"blkio" => {
|
317
|
+
"write_ps" => 5,
|
318
|
+
"read_ps" => 2,
|
319
|
+
"total_ps" => 0
|
320
|
+
})}
|
321
|
+
|
322
|
+
it "include content" do
|
323
|
+
expect(server.pop).to match(/^host=myHost metric=cpu\.0 foo=fancy 0\.24 \d{10,}$/)
|
324
|
+
expect(server.pop).to match(/^host=myHost metric=cpu\.1 foo=fancy 0\.11 \d{10,}$/)
|
325
|
+
expect(server.pop).to match(/^host=myHost metric=cpu\.2 foo=fancy 0\.75 \d{10,}$/)
|
326
|
+
expect(server.pop).to match(/^host=myHost metric=cpu\.3 foo=fancy 0\.28 \d{10,}$/)
|
327
|
+
expect(server.empty?).to eq(true)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
context "fields_exclude is honored when fields_as_metrics (carbon2)" do
|
332
|
+
subject { LogStash::Outputs::SumoLogic.new("url" => "http://localhost/1234", "fields_as_metrics" => true, "intrinsic_tags" => {"host"=>"%{host}"}, "meta_tags" => {"foo" => "%{foo}"}, "fields_include" => ["cpu*"], "fields_exclude" => [".*1"]) }
|
333
|
+
let(:event) { LogStash::Event.new(
|
334
|
+
"host" => "myHost",
|
335
|
+
"foo" => "fancy",
|
336
|
+
"cpu" => [0.24, 0.11, 0.75, 0.28],
|
337
|
+
"storageRW" => 51,
|
338
|
+
"bar" => "blahblah",
|
339
|
+
"blkio" => {
|
340
|
+
"write_ps" => 5,
|
341
|
+
"read_ps" => 2,
|
342
|
+
"total_ps" => 0
|
343
|
+
})}
|
344
|
+
|
345
|
+
it "include content" do
|
346
|
+
expect(server.pop).to match(/^host=myHost metric=cpu\.0 foo=fancy 0\.24 \d{10,}$/)
|
347
|
+
expect(server.pop).to match(/^host=myHost metric=cpu\.2 foo=fancy 0\.75 \d{10,}$/)
|
348
|
+
expect(server.pop).to match(/^host=myHost metric=cpu\.3 foo=fancy 0\.28 \d{10,}$/)
|
349
|
+
expect(server.empty?).to eq(true)
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
22
353
|
end
|