logstash-output-scalyr 0.1.19.beta → 0.1.23.beta
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 +15 -0
- data/Gemfile +2 -2
- data/README.md +7 -1
- data/lib/logstash/outputs/scalyr.rb +97 -61
- data/lib/scalyr/common/util.rb +71 -27
- data/lib/scalyr/constants.rb +1 -1
- data/logstash-output-scalyr.gemspec +1 -1
- data/spec/logstash/outputs/scalyr_integration_spec.rb +8 -2
- data/spec/logstash/outputs/scalyr_spec.rb +40 -2
- data/spec/scalyr/common/util_spec.rb +253 -0
- data/vendor/bundle/jruby/2.5.0/bin/htmldiff +1 -1
- data/vendor/bundle/jruby/2.5.0/bin/ldiff +1 -1
- data/vendor/bundle/jruby/2.5.0/cache/manticore-0.7.1-java.gem +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/APACHE-LICENSE-2.0.txt +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/CHANGELOG.md +12 -3
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/Gemfile +2 -1
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/LICENSE.txt +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/README.md +17 -4
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/Rakefile +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/ext/manticore/org/manticore/HttpDeleteWithEntity.java +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/ext/manticore/org/manticore/HttpGetWithEntity.java +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/ext/manticore/org/manticore/Manticore.java +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/gem-public_cert.pem +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/commons-codec/commons-codec/1.10/commons-codec-1.10.jar +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/commons-logging/commons-logging/1.2/commons-logging-1.2.jar +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/faraday/adapter/manticore.rb +1 -6
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/manticore/client/proxies.rb +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/manticore/client.rb +24 -16
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/manticore/cookie.rb +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/manticore/facade.rb +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/manticore/java_extensions.rb +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/manticore/response.rb +12 -12
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/manticore/stubbed_response.rb +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/manticore/version.rb +1 -1
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/manticore.rb +26 -2
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/manticore_jars.rb +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/org/apache/httpcomponents/httpclient/4.5.2/httpclient-4.5.2.jar +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/org/apache/httpcomponents/httpcore/4.4.4/httpcore-4.4.4.jar +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/org/apache/httpcomponents/httpmime/4.5.2/httpmime-4.5.2.jar +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/lib/org/manticore/manticore-ext.jar +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/manticore.gemspec +4 -2
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/spec/manticore/client_proxy_spec.rb +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/spec/manticore/client_spec.rb +15 -3
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/spec/manticore/cookie_spec.rb +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/spec/manticore/facade_spec.rb +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/spec/manticore/response_spec.rb +1 -1
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/spec/manticore/stubbed_response_spec.rb +0 -0
- data/vendor/bundle/jruby/2.5.0/gems/{manticore-0.6.4-java → manticore-0.7.1-java}/spec/spec_helper.rb +0 -0
- data/vendor/bundle/jruby/2.5.0/specifications/{manticore-0.6.4-java.gemspec → manticore-0.7.1-java.gemspec} +10 -9
- metadata +39 -39
- data/vendor/bundle/jruby/2.5.0/cache/manticore-0.6.4-java.gem +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e2757da74eb03ea09a88597ed713db01bc050e17c31c771558bdb16a80ca40e
|
4
|
+
data.tar.gz: 1bc8519d1b30aea135d66b8b9ecfb632f688fd62abd58cd3b91cc92c4ad8957f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 327a3e2ba020f3166b0c435700bdfedf4f96598a352f1f66f45fe9e671a053ee684aa812d686a4d58b5dd9f319e8b0f87e2ea8290d876e504b8416a8010795ed
|
7
|
+
data.tar.gz: 1ba44520daddda5c17da810221063ce815af082645ae3fd12e76b031247ff8a13cb3e7dab4fbf69e84e5a876605290702785cc17639de69435f0b780a74691f9
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
# Beta
|
2
2
|
|
3
|
+
## 0.1.23.beta
|
4
|
+
- Add testing support for disabling estimation of serialized event size for each event in the batch.
|
5
|
+
|
6
|
+
## 0.1.22.beta
|
7
|
+
- Add new plugin metric for tracking the duration of ``build_multi_event_request_array`` method.
|
8
|
+
- Update internal dependencies (``manticore``) to latest stable version.
|
9
|
+
|
10
|
+
## 0.1.21.beta
|
11
|
+
- Fix issue with iterative flattening function when dealing with empty collections.
|
12
|
+
|
13
|
+
## 0.1.20.beta
|
14
|
+
- Rewrite flattening function to no longer be recursive, to help avoid maxing out the stack.
|
15
|
+
- Added a configurable value `flattening_max_key_count` to create a limit on how large of a record we can flatten.
|
16
|
+
It limits the maximum amount of keys we can have in the final flattened record. Defaults to unlimited.
|
17
|
+
|
3
18
|
## 0.1.19.beta
|
4
19
|
- Undo a change to nested value flattening functionality to keep existing formatting. This change can be re-enabled
|
5
20
|
by setting the `fix_deep_flattening_delimiters` configuration option to true.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -10,7 +10,7 @@ You can view documentation for this plugin [on the Scalyr website](https://app.s
|
|
10
10
|
# Quick start
|
11
11
|
|
12
12
|
1. Build the gem, run `gem build logstash-output-scalyr.gemspec`
|
13
|
-
2. Install the gem into a Logstash installation, run `/usr/share/logstash/bin/logstash-plugin install logstash-output-scalyr-0.1.
|
13
|
+
2. Install the gem into a Logstash installation, run `/usr/share/logstash/bin/logstash-plugin install logstash-output-scalyr-0.1.22.beta.gem` or follow the latest official instructions on working with plugins from Logstash.
|
14
14
|
3. Configure the output plugin (e.g. add it to a pipeline .conf)
|
15
15
|
4. Restart Logstash
|
16
16
|
|
@@ -321,6 +321,12 @@ If you want to run just the unit tests, you can run the command displayed below.
|
|
321
321
|
bundle exec rspec spec/logstash/outputs/scalyr_spec.rb spec/scalyr/common/util_spec.rb
|
322
322
|
```
|
323
323
|
|
324
|
+
Or to run a single test function defined on line XXX
|
325
|
+
|
326
|
+
```bash
|
327
|
+
bundle exec rspec spec/scalyr/common/util_spec.rb:XXX
|
328
|
+
```
|
329
|
+
|
324
330
|
## Instrumentation and metrics
|
325
331
|
|
326
332
|
By default, plugin logs a special line with metrics to Scalyr every 5 minutes. This line contains
|
@@ -71,6 +71,7 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
|
|
71
71
|
config :flatten_nested_values_delimiter, :validate => :string, :default => "_"
|
72
72
|
config :flatten_nested_arrays, :validate => :boolean, :default => true
|
73
73
|
config :fix_deep_flattening_delimiters, :validate => :boolean, :default => false
|
74
|
+
config :flattening_max_key_count, :validate => :number, :default => -1
|
74
75
|
|
75
76
|
# If true, the 'tags' field will be flattened into key-values where each key is a tag and each value is set to
|
76
77
|
# :flat_tag_value
|
@@ -139,11 +140,17 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
|
|
139
140
|
# Whether or not to create fresh quantile estimators after a status send. Depending on what you want to gather from
|
140
141
|
# these stas this might be wanted or not.
|
141
142
|
config :flush_quantile_estimates_on_status_send, :validate => :boolean, :default => false
|
142
|
-
|
143
|
+
|
143
144
|
# Causes this plugin to act as if it successfully uploaded the logs, while actually returning as quickly as possible
|
144
145
|
# after no work being done.
|
145
146
|
config :noop_mode, :validate => :boolean, :default => false
|
146
147
|
|
148
|
+
# Set to true to disable estimiating the size of each serialized event to make sure we don't go over the max request
|
149
|
+
# size (5.5) and split batch into multiple Scalyr requests, if needed. Since this estimation is not "free", especially
|
150
|
+
# for large batches, it may make sense to disable this option when logstash batch size is configured in a way that
|
151
|
+
# Scalyr single request limit won't be reached.
|
152
|
+
config :estimate_each_event_size, :validate => :boolean, :default => true
|
153
|
+
|
147
154
|
# Manticore related options
|
148
155
|
config :http_connect_timeout, :validate => :number, :default => 10
|
149
156
|
config :http_socket_timeout, :validate => :number, :default => 10
|
@@ -288,6 +295,7 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
|
|
288
295
|
# Convenience method to create a fresh quantile estimator
|
289
296
|
def get_new_metrics
|
290
297
|
return {
|
298
|
+
:build_multi_duration_secs => Quantile::Estimator.new,
|
291
299
|
:multi_receive_duration_secs => Quantile::Estimator.new,
|
292
300
|
:multi_receive_event_count => Quantile::Estimator.new,
|
293
301
|
:event_attributes_count => Quantile::Estimator.new,
|
@@ -312,17 +320,21 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
|
|
312
320
|
return events if @noop_mode
|
313
321
|
|
314
322
|
begin
|
323
|
+
records_count = events.to_a.length
|
324
|
+
|
325
|
+
# We also time the duration of the build_multi_event_request_array method. To avoid locking twice,
|
326
|
+
# we store the duration value here and record metric at the end.
|
315
327
|
start_time = Time.now.to_f
|
316
328
|
|
317
329
|
multi_event_request_array = build_multi_event_request_array(events)
|
318
|
-
|
330
|
+
build_multi_duration_secs = Time.now.to_f - start_time
|
319
331
|
|
332
|
+
# Loop over all array of multi-event requests, sending each multi-event to Scalyr
|
320
333
|
sleep_interval = @retry_initial_interval
|
321
334
|
batch_num = 1
|
322
335
|
total_batches = multi_event_request_array.length unless multi_event_request_array.nil?
|
323
336
|
|
324
337
|
result = []
|
325
|
-
records_count = events.to_a.length
|
326
338
|
|
327
339
|
while !multi_event_request_array.to_a.empty?
|
328
340
|
multi_event_request = multi_event_request_array.pop
|
@@ -429,6 +441,7 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
|
|
429
441
|
if records_count > 0
|
430
442
|
@stats_lock.synchronize do
|
431
443
|
@multi_receive_statistics[:total_multi_receive_secs] += (Time.now.to_f - start_time)
|
444
|
+
@plugin_metrics[:build_multi_duration_secs].observe(build_multi_duration_secs)
|
432
445
|
@plugin_metrics[:multi_receive_duration_secs].observe(Time.now.to_f - start_time)
|
433
446
|
@plugin_metrics[:multi_receive_event_count].observe(records_count)
|
434
447
|
@plugin_metrics[:batches_per_multi_receive].observe(total_batches)
|
@@ -633,7 +646,11 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
|
|
633
646
|
# flatten record
|
634
647
|
if @flatten_nested_values
|
635
648
|
start_time = Time.now.to_f
|
636
|
-
|
649
|
+
begin
|
650
|
+
record = Scalyr::Common::Util.flatten(record, delimiter=@flatten_nested_values_delimiter, flatten_arrays=@flatten_nested_arrays, fix_deep_flattening_delimiters=@fix_deep_flattening_delimiters, max_key_count=@flattening_max_key_count)
|
651
|
+
rescue Scalyr::Common::Util::MaxKeyCountError => e
|
652
|
+
@logger.warn("Error while flattening record", :error_message => e.message, :sample_keys => e.sample_keys)
|
653
|
+
end
|
637
654
|
end_time = Time.now.to_f
|
638
655
|
flatten_nested_values_duration = end_time - start_time
|
639
656
|
end
|
@@ -661,67 +678,74 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
|
|
661
678
|
scalyr_event[:log] = logs_ids[log_identifier]
|
662
679
|
end
|
663
680
|
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
@
|
681
|
+
if @estimate_each_event_size
|
682
|
+
# get json string of event to keep track of how many bytes we are sending
|
683
|
+
begin
|
684
|
+
event_json = scalyr_event.to_json
|
685
|
+
log_json = nil
|
686
|
+
if add_log
|
687
|
+
log_json = logs[log_identifier].to_json
|
688
|
+
end
|
689
|
+
rescue JSON::GeneratorError, Encoding::UndefinedConversionError => e
|
690
|
+
@logger.warn "#{e.class}: #{e.message}"
|
691
|
+
|
692
|
+
# Send the faulty event to a label @ERROR block and allow to handle it there (output to exceptions file for ex)
|
693
|
+
# TODO
|
694
|
+
# atime = Fluent::EventTime.new( sec, nsec )
|
695
|
+
# router.emit_error_event(serverHost, time, record, e)
|
696
|
+
|
697
|
+
scalyr_event[:attrs].each do |key, value|
|
698
|
+
@logger.debug "\t#{key} (#{value.encoding.name}): '#{value}'"
|
699
|
+
scalyr_event[:attrs][key] = value.encode(
|
700
|
+
"UTF-8", :invalid => :replace, :undef => :replace, :replace => "<?>"
|
701
|
+
).force_encoding('UTF-8')
|
702
|
+
end
|
703
|
+
event_json = scalyr_event.to_json
|
704
|
+
rescue Java::JavaLang::ClassCastException => e
|
705
|
+
# Most likely we ran into the issue described here: https://github.com/flori/json/issues/336
|
706
|
+
# Because of the version of jruby logstash works with we don't have the option to just update this away,
|
707
|
+
# so if we run into it we convert bignums into strings so we can get the data in at least.
|
708
|
+
# This is fixed in JRuby 9.2.7, which includes json 2.2.0
|
709
|
+
@logger.warn("Error serializing events to JSON, likely due to the presence of Bignum values. Converting Bignum values to strings.")
|
710
|
+
@stats_lock.synchronize do
|
711
|
+
@multi_receive_statistics[:total_java_class_cast_errors] += 1
|
712
|
+
end
|
713
|
+
Scalyr::Common::Util.convert_bignums(scalyr_event)
|
714
|
+
event_json = scalyr_event.to_json
|
715
|
+
log_json = nil
|
716
|
+
if add_log
|
717
|
+
log_json = logs[log_identifier].to_json
|
718
|
+
end
|
694
719
|
end
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
720
|
+
|
721
|
+
# generate new request if json size of events in the array exceed maximum request buffer size
|
722
|
+
append_event = true
|
723
|
+
add_bytes = event_json.bytesize
|
724
|
+
if log_json
|
725
|
+
add_bytes = add_bytes + log_json.bytesize
|
700
726
|
end
|
701
|
-
end
|
702
727
|
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
728
|
+
if total_bytes + add_bytes > @max_request_buffer
|
729
|
+
# make sure we always have at least one event
|
730
|
+
if scalyr_events.size == 0
|
731
|
+
scalyr_events << scalyr_event
|
732
|
+
l_events << l_event
|
733
|
+
append_event = false
|
734
|
+
end
|
735
|
+
|
736
|
+
multi_event_request = self.create_multi_event_request(scalyr_events, l_events, current_threads, logs)
|
737
|
+
multi_event_request_array << multi_event_request
|
738
|
+
|
739
|
+
total_bytes = 0
|
740
|
+
current_threads = Hash.new
|
741
|
+
logs = Hash.new
|
742
|
+
logs_ids = Hash.new
|
743
|
+
scalyr_events = Array.new
|
744
|
+
l_events = Array.new
|
715
745
|
end
|
716
|
-
|
717
|
-
|
718
|
-
|
719
|
-
total_bytes = 0
|
720
|
-
current_threads = Hash.new
|
721
|
-
logs = Hash.new
|
722
|
-
logs_ids = Hash.new
|
723
|
-
scalyr_events = Array.new
|
724
|
-
l_events = Array.new
|
746
|
+
else
|
747
|
+
# If size estimation is disabled we simply append the event and handle splitting later on (if needed)
|
748
|
+
append_event = true
|
725
749
|
end
|
726
750
|
|
727
751
|
# if we haven't consumed the current event already
|
@@ -798,6 +822,14 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
|
|
798
822
|
end
|
799
823
|
end_time = Time.now.to_f
|
800
824
|
serialization_duration = end_time - start_time
|
825
|
+
|
826
|
+
serialized_request_size = serialized_body.bytesize
|
827
|
+
|
828
|
+
if serialized_request_size >= @max_request_buffer
|
829
|
+
# TODO: If we end up here is estimate config opsion is false, split the request here into multiple ones
|
830
|
+
@logger.warn("Serialized request size (#{serialized_request_size}) is larger than max_request_buffer (#{max_request_buffer})!")
|
831
|
+
end
|
832
|
+
|
801
833
|
{
|
802
834
|
:body => serialized_body, :record_count => scalyr_events.size, :serialization_duration => serialization_duration,
|
803
835
|
:logstash_events => logstash_events
|
@@ -811,6 +843,10 @@ class LogStash::Outputs::Scalyr < LogStash::Outputs::Base
|
|
811
843
|
@stats_lock.synchronize do
|
812
844
|
current_stats = @multi_receive_statistics.clone
|
813
845
|
|
846
|
+
current_stats[:build_multi_duration_secs_p50] = @plugin_metrics[:build_multi_duration_secs].query(0.5)
|
847
|
+
current_stats[:build_multi_duration_secs_p90] = @plugin_metrics[:build_multi_duration_secs].query(0.9)
|
848
|
+
current_stats[:build_multi_duration_secs_p99] = @plugin_metrics[:build_multi_duration_secs].query(0.99)
|
849
|
+
|
814
850
|
current_stats[:multi_receive_duration_p50] = @plugin_metrics[:multi_receive_duration_secs].query(0.5)
|
815
851
|
current_stats[:multi_receive_duration_p90] = @plugin_metrics[:multi_receive_duration_secs].query(0.9)
|
816
852
|
current_stats[:multi_receive_duration_p99] = @plugin_metrics[:multi_receive_duration_secs].query(0.99)
|
data/lib/scalyr/common/util.rb
CHANGED
@@ -1,52 +1,96 @@
|
|
1
1
|
module Scalyr; module Common; module Util;
|
2
2
|
|
3
|
+
class MaxKeyCountError < StandardError
|
4
|
+
attr_reader :message, :sample_keys
|
5
|
+
|
6
|
+
def initialize(message, sample_keys)
|
7
|
+
@message = message
|
8
|
+
@sample_keys = sample_keys
|
9
|
+
end
|
10
|
+
end
|
3
11
|
|
4
12
|
# Flattens a hash or array, returning a hash where keys are a delimiter-separated string concatenation of all
|
5
13
|
# nested keys. Returned keys are always strings. If a non-hash or array is provided, raises TypeError.
|
6
14
|
# Please see rspec util_spec.rb for expected behavior.
|
7
15
|
# Includes a known bug where defined delimiter will not be used for nesting levels past the first, this is kept
|
8
16
|
# because some queries and dashboards already rely on the broken functionality.
|
9
|
-
def self.flatten(
|
17
|
+
def self.flatten(hash_obj, delimiter='_', flatten_arrays=true, fix_deep_flattening_delimiters=false, max_key_count=-1)
|
10
18
|
|
11
19
|
# base case is input object is not enumerable, in which case simply return it
|
12
|
-
if !
|
20
|
+
if !hash_obj.respond_to?(:each)
|
13
21
|
raise TypeError.new('Input must be a hash or array')
|
14
22
|
end
|
23
|
+
# case where we pass in a valid array, but don't want to flatten arrays
|
24
|
+
if !hash_obj.respond_to?(:has_key?) and !flatten_arrays
|
25
|
+
return hash_obj
|
26
|
+
end
|
15
27
|
|
28
|
+
stack = []
|
29
|
+
stack << hash_obj
|
30
|
+
key_stack = []
|
31
|
+
key_stack << ""
|
32
|
+
key_list = []
|
33
|
+
key_list_width = []
|
16
34
|
result = Hash.new
|
17
|
-
|
18
|
-
#
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
obj
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
35
|
+
test_key = 0
|
36
|
+
#Debugging
|
37
|
+
#require 'pry'
|
38
|
+
#binding.pry
|
39
|
+
|
40
|
+
until stack.empty?
|
41
|
+
obj = stack.pop
|
42
|
+
key_list << key_stack.pop
|
43
|
+
|
44
|
+
# Case when object is a hash
|
45
|
+
if obj.respond_to?(:has_key?) and obj.keys.count > 0
|
46
|
+
key_list_width << obj.keys.count
|
47
|
+
obj.each do |key, value|
|
48
|
+
key_stack << key
|
49
|
+
stack << value
|
30
50
|
end
|
31
|
-
end
|
32
51
|
|
33
|
-
|
52
|
+
# Case when object is an array we intend to flatten
|
53
|
+
elsif flatten_arrays and obj.respond_to?(:each) and obj.count > 0
|
54
|
+
key_list_width << obj.count
|
55
|
+
obj.each_with_index do |value, index|
|
56
|
+
key_stack << index
|
57
|
+
stack << value
|
58
|
+
end
|
34
59
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
60
|
+
else
|
61
|
+
result_key = ""
|
62
|
+
delim = delimiter
|
63
|
+
key_list.each_with_index do |key, index|
|
64
|
+
# We have a blank key at the start of the key list to avoid issues with calling pop, so we ignore delimiter
|
65
|
+
# for the first two keys
|
66
|
+
if index > 1
|
67
|
+
result_key += "#{delim}#{key}"
|
68
|
+
if not fix_deep_flattening_delimiters
|
69
|
+
delim = "_"
|
70
|
+
end
|
71
|
+
else
|
72
|
+
result_key += "#{key}"
|
40
73
|
end
|
41
|
-
else
|
42
|
-
result["#{index}"] = value
|
43
74
|
end
|
44
|
-
|
75
|
+
result[result_key] = obj
|
45
76
|
|
46
|
-
|
77
|
+
if max_key_count > -1 and result.keys.count > max_key_count
|
78
|
+
raise MaxKeyCountError.new(
|
79
|
+
"Resulting flattened object will contain more keys than the configured flattening_max_key_count of #{max_key_count}",
|
80
|
+
result.keys[0..6]
|
81
|
+
)
|
82
|
+
end
|
47
83
|
|
48
|
-
|
84
|
+
throw_away = key_list.pop
|
85
|
+
until key_list_width.empty? or key_list_width[-1] > 1
|
86
|
+
throw_away = key_list_width.pop
|
87
|
+
throw_away = key_list.pop
|
88
|
+
end
|
89
|
+
if not key_list_width.empty?
|
90
|
+
key_list_width[-1] -= 1
|
91
|
+
end
|
49
92
|
|
93
|
+
end
|
50
94
|
end
|
51
95
|
|
52
96
|
return result
|
data/lib/scalyr/constants.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
PLUGIN_VERSION = "v0.1.
|
2
|
+
PLUGIN_VERSION = "v0.1.23.beta"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-output-scalyr'
|
3
|
-
s.version = '0.1.
|
3
|
+
s.version = '0.1.23.beta'
|
4
4
|
s.licenses = ['Apache-2.0']
|
5
5
|
s.summary = "Scalyr output plugin for Logstash"
|
6
6
|
s.description = "Sends log data collected by Logstash to Scalyr (https://www.scalyr.com)"
|
@@ -7,6 +7,12 @@ require "json"
|
|
7
7
|
require 'webmock/rspec'
|
8
8
|
WebMock.allow_net_connect!
|
9
9
|
|
10
|
+
RSpec.configure do |rspec|
|
11
|
+
rspec.expect_with :rspec do |c|
|
12
|
+
c.max_formatted_output_length = nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
10
16
|
describe LogStash::Outputs::Scalyr do
|
11
17
|
let(:sample_events) {
|
12
18
|
events = []
|
@@ -58,7 +64,7 @@ describe LogStash::Outputs::Scalyr do
|
|
58
64
|
{
|
59
65
|
:error_class=>"Manticore::UnknownException",
|
60
66
|
:batch_num=>1,
|
61
|
-
:message=>"Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty",
|
67
|
+
:message=>"java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty",
|
62
68
|
:payload_size=>781,
|
63
69
|
:record_count=>3,
|
64
70
|
:total_batches=>1,
|
@@ -84,7 +90,7 @@ describe LogStash::Outputs::Scalyr do
|
|
84
90
|
{
|
85
91
|
:error_class=>"Manticore::UnknownException",
|
86
92
|
:batch_num=>1,
|
87
|
-
:message=>"Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty",
|
93
|
+
:message=>"java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty",
|
88
94
|
:payload_size=>781,
|
89
95
|
:record_count=>3,
|
90
96
|
:total_batches=>1,
|