fluent-plugin-kubernetes_metadata_filter 0.29.0 → 0.30.0

Sign up to get free protection for your applications and to get access to all the features.
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