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.
@@ -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.4"
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 = "byi@sumologic.com"
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
- before do
12
- output.register
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
- describe "receive message" do
16
- subject { output.receive(sample_event) }
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 "returns a string" do
19
- expect(subject).to eq("Event received")
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