fluent-plugin-label-router 0.2.2 → 0.2.7

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: 323aeb0b86fedafdcca48546cb3eed9aa7523efa01df41c3f9a46cd069cd76bb
4
- data.tar.gz: b42d4410cdbacabcf49a8eb2f5d8f8be01d3761efb9b436370ba3166a64eaeb3
3
+ metadata.gz: 9fcacfb0c98686f99facd3bd94da5fa8065b4446cf1d2e5850a3e1456e5721d1
4
+ data.tar.gz: 65f9d48cbf0636faa0544b052d16465760cc74c9a8fe3fb8aa378f122f7d0da6
5
5
  SHA512:
6
- metadata.gz: 3e0989c5509dda968b509bb1ec2b01f125b83353aaa7347a68364b2412b41eec93187d320d5005dde9d9e9fadda1afb9ce8b6416dcb86771f6646dd0c8ade2ce
7
- data.tar.gz: 5c53945c123e3271223dff6e04d9eb41bbb674c0876ce62f48af49f70b9adb7c90218c8e70899557b9a20215d999434f595e47dfb1f34a55bf817233b5ddf955
6
+ metadata.gz: 6b1f0a77e69be61a6ade1329b4e1caa58dde56fdd0d2313bbfa54476342d5d04cacdbd71dac21f5b04ce191f5839624f25ff4d3c765f6d627a48e8c692b86bb8
7
+ data.tar.gz: 3129f7a8a90f4d175941b9a719c96796245ed58bae0c0d60dbb42a608c310079b512aafb2385aebc7cee35b9df51c4bf781f3831696085f4438cce633c9e095a
data/README.md CHANGED
@@ -192,7 +192,7 @@ Use `default_label` and/or `default_tag` to route non matching records.
192
192
  ```
193
193
  <match example.tag**>
194
194
  @type label_router
195
- default_label @default_sink
195
+ default_route @default_sink
196
196
  <route>
197
197
  ...
198
198
  </route>
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "fluent-plugin-label-router"
6
- spec.version = "0.2.2"
6
+ spec.version = "0.2.7"
7
7
  spec.authors = ["Banzai Cloud"]
8
8
  spec.email = ["info@banzaicloud.com"]
9
9
 
@@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
20
20
  spec.test_files = test_files
21
21
  spec.require_paths = ["lib"]
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.14"
24
23
  spec.add_development_dependency "rake", "~> 12.0"
25
24
  spec.add_development_dependency "test-unit", "~> 3.0"
25
+ spec.add_dependency "prometheus-client", ">= 2.1.0"
26
26
  spec.add_runtime_dependency "fluentd", [">= 0.14.10", "< 2"]
27
27
  end
@@ -11,10 +11,11 @@
11
11
  # distributed under the License is distributed on an "AS IS" BASIS,
12
12
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  # See the License for the specific language governing permissions and
14
- # limitations under the License.
14
+ # limitations under the License
15
15
 
16
16
  require "fluent/plugin/output"
17
- require 'digest/md5'
17
+ require 'prometheus/client'
18
+
18
19
 
19
20
  module Fluent
20
21
  module Plugin
@@ -34,12 +35,16 @@ module Fluent
34
35
  config_param :default_route, :string, :default => ""
35
36
  desc "Default tag to drain unmatched patterns"
36
37
  config_param :default_tag, :string, :default => ""
38
+ desc "Enable metrics for the router"
39
+ config_param :metrics, :bool, :default => false
37
40
 
38
41
  config_section :route, param_name: :routes, multi: true do
39
42
  desc "New @LABEL if selectors matched"
40
43
  config_param :@label, :string, :default => nil
41
44
  desc "New tag if selectors matched"
42
45
  config_param :tag, :string, :default => ""
46
+ desc "Extra labels for metrics"
47
+ config_param :metrics_labels, :hash, :default => {}
43
48
 
44
49
  config_section :match, param_name: :matches, multi: true do
45
50
  desc "Label definition to match record. Example: app:nginx. You can specify more values as comma separated list: key1:value1,key2:value2"
@@ -56,10 +61,22 @@ module Fluent
56
61
  end
57
62
 
58
63
  class Route
59
- def initialize(matches, tag, router)
64
+ def initialize(rule, router, registry)
60
65
  @router = router
61
- @matches = matches
62
- @tag = tag
66
+ @matches = rule['matches']
67
+ @tag = rule['tag'].to_s
68
+ @label = rule['@label']
69
+ @metrics_labels = (rule['metrics_labels'].map { |k, v| [k.to_sym, v] }.to_h if rule['metrics_labels'])
70
+ @counter = nil
71
+ unless registry.nil?
72
+ @counter = registry.counter(:fluentd_router_records_total, docstring: "Total number of events router for the flow", labels: [:flow])
73
+ end
74
+ end
75
+
76
+ def get_labels
77
+ default = { 'flow': @label }
78
+ labels = default.merge(@metrics_labels)
79
+ labels
63
80
  end
64
81
 
65
82
  # Evaluate selectors
@@ -88,7 +105,7 @@ module Fluent
88
105
  return false
89
106
  end
90
107
  # Break on host mismatch
91
- unless match.container_names.empty? || match.container_names.include?(metadata[:container_name])
108
+ unless match.container_names.empty? || match.container_names.include?(metadata[:container])
92
109
  return false
93
110
  end
94
111
  # Break if list of namespaces is not empty and does not include actual namespace
@@ -113,6 +130,8 @@ module Fluent
113
130
  else
114
131
  @router.emit_stream(@tag, es)
115
132
  end
133
+ # increment the counter for a given label set
134
+ @counter&.increment(by: es.size, labels: get_labels)
116
135
  end
117
136
 
118
137
  def match_labels(input, match)
@@ -122,13 +141,15 @@ module Fluent
122
141
 
123
142
  def process(tag, es)
124
143
  if @sticky_tags
125
- if @route_map.has_key?(tag)
126
- # We already matched with this tag send events to the routers
127
- @route_map[tag].each do |r|
128
- r.emit_es(tag, es.dup)
144
+ @mutex.synchronize {
145
+ if @route_map.has_key?(tag)
146
+ # We already matched with this tag send events to the routers
147
+ @route_map[tag].each do |r|
148
+ r.emit_es(tag, es.dup)
149
+ end
150
+ return
129
151
  end
130
- return
131
- end
152
+ }
132
153
  end
133
154
  event_stream = Hash.new {|h, k| h[k] = Fluent::MultiEventStream.new }
134
155
  es.each do |time, record|
@@ -141,7 +162,9 @@ module Fluent
141
162
  if r.match?(input_metadata)
142
163
  orphan_record = false
143
164
  if @sticky_tags
144
- @route_map[tag].push(r)
165
+ @mutex.synchronize {
166
+ @route_map[tag].add(r)
167
+ }
145
168
  end
146
169
  if @batch
147
170
  event_stream[r].add(time, record)
@@ -152,7 +175,9 @@ module Fluent
152
175
  end
153
176
  if !@default_router.nil? && orphan_record
154
177
  if @sticky_tags
155
- @route_map[tag].push(@default_router)
178
+ @mutex.synchronize {
179
+ @route_map[tag].add(@default_router)
180
+ }
156
181
  end
157
182
  if @batch
158
183
  event_stream[@default_router].add(time, record)
@@ -170,17 +195,19 @@ module Fluent
170
195
 
171
196
  def configure(conf)
172
197
  super
173
- @route_map = Hash.new { |h, k| h[k] = Array.new }
198
+ @registry = (::Prometheus::Client.registry if @metrics)
199
+ @route_map = Hash.new { |h, k| h[k] = Set.new }
200
+ @mutex = Mutex.new
174
201
  @routers = []
175
202
  @default_router = nil
176
203
  @routes.each do |rule|
177
204
  route_router = event_emitter_router(rule['@label'])
178
- puts rule
179
- @routers << Route.new(rule.matches, rule.tag.to_s, route_router)
205
+ @routers << Route.new(rule, route_router, @registry)
180
206
  end
181
207
 
182
208
  if @default_route != '' or @default_tag != ''
183
- @default_router = Route.new(nil, @default_tag, event_emitter_router(@default_route))
209
+ default_rule = { 'matches' => nil, 'tag' => @default_tag, '@label' => @default_route}
210
+ @default_router = Route.new(default_rule, event_emitter_router(@default_route), @registry)
184
211
  end
185
212
 
186
213
  @access_to_labels = record_accessor_create("$.kubernetes.labels")
@@ -76,7 +76,7 @@ class LabelRouterOutputTest < Test::Unit::TestCase
76
76
  d = Fluent::Test::Driver::BaseOwner.new(Fluent::Plugin::LabelRouterOutput)
77
77
  d.configure(routing_conf)
78
78
 
79
- r1 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[0].matches, d.instance.routes[0].tag,nil)
79
+ r1 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[0], nil,nil)
80
80
  # Selector matched: GO
81
81
  assert_equal(true, r1.match?(labels: { 'app' => 'app1' }, namespace: ''))
82
82
  # Exclude match: NO GO
@@ -84,7 +84,7 @@ class LabelRouterOutputTest < Test::Unit::TestCase
84
84
  # Nothing matched: NO GO
85
85
  assert_equal(false, r1.match?(labels: { 'app3' => 'app2' }, namespace: ''))
86
86
 
87
- r2 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[1].matches, d.instance.routes[1].tag,nil)
87
+ r2 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[1], nil,nil)
88
88
  # Match selector and namespace: GO
89
89
  assert_equal(true, r2.match?(labels: { 'app' => 'app1' }, namespace: 'test'))
90
90
  # Exclude via namespace
@@ -92,18 +92,18 @@ class LabelRouterOutputTest < Test::Unit::TestCase
92
92
  # Nothing matched: NO GO
93
93
  assert_equal(false, r2.match?(labels: { 'app3' => 'app' }, namespace: 'system'))
94
94
 
95
- r3 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[2].matches, d.instance.routes[2].tag,nil)
95
+ r3 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[2], nil,nil)
96
96
  assert_equal(true, r3.match?(labels: { 'app' => 'nginx' }, namespace: 'dev'))
97
97
  assert_equal(true, r3.match?(labels: { 'app' => 'nginx' }, namespace: 'sandbox'))
98
98
  assert_equal(false, r3.match?(labels: { 'app' => 'nginx2' }, namespace: 'sandbox'))
99
99
 
100
- r4 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[3].matches, d.instance.routes[3].tag,nil)
100
+ r4 = Fluent::Plugin::LabelRouterOutput::Route.new(d.instance.routes[3], nil,nil)
101
101
  # Matching container name
102
- assert_equal(true, r4.match?(labels: { 'app' => 'nginx' }, namespace: 'dev', container_name: 'mycontainer'))
102
+ assert_equal(true, r4.match?(labels: { 'app' => 'nginx' }, namespace: 'dev', container: 'mycontainer'))
103
103
  # Missing container name is equal to wrong container
104
104
  assert_equal(false, r4.match?(labels: { 'app' => 'nginx' }, namespace: 'sandbox'))
105
105
  # Wrong container name
106
- assert_equal(false, r4.match?(labels: { 'app' => 'nginx' }, namespace: 'dev', container_name: 'mycontainer2'))
106
+ assert_equal(false, r4.match?(labels: { 'app' => 'nginx' }, namespace: 'dev', container: 'mycontainer2'))
107
107
  # Wrong label but good namespace and container_name
108
108
  assert_equal(false, r4.match?(labels: { 'app' => 'nginx2' }, namespace: 'sandbox', container_name: 'mycontainer2'))
109
109
  end
@@ -208,4 +208,33 @@ default_tag "new_tag"
208
208
  assert_equal ["new_app_tag", event_time, {"kubernetes" => {"labels" => {"app" => "app2"} } }], events[1]
209
209
  end
210
210
  end
211
+
212
+ sub_test_case 'test_metrics' do
213
+ test 'normal' do
214
+ CONFIG4 = %[
215
+ metrics true
216
+ <route>
217
+ tag new_app_tag
218
+ <match>
219
+ labels
220
+ namespaces
221
+ </match>
222
+ </route>
223
+ ]
224
+ event_time = event_time("2019-07-17 11:11:11 UTC")
225
+ d = create_driver(CONFIG4)
226
+ d.run(default_tag: 'test') do
227
+ d.feed(event_time, {"kubernetes" => {"labels" => {"app" => "app1"} } } )
228
+ end
229
+ d.run(default_tag: 'test2') do
230
+ d.feed(event_time, {"kubernetes" => {"labels" => {"app" => "app2"} } } )
231
+ end
232
+ events = d.events
233
+
234
+ assert_equal(2, events.size)
235
+ assert_equal ["new_app_tag", event_time, {"kubernetes" => {"labels" => {"app" => "app1"} } }], events[0]
236
+ assert_equal ["new_app_tag", event_time, {"kubernetes" => {"labels" => {"app" => "app2"} } }], events[1]
237
+ end
238
+ end
239
+
211
240
  end
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-label-router
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Banzai Cloud
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-24 00:00:00.000000000 Z
11
+ date: 2021-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.14'
19
+ version: '12.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.14'
26
+ version: '12.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: test-unit
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '12.0'
33
+ version: '3.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '12.0'
40
+ version: '3.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: test-unit
42
+ name: prometheus-client
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '3.0'
48
- type: :development
47
+ version: 2.1.0
48
+ type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '3.0'
54
+ version: 2.1.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: fluentd
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -92,7 +92,7 @@ homepage: https://github.com/banzaicloud/fluent-plugin-label-router
92
92
  licenses:
93
93
  - Apache-2.0
94
94
  metadata: {}
95
- post_install_message:
95
+ post_install_message:
96
96
  rdoc_options: []
97
97
  require_paths:
98
98
  - lib
@@ -107,8 +107,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
107
  - !ruby/object:Gem::Version
108
108
  version: '0'
109
109
  requirements: []
110
- rubygems_version: 3.0.3
111
- signing_key:
110
+ rubygems_version: 3.1.6
111
+ signing_key:
112
112
  specification_version: 4
113
113
  summary: Routing records based on Kubernetes labels.
114
114
  test_files: