fluent-plugin-kubernetes_metadata_filter 0.29.0 → 0.30.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
  SHA1:
3
- metadata.gz: da9ac5757f2ae0199b718b45cf559a9c214eb486
4
- data.tar.gz: 808080db4f5fe7cd15d0972596be8b0bd6310d19
3
+ metadata.gz: ae88fa238369257fb50ba6989fc08f80986ec4a0
4
+ data.tar.gz: 263164257b94e338517a23e06b58e0a7b923f41a
5
5
  SHA512:
6
- metadata.gz: 9506b64f77aaf9c4c07bd55ca7939ee8a2fb6f14e527870ea0515d2f66527db45c2aff89ef5c38c9a345b65543ed20675a6c4a6773fb322bd0d30e24c6edb595
7
- data.tar.gz: 7e1812dd6c2e14a14e29def29bea2c28aef596a520edb0ac4aa8f87f3eedaac187681842e503cc87c5878ad1192aaab338afcac48c704b0828dc06d9ed7c3501
6
+ metadata.gz: e81f454859bbb3338de78dbc1b0d468d6ea87110aa41f89eafb09f1bfb1e482bb5ada1dd09cd96d892b21d7287c66c9073bf31c812bb381876c05783598b0ed2
7
+ data.tar.gz: 400599efefa4014dacb62a660a5f2a6c83a0b6012c53cd9e4f75d7cf27e9ce86823cfdb27ee5bf8204316ec391ac4e95d143eb40a67cd41692f418a9268caaf1
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'codeclimate-test-reporter', :group => :test, :require => nil
3
+ gem 'codeclimate-test-reporter', '<1.0.0', :group => :test, :require => nil
4
4
  gem 'rubocop', require: false
5
5
 
6
6
  # Specify your gem's dependencies in fluent-plugin-add.gemspec
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |gem|
6
6
  gem.name = "fluent-plugin-kubernetes_metadata_filter"
7
- gem.version = "0.29.0"
7
+ gem.version = "0.30.0"
8
8
  gem.authors = ["Jimmi Dyson"]
9
9
  gem.email = ["jimmidyson@gmail.com"]
10
10
  gem.description = %q{Filter plugin to add Kubernetes metadata}
@@ -16,6 +16,7 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
  #
19
+ require_relative 'kubernetes_metadata_stats'
19
20
  module Fluent
20
21
  class KubernetesMetadataFilter < Fluent::Filter
21
22
  K8_POD_CA_CERT = 'ca.crt'
@@ -57,6 +58,7 @@ module Fluent
57
58
  :default => '^(?<name_prefix>[^_]+)_(?<container_name>[^\._]+)(\.(?<container_hash>[^_]+))?_(?<pod_name>[^_]+)_(?<namespace>[^_]+)_[^_]+_[^_]+$'
58
59
 
59
60
  config_param :annotation_match, :array, default: []
61
+ config_param :stats_interval, :integer, default: 30
60
62
 
61
63
  def syms_to_strs(hsh)
62
64
  newhsh = {}
@@ -110,15 +112,63 @@ module Fluent
110
112
  def get_pod_metadata(namespace_name, pod_name)
111
113
  begin
112
114
  metadata = @client.get_pod(pod_name, namespace_name)
113
- return if !metadata
114
- return parse_pod_metadata(metadata)
115
- rescue KubeException
115
+ unless metadata
116
+ @stats.bump(:pod_cache_api_nil_not_found)
117
+ else
118
+ begin
119
+ metadata = parse_pod_metadata(metadata)
120
+ @stats.bump(:pod_cache_api_updates)
121
+ return metadata
122
+ rescue Exception=>e
123
+ log.debug(e)
124
+ @stats.bump(:pod_cache_api_nil_bad_resp_payload)
125
+ nil
126
+ end
127
+ end
128
+ rescue KubeException=>e
129
+ @stats.bump(:pod_cache_api_nil_error)
130
+ log.debug "Exception encountered fetching pod metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}: #{e.message}"
131
+ nil
132
+ end
133
+ end
134
+
135
+ def dump_stats
136
+ @curr_time = Time.now
137
+ return if @curr_time.to_i - @prev_time.to_i < @stats_interval
138
+ @prev_time = @curr_time
139
+ @stats.set(:pod_cache_size, @cache.count)
140
+ @stats.set(:namespace_cache_size, @namespace_cache.count)
141
+ log.info(@stats)
142
+ end
143
+
144
+ def get_namespace_metadata(namespace_name)
145
+ begin
146
+ metadata = @client.get_namespace(namespace_name)
147
+ unless metadata
148
+ @stats.bump(:namespace_cache_api_nil_not_found)
149
+ else
150
+ begin
151
+ metadata = parse_namespace_metadata(metadata)
152
+ @stats.bump(:namespace_cache_api_updates)
153
+ return metadata
154
+ rescue Exception => e
155
+ log.debug(e)
156
+ @stats.bump(:namespace_cache_api_nil_bad_resp_payload)
157
+ nil
158
+ end
159
+ end
160
+ rescue KubeException => kube_error
161
+ @stats.bump(:namespace_cache_api_nil_error)
162
+ log.debug "Exception encountered fetching namespace metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}: #{kube_error.message}"
116
163
  nil
117
164
  end
118
165
  end
119
166
 
120
167
  def initialize
121
168
  super
169
+ @stats = KubernetesMetadata::Stats.new
170
+ @prev_time = Time.now
171
+
122
172
  end
123
173
 
124
174
  def configure(conf)
@@ -235,6 +285,7 @@ module Fluent
235
285
 
236
286
  this = self
237
287
  pod_metadata = @cache.getset(cache_key) {
288
+ @stats.bump(:pod_cache_miss)
238
289
  md = this.get_pod_metadata(
239
290
  namespace_name,
240
291
  pod_name,
@@ -245,14 +296,8 @@ module Fluent
245
296
 
246
297
  if @include_namespace_metadata
247
298
  namespace_metadata = @namespace_cache.getset(namespace_name) {
248
- begin
249
- namespace = @client.get_namespace(namespace_name)
250
- if namespace
251
- parse_namespace_metadata(namespace)
252
- end
253
- rescue KubeException
254
- nil
255
- end
299
+ @stats.bump(:namespace_cache_miss)
300
+ get_namespace_metadata(namespace_name)
256
301
  }
257
302
  metadata.merge!(namespace_metadata) if namespace_metadata
258
303
  end
@@ -289,7 +334,7 @@ module Fluent
289
334
 
290
335
  new_es.add(time, record)
291
336
  }
292
-
337
+ dump_stats
293
338
  new_es
294
339
  end
295
340
 
@@ -317,9 +362,11 @@ module Fluent
317
362
  end
318
363
  unless metadata
319
364
  log.debug "Error: could not match CONTAINER_NAME from record #{record}"
365
+ @stats.dump(:container_name_match_failed)
320
366
  end
321
367
  elsif record.has_key?('CONTAINER_NAME') && record['CONTAINER_NAME'].start_with?('k8s_')
322
368
  log.debug "Error: no container name and id in record #{record}"
369
+ @stats.dump(:container_name_id_missing)
323
370
  end
324
371
 
325
372
  if metadata
@@ -329,6 +376,7 @@ module Fluent
329
376
  new_es.add(time, record)
330
377
  }
331
378
 
379
+ dump_stats
332
380
  new_es
333
381
  end
334
382
 
@@ -341,7 +389,9 @@ module Fluent
341
389
  unless @preserve_json_log
342
390
  record.delete(@merge_json_log_key)
343
391
  end
344
- rescue JSON::ParserError
392
+ rescue JSON::ParserError=>e
393
+ @stats.bump(:merge_json_parse_errors)
394
+ log.debug(e)
345
395
  end
346
396
  end
347
397
  end
@@ -376,9 +426,7 @@ module Fluent
376
426
  watcher = @client.watch_pods(resource_version)
377
427
  rescue Exception => e
378
428
  message = "Exception encountered fetching metadata from Kubernetes API endpoint: #{e.message}"
379
- if e.respond_to?(:response)
380
- message += " (#{e.response})"
381
- end
429
+ message += " (#{e.response})" if e.respond_to?(:response)
382
430
 
383
431
  raise Fluent::ConfigError, message
384
432
  end
@@ -390,20 +438,32 @@ module Fluent
390
438
  cached = @cache[cache_key]
391
439
  if cached
392
440
  @cache[cache_key] = parse_pod_metadata(notice.object)
441
+ @stats.bump(:pod_cache_watch_updates)
442
+ else
443
+ @stats.bump(:pod_cache_watch_misses)
393
444
  end
394
445
  when 'DELETED'
395
446
  cache_key = "#{notice.object['metadata']['namespace']}_#{notice.object['metadata']['name']}"
396
447
  @cache.delete(cache_key)
448
+ @stats.bump(:pod_cache_watch_deletes)
397
449
  else
398
450
  # Don't pay attention to creations, since the created pod may not
399
451
  # end up on this node.
452
+ @stats.bump(:pod_cache_watch_ignored)
400
453
  end
401
454
  end
402
455
  end
403
456
 
404
457
  def start_namespace_watch
405
- resource_version = @client.get_namespaces.resourceVersion
406
- watcher = @client.watch_namespaces(resource_version)
458
+ begin
459
+ resource_version = @client.get_namespaces.resourceVersion
460
+ watcher = @client.watch_namespaces(resource_version)
461
+ rescue Exception=>e
462
+ message = "start_namespace_watch: Exception encountered setting up namespace watch from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}: #{e.message}"
463
+ message += " (#{e.response})" if e.respond_to?(:response)
464
+ log.debug(message)
465
+ raise Fluent::ConfigError, message
466
+ end
407
467
  watcher.each do |notice|
408
468
  case notice.type
409
469
  when 'MODIFIED'
@@ -411,12 +471,17 @@ module Fluent
411
471
  cached = @namespace_cache[cache_key]
412
472
  if cached
413
473
  @namespace_cache[cache_key] = parse_namespace_metadata(notice.object)
474
+ @stats.bump(:namespace_cache_watch_updates)
475
+ else
476
+ @stats.bump(:namespace_cache_watch_misses)
414
477
  end
415
478
  when 'DELETED'
416
479
  @namespace_cache.delete(notice.object['metadata']['name'])
480
+ @stats.bump(:namespace_cache_watch_deletes)
417
481
  else
418
482
  # Don't pay attention to creations, since the created namespace may not
419
483
  # be used by any pod on this node.
484
+ @stats.bump(:namespace_cache_watch_ignored)
420
485
  end
421
486
  end
422
487
  end
@@ -0,0 +1,41 @@
1
+ #
2
+ # Fluentd Kubernetes Metadata Filter Plugin - Enrich Fluentd events with
3
+ # Kubernetes metadata
4
+ #
5
+ # Copyright 2015 Red Hat, Inc.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ module KubernetesMetadata
20
+ class Stats
21
+
22
+ def initialize
23
+ @stats = LruRedux::TTL::ThreadSafeCache.new(1000, 3600)
24
+ end
25
+
26
+ def bump(key)
27
+ @stats[key] = @stats.getset(key) { 0 } + 1
28
+ end
29
+
30
+ def set(key, value)
31
+ @stats[key] = value
32
+ end
33
+
34
+ def to_s
35
+ "stats - " + [].tap do |a|
36
+ @stats.each {|k,v| a << "#{k.to_s}: #{v}"}
37
+ end.join(', ')
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,36 @@
1
+ #
2
+ # Fluentd Kubernetes Metadata Filter Plugin - Enrich Fluentd events with
3
+ # Kubernetes metadata
4
+ #
5
+ # Copyright 2015 Red Hat, Inc.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ require_relative '../helper'
20
+ require 'fluent/plugin/kubernetes_metadata_stats'
21
+ require 'webmock/test_unit'
22
+ WebMock.disable_net_connect!
23
+
24
+ class KubernetesMetadataCacheStatsTest < Test::Unit::TestCase
25
+
26
+ test 'watch stats' do
27
+ require 'lru_redux'
28
+ stats = KubernetesMetadata::Stats.new
29
+ stats.bump(:missed)
30
+ stats.bump(:deleted)
31
+ stats.bump(:deleted)
32
+
33
+ assert_equal("stats - deleted: 2, missed: 1", stats.to_s)
34
+ end
35
+
36
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-kubernetes_metadata_filter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.29.0
4
+ version: 0.30.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jimmi Dyson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-08-17 00:00:00.000000000 Z
11
+ date: 2017-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -207,6 +207,7 @@ files:
207
207
  - circle.yml
208
208
  - fluent-plugin-kubernetes_metadata_filter.gemspec
209
209
  - lib/fluent/plugin/filter_kubernetes_metadata.rb
210
+ - lib/fluent/plugin/kubernetes_metadata_stats.rb
210
211
  - test/cassettes/invalid_api_server_config.yml
211
212
  - test/cassettes/kubernetes_docker_metadata.yml
212
213
  - test/cassettes/kubernetes_docker_metadata_annotations.yml
@@ -217,6 +218,7 @@ files:
217
218
  - test/cassettes/valid_kubernetes_api_server.yml
218
219
  - test/helper.rb
219
220
  - test/plugin/test.token
221
+ - test/plugin/test_cache_stats.rb
220
222
  - test/plugin/test_filter_kubernetes_metadata.rb
221
223
  homepage: https://github.com/fabric8io/fluent-plugin-kubernetes_metadata_filter
222
224
  licenses:
@@ -238,7 +240,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
238
240
  version: '0'
239
241
  requirements: []
240
242
  rubyforge_project:
241
- rubygems_version: 2.6.8
243
+ rubygems_version: 2.6.12
242
244
  signing_key:
243
245
  specification_version: 4
244
246
  summary: Filter plugin to add Kubernetes metadata
@@ -253,4 +255,5 @@ test_files:
253
255
  - test/cassettes/valid_kubernetes_api_server.yml
254
256
  - test/helper.rb
255
257
  - test/plugin/test.token
258
+ - test/plugin/test_cache_stats.rb
256
259
  - test/plugin/test_filter_kubernetes_metadata.rb