fluent-plugin-concat 2.4.0 → 2.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d906b3c9372b21adec5b1515e4820b037d90a0fa83a32f01dad1a8d6e5e0f79c
4
- data.tar.gz: 9685f06e791e53ae0fcb3bb3e71991f812405298084c31cb4cc61a4181e17d6c
3
+ metadata.gz: 31897cab290a08b88945f1a78571bc4bfac24affae42aa2fb79eee0c6a5df937
4
+ data.tar.gz: 689b42a5ec25b1400d51af0c4f59961023e4fd01dd9b56c2d87b6ff83a2c3ddd
5
5
  SHA512:
6
- metadata.gz: 1683fcfe93f86fedbc89334dde6565b48fad41800631a5624ebfd26f89f8c725c0cff1aed9ef3733d863bf1ec3fb2e0e62676ce78a68dc40d332b08f80209748
7
- data.tar.gz: 6bec85d758dfce0dbced83a03413d2e1c2cef6d73a9c30ccb07f03c62d5d211d13559fdd7703f373f72af6d3c631ecf753451b93737777e82b2fc053ae5cb0ef
6
+ metadata.gz: 501acf92258e36fbb603c27bd4a861fff446304b33b3ccb425fb2fa281bc4b6ab05c357cc051196b17da66fd57c4de4e2e7d55999b194adfc3ce4dac9694b130
7
+ data.tar.gz: 369632414f573689ca37ea34c2f17b88a74476dab41ea7edfe9d8ee394d42b20fed5d27bef7306489729b7eb9ee96f8a1429adaca88bf1b0066d7ccbcc25b22a
@@ -0,0 +1,67 @@
1
+ name: Bug Report
2
+ description: Create a report with a procedure for reproducing the bug
3
+ labels: "waiting-for-triage"
4
+ body:
5
+ - type: textarea
6
+ id: description
7
+ attributes:
8
+ label: Describe the bug
9
+ description: A clear and concise description of what the bug is
10
+ validations:
11
+ required: true
12
+ - type: textarea
13
+ id: reproduce
14
+ attributes:
15
+ label: To Reproduce
16
+ description: Steps to reproduce the behavior
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: expected
21
+ attributes:
22
+ label: Expected behavior
23
+ description: A clear and concise description of what you expected to happen
24
+ validations:
25
+ required: true
26
+ - type: textarea
27
+ id: environment
28
+ attributes:
29
+ label: Your Environment
30
+ description: |
31
+ - Fluentd or its package version: `fluentd --version` (Fluentd, fluent-package) or `td-agent --version` (td-agent)
32
+ - Operating system: `cat /etc/os-release`
33
+ - Kernel version: `uname -r`
34
+
35
+ Tip: If you hit the problem with older fluent-plugin-concat version, try latest version first.
36
+ value: |
37
+ - Fluentd version:
38
+ - Package version:
39
+ - Operating system:
40
+ - Kernel version:
41
+ render: markdown
42
+ validations:
43
+ required: true
44
+ - type: textarea
45
+ id: configuration
46
+ attributes:
47
+ label: Your Configuration
48
+ description: |
49
+ Write your configuration here. Minimum reproducible fluentd.conf is recommended.
50
+ render: apache
51
+ validations:
52
+ required: true
53
+ - type: textarea
54
+ id: logs
55
+ attributes:
56
+ label: Your Error Log
57
+ description: Write your ALL error log here
58
+ render: shell
59
+ validations:
60
+ required: true
61
+ - type: textarea
62
+ id: addtional-context
63
+ attributes:
64
+ label: Additional context
65
+ description: Add any other context about the problem here.
66
+ validations:
67
+ required: false
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: Ask a Question
4
+ url: https://github.com/fluent/fluentd/discussions
5
+ about: I have questions about Fluentd and plugins. Please ask and answer questions at https://github.com/fluent/fluentd/discussions
@@ -0,0 +1,35 @@
1
+ name: Feature request
2
+ description: Suggest an idea for this project
3
+ labels: ["waiting-for-triage", "enhancement"]
4
+ body:
5
+ - type: textarea
6
+ id: description
7
+ attributes:
8
+ label: Is your feature request related to a problem? Please describe.
9
+ description: |
10
+ A clear and concise description of what the problem is.
11
+ Ex. I'm always frustrated when [...]
12
+ validations:
13
+ required: true
14
+ - type: textarea
15
+ id: solution
16
+ attributes:
17
+ label: Describe the solution you'd like
18
+ description: A clear and concise description of what you want to happen.
19
+ validations:
20
+ required: true
21
+ - type: textarea
22
+ id: alternative
23
+ attributes:
24
+ label: Describe alternatives you've considered
25
+ description: A clear and concise description of any alternative solutions or features you've considered.
26
+ validations:
27
+ required: true
28
+ - type: textarea
29
+ id: addtional-context
30
+ attributes:
31
+ label: Additional context
32
+ description: Add any other context or screenshots about the feature request here.
33
+ validations:
34
+ required: false
35
+
@@ -0,0 +1,17 @@
1
+ name: Add bugs to fluent project
2
+
3
+ on:
4
+ issues:
5
+ types:
6
+ - opened
7
+
8
+ jobs:
9
+ add-to-project:
10
+ name: Add issue to project
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/add-to-project@v1.0.2
14
+ with:
15
+ project-url: https://github.com/orgs/fluent/projects/4
16
+ github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
17
+ labeled: waiting-for-triage
@@ -0,0 +1,33 @@
1
+ name: Testing on Ubuntu
2
+ on:
3
+ - push
4
+ - pull_request
5
+ jobs:
6
+ build:
7
+ runs-on: ${{ matrix.os }}
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby:
12
+ - 2.7
13
+ - '3.0'
14
+ - 3.1
15
+ - 3.2
16
+ - 3.3
17
+ - 3.4
18
+ os:
19
+ - ubuntu-latest
20
+ name: Ruby ${{ matrix.ruby }} unit testing on ${{ matrix.os }}
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+ - uses: ruby/setup-ruby@v1
24
+ with:
25
+ ruby-version: ${{ matrix.ruby }}
26
+ rubygems: latest
27
+ - name: unit testing
28
+ env:
29
+ CI: true
30
+ run: |
31
+ gem install bundler rake
32
+ bundle install --jobs 4 --retry 3
33
+ bundle exec rake test
@@ -0,0 +1,27 @@
1
+ name: Testing on Windows
2
+ on:
3
+ - push
4
+ - pull_request
5
+ jobs:
6
+ build:
7
+ runs-on: ${{ matrix.os }}
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby: [ '2.7', '3.0', '3.1', '3.2', '3.3', '3.4' ]
12
+ os:
13
+ - windows-latest
14
+ name: Ruby ${{ matrix.ruby }} unit testing on ${{ matrix.os }}
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: ${{ matrix.ruby }}
20
+ rubygems: latest
21
+ - name: unit testing
22
+ env:
23
+ CI: true
24
+ run: |
25
+ gem install bundler rake
26
+ bundle install --jobs 4 --retry 3
27
+ bundle exec rake test
data/NEWS.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # ChangeLog
2
2
 
3
+ ## next
4
+
5
+ ### Improvements
6
+
7
+ * adds `partial_metadata_format` to support Docker 20.10 journald log driver improvements [moby/moby#41407](https://github.com/moby/moby/pull/41407)
8
+
9
+ ## v2.6.0
10
+
11
+ ### Improvements
12
+
13
+ * Support `buffer_limit_size`, `buffer_overflow_method` to change behavior when buffer overflow. See #68
14
+
3
15
  ## v2.3.0
4
16
 
5
17
  ### Improvements
data/README.md CHANGED
@@ -27,75 +27,79 @@ Or install it yourself as:
27
27
 
28
28
  $ gem install fluent-plugin-concat
29
29
 
30
- ## Configuration
31
-
32
- **key** (string) (required)
33
-
34
- The key for part of multiline log.
35
-
36
- **separator** (string) (optional)
37
-
38
- The separator of lines.
39
- Default value is `"\n"`.
40
-
41
- **n\_lines** (integer) (optional)
42
-
43
- The number of lines.
44
- This is exclusive with `multiline_start_regex`.
45
-
46
- **multiline\_start\_regexp** (string) (optional)
47
-
48
- The regexp to match beginning of multiline.
49
- This is exclusive with `n_lines.`
50
-
51
- **multiline\_end\_regexp** (string) (optional)
52
-
53
- The regexp to match ending of multiline.
54
- This is exclusive with `n_lines.`
55
-
56
- **continuous\_line\_regexp** (string) (optional)
57
-
58
- The regexp to match continuous lines.
59
- This is exclusive with `n_lines.`
60
-
61
- **stream\_identity\_key** (string) (optional)
30
+ ## Plugin helpers
62
31
 
63
- The key to determine which stream an event belongs to.
32
+ * [timer](https://docs.fluentd.org/v1.0/articles/api-plugin-helper-timer)
33
+ * [event_emitter](https://docs.fluentd.org/v1.0/articles/api-plugin-helper-event_emitter)
64
34
 
65
- **flush\_interval** (integer) (optional)
35
+ * See also: [Filter Plugin Overview](https://docs.fluentd.org/filter#overview)
66
36
 
67
- The number of seconds after which the last received event log will be flushed.
68
- If specified 0, wait for next line forever.
69
-
70
- **timeout\_label** (string) (optional)
71
-
72
- The label name to handle events caused by timeout.
73
-
74
- **use\_first\_timestamp** (bool) (optional)
75
-
76
- Use timestamp of first record when buffer is flushed.
77
- Default value is `false`.
78
-
79
- **partial\_key** (string) (optional)
80
-
81
- The field name that is the reference to concatenate records
82
-
83
- **partial\_value** (string) (optional)
84
-
85
- The value stored in the field specified by partial_key that represent partial log
86
-
87
- **keep\_partial\_key** (bool) (optional)
88
-
89
- If true, keep partial_key in concatenated records
90
- Default value is `false`.
91
-
92
- **use\_partial\_metadata** (bool) (optional)
37
+ ## Configuration
93
38
 
94
- Use partial metadata to concatenate multiple records
39
+ ### Example
95
40
 
96
- **keep\_partial\_metadata** (bool) (optional)
41
+ ```
42
+ <filter docker.log>
43
+ @type concat
44
+ key loga
45
+ #separator "\n"
46
+ n_lines 10
47
+ #multiline_start_regexp /^Start/
48
+ #multiline_end_regexp /^End/
49
+ #continuous_line_regexp nil
50
+ #stream_identity_key nil
51
+ #flush_interval 60
52
+ #timeout_label nil
53
+ #use_first_timestamp false
54
+ #partial_key nil
55
+ #partial_value nil
56
+ #keep_partial_key false
57
+ #use_partial_metadata false
58
+ #keep_partial_metadata false
59
+ #partial\_metadata\_format docker-fluentd
60
+ #use\_partial\_cri\_logtag false
61
+ #partial\_cri\_logtag\_key nil
62
+ #partial\_cri\_stream\_key stream
63
+ </filter>
64
+ ```
97
65
 
98
- If true, keep partial metadata
66
+ ### Parameter
67
+
68
+ |parameter|description|default|
69
+ |---|---|---|
70
+ |key|The key for part of multiline log||
71
+ |separator|The separator of lines|`"\n"`|
72
+ |n\_lines|The number of lines. This is exclusive with `multiline_start_regex`|nil|
73
+ |multiline\_start\_regexp|The regexp to match beginning of multiline. This is exclusive with `n_lines`|nil|
74
+ |multiline\_end\_regexp|The regexp to match ending of multiline.This is exclusive with `n_lines`|nil|
75
+ |continuous\_line\_regexp|The regexp to match continuous lines.This is exclusive with `n_lines`|nil|
76
+ |stream\_identity\_key|The key to determine which stream an event belongs to|nil|
77
+ |flush\_interval|The number of seconds after which the last received event log will be flushed.If specified 0, wait for next line forever|60|
78
+ |timeout\_label|The label name to handle events caused by timeout|nil|
79
+ |use\_first\_timestamp|Use timestamp of first record when buffer is flushed|`false`|
80
+ |partial\_key|The field name that is the reference to concatenate records|nil|
81
+ |partial\_value|The value stored in the field specified by partial_key that represent partial log|nil|
82
+ |keep\_partial\_key|If true, keep partial_key in concatenated records|`false`|
83
+ |use\_partial\_metadata|Use partial metadata to concatenate multiple records|`false`|
84
+ |keep\_partial\_metadata|If true, keep partial metadata|`false`|
85
+ |partial\_metadata\_format|Input format of the partial metadata (fluentd or journald docker log driver) ( `docker-fluentd`, `docker-journald`, `docker-journald-lowercase`)<br>Configure based on the input plugin, that is used. <br>The docker fluentd and journald log drivers are behaving differently, so the plugin needs to know, what to look for.<br>Use `docker-journald-lowercase`, if you have `fields_lowercase true` in the `journald` source config |`docker-fluentd`|
86
+ |use\_partial\_cri\_logtag|bool (optional)|Use cri log tag to concatenate multiple records||
87
+ |partial\_cri\_logtag\_key|string (optional)|The key name that is referred to concatenate records on cri log||
88
+ |partial\_cri\_stream\_key|string (optional)|The key name that is referred to detect stream name on cri log|`stream`|
89
+ |buffer\_limit\_size|The max size of each buffer|`512000`|
90
+
91
+ |parameter|description|available values|default|
92
+ |---|---|---|---|
93
+ |buffer\_overflow\_method|The method if overflow buffer|`ignore`, `truncate`, `drop`, `new`|`ignore`|
94
+
95
+ * `ignore`
96
+ * Concatenate the current record in the buffer
97
+ * `truncate`
98
+ * Drop the current record and flush the buffer
99
+ * `drop`
100
+ * Drop the current record and clear the buffer
101
+ * `new`
102
+ * Flush the buffer and store the current record in next buffer
99
103
 
100
104
  ## Usage
101
105
 
@@ -168,13 +172,38 @@ Handle Docker logs splitted in several parts (using `partial_message`), and do n
168
172
  ```aconf
169
173
  <filter>
170
174
  @type concat
171
- key message
175
+ key log
172
176
  partial_key partial_message
173
177
  partial_value true
174
178
  separator ""
175
179
  </filter>
176
180
  ```
177
181
 
182
+ (Docker v19.03+) Handle Docker logs splitted in several parts (using `use_partial_metadata`), and do not add new line between parts.
183
+
184
+ ```aconf
185
+ <filter>
186
+ @type concat
187
+ key log
188
+ use_partial_metadata true
189
+ separator ""
190
+ </filter>
191
+ ```
192
+
193
+ (Docker v20.10+) Handle Docker logs splitted in several parts (using `use_partial_metadata`), and do not add new line between parts.
194
+
195
+ Docker v20.10 improved partial message handling by adding better metadata in the journald log driver, this works now similarily to the fluentd log driver, but requires one additional setting
196
+
197
+ ```aconf
198
+ <filter>
199
+ @type concat
200
+ key log
201
+ use_partial_metadata true
202
+ partial_metadata_format docker-journald
203
+ separator ""
204
+ </filter>
205
+ ```
206
+
178
207
  Handle Docker logs splitted in several parts (using newline detection), and do not add new line between parts (prior to Docker 18.06).
179
208
 
180
209
  ```aconf
@@ -194,7 +223,8 @@ Handle containerd/cri in Kubernetes.
194
223
  path /var/log/containers/*.log
195
224
  <parse>
196
225
  @type regexp
197
- expression /^(?<timestamp>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z) (?<output>\w+) (?<partial_flag>[FP]) (?<message>.+)$/
226
+ expression /^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<message>.*)$/
227
+ time_format %Y-%m-%dT%H:%M:%S.%L%z
198
228
  </parse>
199
229
  tag k8s
200
230
  @label @CONCAT
@@ -204,8 +234,9 @@ Handle containerd/cri in Kubernetes.
204
234
  <filter k8s>
205
235
  @type concat
206
236
  key message
207
- partial_key partial_flag
208
- partial_value P
237
+ use_partial_cri_logtag true
238
+ partial_cri_logtag_key logtag
239
+ partial_cri_stream_key stream
209
240
  </filter>
210
241
  <match k8s>
211
242
  @type relabel
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "fluent-plugin-concat"
7
- spec.version = "2.4.0"
7
+ spec.version = "2.6.0"
8
8
  spec.authors = ["Kenji Okimoto"]
9
9
  spec.email = ["okimoto@clear-code.com"]
10
10
 
@@ -22,4 +22,5 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency "test-unit", ">= 3.1.0"
23
23
  spec.add_development_dependency "test-unit-rr"
24
24
  spec.add_development_dependency "appraisal"
25
+ spec.add_development_dependency "webrick"
25
26
  end
@@ -22,7 +22,7 @@ module Fluent::Plugin
22
22
  config_param :stream_identity_key, :string, default: nil
23
23
  desc "The interval between data flushes, 0 means disable timeout"
24
24
  config_param :flush_interval, :time, default: 60
25
- desc "The label name to handle timeout"
25
+ desc "The label name to handle events caused by timeout"
26
26
  config_param :timeout_label, :string, default: nil
27
27
  desc "Use timestamp of first record when buffer is flushed"
28
28
  config_param :use_first_timestamp, :bool, default: false
@@ -34,8 +34,20 @@ module Fluent::Plugin
34
34
  config_param :keep_partial_key, :bool, default: false
35
35
  desc "Use partial metadata to concatenate multiple records"
36
36
  config_param :use_partial_metadata, :bool, default: false
37
+ desc "Input format of the partial metadata (fluentd or journald docker log driver)"
38
+ config_param :partial_metadata_format, :enum, list: [:"docker-fluentd", :"docker-journald", :"docker-journald-lowercase"], default: :"docker-fluentd"
37
39
  desc "If true, keep partial metadata"
38
40
  config_param :keep_partial_metadata, :bool, default: false
41
+ desc "Use cri log tag to concatenate multiple records"
42
+ config_param :use_partial_cri_logtag, :bool, default: false
43
+ desc "The key name that is referred to concatenate records on cri log"
44
+ config_param :partial_cri_logtag_key, :string, default: nil
45
+ desc "The key name that is referred to detect stream name on cri log"
46
+ config_param :partial_cri_stream_key, :string, default: "stream"
47
+ desc "The max size of each buffer"
48
+ config_param :buffer_limit_size, :size, default: 500 * 1024 # 500k
49
+ desc "The method if overflow buffer"
50
+ config_param :buffer_overflow_method, :enum, list: [:ignore, :truncate, :drop, :new], default: :ignore
39
51
 
40
52
  class TimeoutError < StandardError
41
53
  end
@@ -44,17 +56,25 @@ module Fluent::Plugin
44
56
  super
45
57
 
46
58
  @buffer = Hash.new {|h, k| h[k] = [] }
59
+ @buffer_size = Hash.new(0)
47
60
  @timeout_map_mutex = Thread::Mutex.new
48
61
  @timeout_map_mutex.synchronize do
49
62
  @timeout_map = Hash.new {|h, k| h[k] = Fluent::Engine.now }
50
63
  end
51
64
  end
52
65
 
66
+ def required_params
67
+ params = [@n_lines.nil?, @multiline_start_regexp.nil?, @multiline_end_regexp.nil?, @partial_key.nil?, !@use_partial_metadata, !@use_partial_cri_logtag]
68
+ names = ["n_lines", "multiline_start_regexp", "multiline_end_regexp", "partial_key", "use_partial_metadata", "use_partial_cri_logtag"]
69
+ return params, names
70
+ end
71
+
53
72
  def configure(conf)
54
73
  super
55
74
 
56
- if @n_lines.nil? && @multiline_start_regexp.nil? && @multiline_end_regexp.nil? && @partial_key.nil? && !@use_partial_metadata
57
- raise Fluent::ConfigError, "Either n_lines, multiline_start_regexp, multiline_end_regexp, partial_key or use_partial_metadata is required"
75
+ params, names = required_params
76
+ if params.all?
77
+ raise Fluent::ConfigError, "Either #{[names[0..-2].join(", "), names[-1]].join(" or ")} is required"
58
78
  end
59
79
  if @n_lines && (@multiline_start_regexp || @multiline_end_regexp)
60
80
  raise Fluent::ConfigError, "n_lines and multiline_start_regexp/multiline_end_regexp are exclusive"
@@ -69,13 +89,22 @@ module Fluent::Plugin
69
89
  raise Fluent::ConfigError, "partial_value is required when partial_key is specified"
70
90
  end
71
91
  if @use_partial_metadata && @n_lines
72
- raise Fluent::ConfigError, "user_partial_metadata and n_lines are exclusive"
92
+ raise Fluent::ConfigError, "use_partial_metadata and n_lines are exclusive"
73
93
  end
74
94
  if @use_partial_metadata && (@multiline_start_regexp || @multiline_end_regexp)
75
- raise Fluent::ConfigError, "user_partial_metadata and multiline_start_regexp/multiline_end_regexp are exclusive"
95
+ raise Fluent::ConfigError, "use_partial_metadata and multiline_start_regexp/multiline_end_regexp are exclusive"
76
96
  end
77
97
  if @use_partial_metadata && @partial_key
78
- raise Fluent::ConfigError, "user_partial_metadata and partial_key are exclusive"
98
+ raise Fluent::ConfigError, "use_partial_metadata and partial_key are exclusive"
99
+ end
100
+ if @use_partial_cri_logtag && @n_lines
101
+ raise Fluent::ConfigError, "use_partial_cri_logtag and n_lines are exclusive"
102
+ end
103
+ if @use_partial_cri_logtag && (@multiline_start_regexp || @multiline_end_regexp)
104
+ raise Fluent::ConfigError, "use_partial_cri_logtag and multiline_start_regexp/multiline_end_regexp are exclusive"
105
+ end
106
+ if @use_partial_cri_logtag && @partial_key
107
+ raise Fluent::ConfigError, "use_partial_cri_logtag and partial_key are exclusive"
79
108
  end
80
109
 
81
110
  @mode = nil
@@ -86,6 +115,33 @@ module Fluent::Plugin
86
115
  @mode = :partial
87
116
  when @use_partial_metadata
88
117
  @mode = :partial_metadata
118
+ case @partial_metadata_format
119
+ when :"docker-fluentd"
120
+ @partial_message_field = "partial_message".freeze
121
+ @partial_id_field = "partial_id".freeze
122
+ @partial_ordinal_field = "partial_ordinal".freeze
123
+ @partial_last_field = "partial_last".freeze
124
+ @partial_message_indicator = @partial_message_field
125
+ when :"docker-journald"
126
+ @partial_message_field = "CONTAINER_PARTIAL_MESSAGE".freeze
127
+ @partial_id_field = "CONTAINER_PARTIAL_ID".freeze
128
+ @partial_ordinal_field = "CONTAINER_PARTIAL_ORDINAL".freeze
129
+ @partial_last_field = "CONTAINER_PARTIAL_LAST".freeze
130
+ # the journald log driver does not add CONTAINER_PARTIAL_MESSAGE to the last message
131
+ # so we help ourself by using another indicator
132
+ @partial_message_indicator = @partial_id_field
133
+ when :"docker-journald-lowercase"
134
+ @partial_message_field = "container_partial_message".freeze
135
+ @partial_id_field = "container_partial_id".freeze
136
+ @partial_ordinal_field = "container_partial_ordinal".freeze
137
+ @partial_last_field = "container_partial_last".freeze
138
+ @partial_message_indicator = @partial_id_field
139
+ end
140
+ when @use_partial_cri_logtag
141
+ @mode = :partial_cri
142
+ @partial_logtag_delimiter = ":".freeze
143
+ @partial_logtag_continue = "P".freeze
144
+ @partial_logtag_full = "F".freeze
89
145
  when @multiline_start_regexp || @multiline_end_regexp
90
146
  @mode = :regexp
91
147
  if @multiline_start_regexp
@@ -113,12 +169,12 @@ module Fluent::Plugin
113
169
  end
114
170
 
115
171
  def filter_stream(tag, es)
172
+ if /\Afluent\.(?:trace|debug|info|warn|error|fatal)\z/ =~ tag
173
+ return es
174
+ end
175
+
116
176
  new_es = Fluent::MultiEventStream.new
117
177
  es.each do |time, record|
118
- if /\Afluent\.(?:trace|debug|info|warn|error|fatal)\z/ =~ tag
119
- new_es.add(time, record)
120
- next
121
- end
122
178
  unless record.key?(@key)
123
179
  new_es.add(time, record)
124
180
  next
@@ -130,7 +186,7 @@ module Fluent::Plugin
130
186
  end
131
187
  end
132
188
  if @mode == :partial_metadata
133
- unless record.key?("partial_message")
189
+ unless record.key?(@partial_message_indicator)
134
190
  new_es.add(time, record)
135
191
  next
136
192
  end
@@ -146,11 +202,14 @@ module Fluent::Plugin
146
202
  merged_record.delete(@partial_key) unless @keep_partial_key
147
203
  when :partial_metadata
148
204
  unless @keep_partial_metadata
149
- merged_record.delete("partial_message")
150
- merged_record.delete("partial_id")
151
- merged_record.delete("partial_ordinal")
152
- merged_record.delete("partial_last")
205
+ merged_record.delete(@partial_message_field)
206
+ merged_record.delete(@partial_id_field)
207
+ merged_record.delete(@partial_ordinal_field)
208
+ merged_record.delete(@partial_last_field)
153
209
  end
210
+ when :partial_cri
211
+ merged_record.delete(@partial_cri_logtag_key) unless @keep_partial_key
212
+ merged_record.delete(@partial_cri_stream_key)
154
213
  end
155
214
  new_es.add(time, merged_record)
156
215
  end
@@ -175,9 +234,9 @@ module Fluent::Plugin
175
234
  def process(tag, time, record)
176
235
  if @mode == :partial_metadata
177
236
  if @stream_identity_key
178
- stream_identity = %Q(#{tag}:#{record[@stream_identity_key]}#{record["partial_id"]})
237
+ stream_identity = %Q(#{tag}:#{record[@stream_identity_key]}#{record[@partial_id_field]})
179
238
  else
180
- stream_identity = %Q(#{tag}:#{record["partial_id"]})
239
+ stream_identity = %Q(#{tag}:#{record[@partial_id_field]})
181
240
  end
182
241
  else
183
242
  if @stream_identity_key
@@ -196,6 +255,8 @@ module Fluent::Plugin
196
255
  process_partial(stream_identity, tag, time, record)
197
256
  when :partial_metadata
198
257
  process_partial_metadata(stream_identity, tag, time, record)
258
+ when :partial_cri
259
+ process_partial_cri(stream_identity, tag, time, record)
199
260
  when :regexp
200
261
  process_regexp(stream_identity, tag, time, record)
201
262
  end
@@ -214,20 +275,58 @@ module Fluent::Plugin
214
275
 
215
276
  def process_partial(stream_identity, tag, time, record)
216
277
  new_es = Fluent::MultiEventStream.new
217
- @buffer[stream_identity] << [tag, time, record]
218
- unless @partial_value == record[@partial_key]
278
+ force_flush = false
279
+ if overflow?(stream_identity, record)
280
+ force_flush = case @buffer_overflow_method
281
+ when :ignore
282
+ @buffer[stream_identity] << [tag, time, record]
283
+ false
284
+ when :truncate
285
+ true
286
+ when :drop
287
+ @buffer[stream_identity] = []
288
+ false
289
+ when :new
290
+ true
291
+ end
292
+ else
293
+ @buffer[stream_identity] << [tag, time, record]
294
+ end
295
+ if force_flush || @partial_value != record[@partial_key]
219
296
  new_time, new_record = flush_buffer(stream_identity)
220
297
  time = new_time if @use_first_timestamp
221
298
  new_record.delete(@partial_key)
222
299
  new_es.add(time, new_record)
223
300
  end
301
+ if force_flush && @buffer_overflow_method == :new
302
+ @buffer[stream_identity] << [tag, time, record]
303
+ @buffer_size[stream_identity] = record.keys.sum(&:bytesize) + record.values.sum(&:bytesize)
304
+ if @partial_value != record[@partial_key]
305
+ new_time, new_record = flush_buffer(stream_identity)
306
+ time = new_time if @use_first_timestamp
307
+ new_record.delete(@partial_key)
308
+ new_es.add(time, new_record)
309
+ end
310
+ end
311
+ new_es
312
+ end
313
+
314
+ def process_partial_cri(stream_identity, tag, time, record)
315
+ new_es = Fluent::MultiEventStream.new
316
+ @buffer[stream_identity] << [tag, time, record]
317
+ if record[@partial_cri_logtag_key].split(@partial_logtag_delimiter)[0] == @partial_logtag_full
318
+ new_time, new_record = flush_buffer(stream_identity)
319
+ time = new_time if @use_first_timestamp
320
+ new_record.delete(@partial_cri_logtag_key)
321
+ new_es.add(time, new_record)
322
+ end
224
323
  new_es
225
324
  end
226
325
 
227
326
  def process_partial_metadata(stream_identity, tag, time, record)
228
327
  new_es = Fluent::MultiEventStream.new
229
328
  @buffer[stream_identity] << [tag, time, record]
230
- if record["partial_last"] == "true"
329
+ if record[@partial_last_field] == "true"
231
330
  new_time, new_record = flush_buffer(stream_identity)
232
331
  time = new_time if @use_first_timestamp
233
332
  new_record.delete(@partial_key)
@@ -288,25 +387,36 @@ module Fluent::Plugin
288
387
  end
289
388
 
290
389
  def firstline?(text)
291
- @multiline_start_regexp && !!@multiline_start_regexp.match(text)
390
+ @multiline_start_regexp && @multiline_start_regexp.match?(text)
292
391
  end
293
392
 
294
393
  def lastline?(text)
295
- @multiline_end_regexp && !!@multiline_end_regexp.match(text)
394
+ @multiline_end_regexp && @multiline_end_regexp.match?(text)
296
395
  end
297
396
 
298
397
  def continuous_line?(text)
299
398
  if @continuous_line_regexp
300
- !!@continuous_line_regexp.match(text)
399
+ @continuous_line_regexp.match?(text)
301
400
  else
302
401
  true
303
402
  end
304
403
  end
305
404
 
405
+ def overflow?(stream_identity, record)
406
+ size = record.keys.sum(&:bytesize) + record.values.sum(&:bytesize)
407
+ if @buffer_size[stream_identity] + size > @buffer_limit_size
408
+ @buffer_size[stream_identity] = 0
409
+ true
410
+ else
411
+ @buffer_size[stream_identity] += size
412
+ false
413
+ end
414
+ end
415
+
306
416
  def flush_buffer(stream_identity, new_element = nil)
307
417
  lines = if @mode == :partial_metadata
308
418
  @buffer[stream_identity]
309
- .sort_by {|_tag, _time, record| record["partial_ordinal"].to_i }
419
+ .sort_by {|_tag, _time, record| record[@partial_ordinal_field].to_i }
310
420
  .map {|_tag, _time, record| record[@key] }
311
421
  else
312
422
  @buffer[stream_identity].map {|_tag, _time, record| record[@key] }
@@ -317,6 +427,7 @@ module Fluent::Plugin
317
427
  }
318
428
  @buffer[stream_identity] = []
319
429
  @buffer[stream_identity] << new_element if new_element
430
+ @buffer_size[stream_identity] = 0
320
431
  [time, first_record.merge(new_record)]
321
432
  end
322
433
 
@@ -366,3 +477,18 @@ module Fluent::Plugin
366
477
  end
367
478
  end
368
479
  end
480
+
481
+ class Array
482
+ # Support Ruby 2.3 or earlier
483
+ unless [].respond_to?(:sum)
484
+ def sum
485
+ inject(0) do |memo, value|
486
+ if block_given?
487
+ memo + yield(value)
488
+ else
489
+ memo + value
490
+ end
491
+ end
492
+ end
493
+ end
494
+ end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-concat
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenji Okimoto
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2019-07-26 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: fluentd
@@ -100,6 +99,20 @@ dependencies:
100
99
  - - ">="
101
100
  - !ruby/object:Gem::Version
102
101
  version: '0'
102
+ - !ruby/object:Gem::Dependency
103
+ name: webrick
104
+ requirement: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ type: :development
110
+ prerelease: false
111
+ version_requirements: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
103
116
  description: Fluentd Filter plugin to concat multiple event messages
104
117
  email:
105
118
  - okimoto@clear-code.com
@@ -107,10 +120,14 @@ executables: []
107
120
  extensions: []
108
121
  extra_rdoc_files: []
109
122
  files:
110
- - ".github/ISSUE_TEMPLATE.md"
123
+ - ".github/ISSUE_TEMPLATE/bug_report.yml"
124
+ - ".github/ISSUE_TEMPLATE/config.yml"
125
+ - ".github/ISSUE_TEMPLATE/feature_request.yml"
126
+ - ".github/workflows/add-to-project.yml"
127
+ - ".github/workflows/linux.yml"
128
+ - ".github/workflows/windows.yml"
111
129
  - ".gitignore"
112
130
  - ".rubocop.yml"
113
- - ".travis.yml"
114
131
  - Appraisals
115
132
  - Gemfile
116
133
  - LICENSE.txt
@@ -123,7 +140,6 @@ homepage: https://github.com/fluent-plugins-nursery/fluent-plugin-concat
123
140
  licenses:
124
141
  - MIT
125
142
  metadata: {}
126
- post_install_message:
127
143
  rdoc_options: []
128
144
  require_paths:
129
145
  - lib
@@ -138,8 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
154
  - !ruby/object:Gem::Version
139
155
  version: '0'
140
156
  requirements: []
141
- rubygems_version: 3.0.3
142
- signing_key:
157
+ rubygems_version: 3.6.8
143
158
  specification_version: 4
144
159
  summary: Fluentd Filter plugin to concat multiple event messages
145
160
  test_files: []
@@ -1,19 +0,0 @@
1
- #### Problem
2
-
3
- ...
4
-
5
- #### Steps to replicate
6
-
7
- Provide example config and message
8
-
9
- #### Expected Behavior
10
-
11
- ...
12
-
13
- #### Your environment
14
-
15
- * OS version
16
- * paste result of ``fluentd --version`` or ``td-agent --version``
17
- * plugin version
18
- * paste boot log of fluentd or td-agent
19
- * paste result of ``fluent-gem list``, ``td-agent-gem list`` or your Gemfile.lock
data/.travis.yml DELETED
@@ -1,19 +0,0 @@
1
- sudo: false
2
- language: ruby
3
-
4
- notifications:
5
- webhooks:
6
- urls:
7
- secure: NhOBulc3nFAnJrCr9G0/3IGd1pOb/Zk0Wyk9Jqrf7PHnI4mZOIgttGnewZx1sG96NWrs0Braue5vXwFBTrJ60J6EW3+Q33XzhaZR+Q95jEb+5vcdIP69TYs0TgOIiOouo69Y4rIE1ANYuF/1cBfCKxGulpOIKUCW5LYPkyUEwQy+7VccULctCYCha2OYHQau5SUITCQQqZMfYCvZ+9FRubhR+OiiAnwduuzixKm5b2sa2K4lCKy2vsz3JZtjvQ6/7WM5JsipErtuUY2fDlrWSr/9SehRu8LCD119FjV/HcaAffFMokX+8vJm6RLGcyx/0mAejEqaBofqf9vi1KQJKsKuEe8N9IUpoLrl36RYVfDDRNDqm0pSkrz/KaNxSSe5sDNsCFY+uEFhtiPMHJiSlyEA+BVqnUeoM9pSWp3pcTsIHAjq5VGfQ6u9IooUODCASBlOsLuPu+FYEWG3dC3oiOLEIqQ+WywJg2P7I4dJNhyivti5j61czipTGj28ReFiydp5macKabkvAFBvOW8q07QBO4cvjixhr8hiUgMEVdo5y5dqNhLvS182by3OpmtaSQfpuI8QXytiN9629lWzB7qu0Q7Pji/5wSqEuCdaEHjF5uCVYLFE2LaGJdlTLBg9n0vFfFpJXnP1q0nehq2qRs30pNcgkcCKfEIPJgFgCac=
8
- on_success: change
9
- on_failure: always
10
- on_start: never
11
-
12
- matrix:
13
- include:
14
- - rvm: 2.4.5
15
- gemfile: Gemfile
16
- - rvm: 2.5.5
17
- gemfile: Gemfile
18
- - rvm: 2.6.2
19
- gemfile: Gemfile