fluent-plugin-detect-exceptions 0.0.13 → 0.0.14

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3fa3afee1139adec8fe98c8406bd72035d844aadf9f1715c01c5db3e45bd7e1c
4
- data.tar.gz: 63b1bba51e317c9931d4904551b64ef94c56b0946bccec6f67edc2311c0bbba2
3
+ metadata.gz: f846941463ccc37acd71280e182d5ae7b0ffd0c95c609bfbfe67de64f86ff478
4
+ data.tar.gz: 1454c4ddae5ba4efa214972f2109f0a71d4984e87b49cefa3541cb87d92d6cc7
5
5
  SHA512:
6
- metadata.gz: 60bbd111f5818ebfa4eda68c87236c3d985df25e66acf12e29f2851f52c4f9e0c74a0d8bbeeb5f077f1b154c4f23fa2bb223ac26f230aff29fdc5d0ddfa69272
7
- data.tar.gz: 85e20f53eb5e72b7062b6d60d724f55edc53997530dce6ca6adc252bb422a7c5466c73dc5370909ec944a52f7097a8d632649b2ed32fb16962689073dfe3415b
6
+ metadata.gz: 585f0de72a4f845f39c0f7e753ca3661ad335b10c18d26930afc19bab246b205cb9d68d1fa506c87e5ea674fc9b1ce51b04c278aed5590d997875ea9b50b21d8
7
+ data.tar.gz: 987c453e5667c1736507500859a1f46612a56451f791afaf194574380afd31527da73f9ebd87de53faf2c40e5929ce0cdd0f2c3fbd0c9d4c89a2137bad40a9a1
data/README.rdoc CHANGED
@@ -42,6 +42,16 @@ will also install and configure the gem.
42
42
 
43
43
  The plugin supports the following parameters:
44
44
 
45
+ === Required
46
+
47
+ [remove_tag_prefix] The prefix to remove from the input tag when outputting
48
+ a record. A prefix has to be a complete tag part.
49
+ Example: If remove_tag_prefix is set to 'foo', the input
50
+ tag foo.bar.baz is transformed to bar.baz and the input tag
51
+ 'foofoo.bar' is not modified.
52
+
53
+ === Optional
54
+
45
55
  [message] Name of the field in the JSON record that contains the
46
56
  single-line log messages that shall be scanned for exceptions.
47
57
  If this is set to '', the plugin will try 'message' and 'log',
@@ -49,12 +59,6 @@ The plugin supports the following parameters:
49
59
  This parameter is only applicable to structured (JSON) log streams.
50
60
  Default: ''.
51
61
 
52
- [remove_tag_prefix] The prefix to remove from the input tag when outputting
53
- a record. A prefix has to be a complete tag part.
54
- Example: If remove_tag_prefix is set to 'foo', the input
55
- tag foo.bar.baz is transformed to bar.baz and the input tag
56
- 'foofoo.bar' is not modified. Default: empty string.
57
-
58
62
  [languages] A list of language for which exception stack traces shall be
59
63
  detected. The values in the list can be separated by commas or
60
64
  written as JSON list.
@@ -66,6 +70,12 @@ The plugin supports the following parameters:
66
70
  forwarded. If not set, incomplete exceptions stacks
67
71
  are not flushed.
68
72
 
73
+ [force_line_breaks] Force line breaks between each lines when comibining exception stacks.
74
+ This is useful if your exception is formatted
75
+ as a single line. i.e., logs retrieved from the docker's
76
+ logging driver don't have any line break.
77
+ Default: false.
78
+
69
79
  [max_lines] Maximum number of lines in a detected exception stack trace.
70
80
  If this maximum number is exceeded, the exception stack trace
71
81
  that has been detected so far will be output as a single
@@ -11,7 +11,7 @@ eos
11
11
  gem.homepage = \
12
12
  'https://github.com/GoogleCloudPlatform/fluent-plugin-detect-exceptions'
13
13
  gem.license = 'Apache-2.0'
14
- gem.version = '0.0.13'
14
+ gem.version = '0.0.14'
15
15
  gem.authors = ['Stackdriver Agents']
16
16
  gem.email = ['stackdriver-agents@google.com']
17
17
  gem.required_ruby_version = Gem::Requirement.new('>= 2.0')
@@ -256,20 +256,22 @@ module Fluent
256
256
  # message_field may contain the empty string. In this case, the
257
257
  # TraceAccumulator 'learns' the field name from the first record by checking
258
258
  # for some pre-defined common field names of text logs.
259
- # The named parameters max_lines and max_bytes limit the maximum amount
259
+ # The option parameter can be used to pass the following parameters:
260
+ # force_line_breaks adds line breaks when combining exception stacks
261
+ # max_lines and max_bytes limit the maximum amount
260
262
  # of data to be buffered. The default value 0 indicates 'no limit'.
261
- def initialize(message_field, languages, max_lines: 0, max_bytes: 0,
262
- &emit_callback)
263
+ def initialize(message_field, languages, **options, &emit_callback)
263
264
  @exception_detector = Fluent::ExceptionDetector.new(*languages)
264
- @max_lines = max_lines
265
- @max_bytes = max_bytes
266
265
  @message_field = message_field
266
+ @force_line_breaks = options[:force_line_breaks] || false
267
+ @max_lines = options[:max_lines] || 0
268
+ @max_bytes = options[:max_bytes] || 0
269
+ @emit = emit_callback
267
270
  @messages = []
268
271
  @buffer_start_time = Time.now
269
272
  @buffer_size = 0
270
273
  @first_record = nil
271
274
  @first_timestamp = nil
272
- @emit = emit_callback
273
275
  end
274
276
 
275
277
  def push(time_sec, record)
@@ -360,8 +362,14 @@ module Fluent
360
362
  @buffer_start_time = Time.now
361
363
  end
362
364
  unless message.nil?
363
- @messages << message
364
- @buffer_size += message.length
365
+ message_with_line_break =
366
+ if @force_line_breaks && !@messages.empty? && !message.include?("\n")
367
+ "\n" + message
368
+ else
369
+ message
370
+ end
371
+ @messages << message_with_line_break
372
+ @buffer_size += message_with_line_break.length
365
373
  end
366
374
  end
367
375
  end
@@ -22,14 +22,16 @@ module Fluent
22
22
  # an exception stack trace, they forwarded as a single, combined JSON
23
23
  # object. Otherwise, the input log data is forwarded as is.
24
24
  class DetectExceptionsOutput < Output
25
+ desc 'The prefix to be removed from the input tag when outputting a record.'
26
+ config_param :remove_tag_prefix, :string
25
27
  desc 'The field which contains the raw message text in the input JSON data.'
26
28
  config_param :message, :string, default: ''
27
- desc 'The prefix to be removed from the input tag when outputting a record.'
28
- config_param :remove_tag_prefix, :string, default: ''
29
29
  desc 'The interval of flushing the buffer for multiline format.'
30
30
  config_param :multiline_flush_interval, :time, default: nil
31
31
  desc 'Programming languages for which to detect exceptions. Default: all.'
32
32
  config_param :languages, :array, value_type: :string, default: []
33
+ desc 'Force live breaks when combining exception stacks. Default: false.'
34
+ config_param :force_line_breaks, :bool, default: false
33
35
  desc 'Maximum number of lines to flush (0 means no limit). Default: 1000.'
34
36
  config_param :max_lines, :integer, default: 1000
35
37
  desc 'Maximum number of bytes to flush (0 means no limit). Default: 0.'
@@ -91,9 +93,13 @@ module Fluent
91
93
  unless @accumulators.key?(log_id)
92
94
  out_tag = tag.sub(/^#{Regexp.escape(@remove_tag_prefix)}\./, '')
93
95
  @accumulators[log_id] =
94
- Fluent::TraceAccumulator.new(@message, @languages,
95
- max_lines: @max_lines,
96
- max_bytes: @max_bytes) do |t, r|
96
+ Fluent::TraceAccumulator.new(
97
+ @message,
98
+ @languages,
99
+ force_line_breaks: @force_line_breaks,
100
+ max_lines: @max_lines,
101
+ max_bytes: @max_bytes
102
+ ) do |t, r|
97
103
  router.emit(out_tag, t, r)
98
104
  end
99
105
  end
@@ -28,6 +28,8 @@ END
28
28
 
29
29
  DEFAULT_TAG = 'prefix.test.tag'.freeze
30
30
 
31
+ DEFAULT_TAG_STRIPPED = 'test.tag'.freeze
32
+
31
33
  ARBITRARY_TEXT = 'This line is not an exception.'.freeze
32
34
 
33
35
  JAVA_EXC = <<END.freeze
@@ -74,6 +76,17 @@ END
74
76
  log_entry
75
77
  end
76
78
 
79
+ def feed_lines_without_line_breaks(driver, t, *messages, stream: nil)
80
+ count = 0
81
+ messages.each do |m|
82
+ m.each_line do |line|
83
+ line.delete!("\n")
84
+ driver.emit(log_entry(line, count, stream), t + count)
85
+ count += 1
86
+ end
87
+ end
88
+ end
89
+
77
90
  def feed_lines(driver, t, *messages, stream: nil)
78
91
  count = 0
79
92
  messages.each do |m|
@@ -125,7 +138,9 @@ END
125
138
  }
126
139
 
127
140
  test_cases.each do |language, exception|
128
- cfg = "languages #{language}"
141
+ cfg = %(
142
+ #{CONFIG}
143
+ languages #{language})
129
144
  d = create_driver(cfg)
130
145
  t = Time.now.to_i
131
146
 
@@ -156,12 +171,12 @@ END
156
171
 
157
172
  # Validate that each line received is emitted separately as expected.
158
173
  router_mock.should_receive(:emit)
159
- .once.with(DEFAULT_TAG, Integer,
174
+ .once.with(DEFAULT_TAG_STRIPPED, Integer,
160
175
  'message' => json_line_with_exception,
161
176
  'count' => 0)
162
177
 
163
178
  router_mock.should_receive(:emit)
164
- .once.with(DEFAULT_TAG, Integer,
179
+ .once.with(DEFAULT_TAG_STRIPPED, Integer,
165
180
  'message' => json_line_without_exception,
166
181
  'count' => 1)
167
182
 
@@ -174,7 +189,9 @@ END
174
189
  end
175
190
 
176
191
  def test_single_language_config
177
- cfg = 'languages java'
192
+ cfg = %(
193
+ #{CONFIG}
194
+ languages java)
178
195
  d = create_driver(cfg)
179
196
  t = Time.now.to_i
180
197
  d.run do
@@ -185,7 +202,9 @@ END
185
202
  end
186
203
 
187
204
  def test_multi_language_config
188
- cfg = 'languages python, java'
205
+ cfg = %(
206
+ #{CONFIG}
207
+ languages python, java)
189
208
  d = create_driver(cfg)
190
209
  t = Time.now.to_i
191
210
  d.run do
@@ -196,7 +215,9 @@ END
196
215
  end
197
216
 
198
217
  def test_split_exception_after_timeout
199
- cfg = 'multiline_flush_interval 1'
218
+ cfg = %(
219
+ #{CONFIG}
220
+ multiline_flush_interval 1)
200
221
  d = create_driver(cfg)
201
222
  t1 = 0
202
223
  t2 = 0
@@ -227,6 +248,12 @@ END
227
248
  assert_equal(make_logs(t1, JAVA_EXC + " at x\n at y\n"), d.events)
228
249
  end
229
250
 
251
+ def test_remove_tag_prefix_is_required
252
+ cfg = ''
253
+ e = assert_raises(Fluent::ConfigError) { create_driver(cfg) }
254
+ assert_match(/remove_tag_prefix/, e.message)
255
+ end
256
+
230
257
  def get_out_tags(remove_tag_prefix, original_tag)
231
258
  cfg = "remove_tag_prefix #{remove_tag_prefix}"
232
259
  d = create_driver(cfg, original_tag)
@@ -243,8 +270,42 @@ END
243
270
  assert_equal(['prefix.plus.rest.of.the.tag'], tags)
244
271
  end
245
272
 
273
+ def test_force_line_breaks_false
274
+ cfg = %(
275
+ #{CONFIG}
276
+ force_line_breaks true)
277
+ d = create_driver(cfg)
278
+ t = Time.now.to_i
279
+ d.run do
280
+ feed_lines(d, t, JAVA_EXC)
281
+ end
282
+ expected = JAVA_EXC
283
+ assert_equal(make_logs(t, *expected), d.events)
284
+ end
285
+
286
+ def test_force_line_breaks_true
287
+ cfg = %(
288
+ #{CONFIG}
289
+ force_line_breaks true)
290
+ d = create_driver(cfg)
291
+ t = Time.now.to_i
292
+ d.run do
293
+ feed_lines_without_line_breaks(d, t, JAVA_EXC)
294
+ end
295
+ # Expected: the first two lines of the exception are buffered and combined.
296
+ # Then the max_lines setting kicks in and the rest of the Python exception
297
+ # is logged line-by-line (since it's not an exception stack in itself).
298
+ # For the following Java stack trace, the two lines of the first exception
299
+ # are buffered and combined. So are the first two lines of the second
300
+ # exception. Then the rest is logged line-by-line.
301
+ expected = JAVA_EXC.chomp
302
+ assert_equal(make_logs(t, *expected), d.events)
303
+ end
304
+
246
305
  def test_flush_after_max_lines
247
- cfg = 'max_lines 2'
306
+ cfg = %(
307
+ #{CONFIG}
308
+ max_lines 2)
248
309
  d = create_driver(cfg)
249
310
  t = Time.now.to_i
250
311
  d.run do
@@ -263,7 +324,9 @@ END
263
324
  end
264
325
 
265
326
  def test_separate_streams
266
- cfg = 'stream stream'
327
+ cfg = %(
328
+ #{CONFIG}
329
+ stream stream)
267
330
  d = create_driver(cfg)
268
331
  t = Time.now.to_i
269
332
  d.run do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-detect-exceptions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stackdriver Agents
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-04 00:00:00.000000000 Z
11
+ date: 2021-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -93,7 +93,6 @@ extra_rdoc_files: []
93
93
  files:
94
94
  - CONTRIBUTING
95
95
  - Gemfile
96
- - Gemfile.lock
97
96
  - LICENSE
98
97
  - README.rdoc
99
98
  - Rakefile
@@ -123,7 +122,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
122
  - !ruby/object:Gem::Version
124
123
  version: '0'
125
124
  requirements: []
126
- rubygems_version: 3.0.4
125
+ rubygems_version: 3.0.8
127
126
  signing_key:
128
127
  specification_version: 4
129
128
  summary: fluentd output plugin for combining stack traces as multi-line JSON logs
data/Gemfile.lock DELETED
@@ -1,66 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- fluent-plugin-detect-exceptions (0.0.13)
5
- fluentd (>= 0.10)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- ast (2.4.0)
11
- concurrent-ruby (1.1.5)
12
- cool.io (1.5.4)
13
- dig_rb (1.0.1)
14
- flexmock (2.3.6)
15
- fluentd (1.7.4)
16
- cool.io (>= 1.4.5, < 2.0.0)
17
- dig_rb (~> 1.0.0)
18
- http_parser.rb (>= 0.5.1, < 0.7.0)
19
- msgpack (>= 1.2.0, < 2.0.0)
20
- serverengine (>= 2.0.4, < 3.0.0)
21
- sigdump (~> 0.2.2)
22
- strptime (>= 0.2.2, < 1.0.0)
23
- tzinfo (~> 2.0)
24
- tzinfo-data (~> 1.0)
25
- yajl-ruby (~> 1.0)
26
- http_parser.rb (0.6.0)
27
- msgpack (1.3.1)
28
- parser (2.6.5.0)
29
- ast (~> 2.4.0)
30
- power_assert (1.1.5)
31
- powerpack (0.1.2)
32
- rainbow (2.2.2)
33
- rake
34
- rake (10.5.0)
35
- rubocop (0.42.0)
36
- parser (>= 2.3.1.1, < 3.0)
37
- powerpack (~> 0.1)
38
- rainbow (>= 1.99.1, < 3.0)
39
- ruby-progressbar (~> 1.7)
40
- unicode-display_width (~> 1.0, >= 1.0.1)
41
- ruby-progressbar (1.10.1)
42
- serverengine (2.1.1)
43
- sigdump (~> 0.2.2)
44
- sigdump (0.2.4)
45
- strptime (0.2.3)
46
- test-unit (3.3.4)
47
- power_assert
48
- tzinfo (2.0.0)
49
- concurrent-ruby (~> 1.0)
50
- tzinfo-data (1.2019.3)
51
- tzinfo (>= 1.0.0)
52
- unicode-display_width (1.6.0)
53
- yajl-ruby (1.4.1)
54
-
55
- PLATFORMS
56
- ruby
57
-
58
- DEPENDENCIES
59
- flexmock (~> 2.0)
60
- fluent-plugin-detect-exceptions!
61
- rake (~> 10.3)
62
- rubocop (= 0.42.0)
63
- test-unit (~> 3.0)
64
-
65
- BUNDLED WITH
66
- 2.0.2