fluent-plugin-kubernetes_metadata_filter 1.2.2 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile +1 -5
- data/README.md +3 -35
- data/circle.yml +2 -0
- data/fluent-plugin-kubernetes_metadata_filter.gemspec +4 -13
- data/lib/fluent/plugin/filter_kubernetes_metadata.rb +116 -79
- data/lib/fluent/plugin/kubernetes_metadata_cache_strategy.rb +1 -1
- data/lib/fluent/plugin/kubernetes_metadata_common.rb +0 -46
- data/lib/fluent/plugin/kubernetes_metadata_watch_pods.rb +0 -3
- data/test/cassettes/kubernetes_docker_metadata_using_bearer_token.yml +1 -1
- data/test/plugin/test_filter_kubernetes_metadata.rb +247 -345
- data/test/plugin/test_watch_pods.rb +3 -46
- metadata +13 -10
- data/test/cassettes/metadata_from_tag_and_journald_fields.yml +0 -408
- data/test/cassettes/metadata_from_tag_journald_and_kubernetes_fields.yml +0 -540
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3e76bf94f6dd2d7d375b01379c3a0533670291e7
|
4
|
+
data.tar.gz: 0cf265d4423a322313a6233a9360c0438081f878
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c52356d4f5edc444bfb26b9f812257cafc250328f7de81708bb7f3e64711c1c85895a46877537d7fd5d17e486f75328900a848d80625e6450922672005b7ce6a
|
7
|
+
data.tar.gz: 4d0e4b4cdfd0734736419d32fe4237130e81fd04cc6612a5ea5f1eca22c69b8300b8ea4baeeca943b63dad93f256aeb7f35bd160f753a1a28ad650d395ba43b4
|
data/Gemfile
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
gem 'codeclimate-test-reporter', '<1.0.0', :group => :test, :require => nil
|
4
|
-
|
5
|
-
gem 'rubocop', '<0.51.0', require: false
|
6
|
-
else
|
7
|
-
gem 'rubocop', require: false
|
8
|
-
end
|
4
|
+
gem 'rubocop', require: false
|
9
5
|
|
10
6
|
# Specify your gem's dependencies in fluent-plugin-add.gemspec
|
11
7
|
gemspec
|
data/README.md
CHANGED
@@ -42,10 +42,11 @@ This must used named capture groups for `container_name`, `pod_name` & `namespac
|
|
42
42
|
* `cache_size` - size of the cache of Kubernetes metadata to reduce requests to the API server (default: `1000`)
|
43
43
|
* `cache_ttl` - TTL in seconds of each cached element. Set to negative value to disable TTL eviction (default: `3600` - 1 hour)
|
44
44
|
* `watch` - set up a watch on pods on the API server for updates to metadata (default: `true`)
|
45
|
+
* `merge_json_log` - merge logs in JSON format as top level keys (default: `true`)
|
46
|
+
* `preserve_json_log` - preserve JSON logs in raw form in the `log` key, only used if the previous option is true (default: `true`)
|
45
47
|
* `de_dot` - replace dots in labels and annotations with configured `de_dot_separator`, required for ElasticSearch 2.x compatibility (default: `true`)
|
46
48
|
* `de_dot_separator` - separator to use if `de_dot` is enabled (default: `_`)
|
47
|
-
*
|
48
|
-
if available, otherwise, will use the tag in the `tag_to_kubernetes_name_regexp` format.
|
49
|
+
* `use_journal` - If false (default), messages are expected to be formatted and tagged as if read by the fluentd in\_tail plugin with wildcard filename. If true, messages are expected to be formatted as if read from the systemd journal. The `MESSAGE` field has the full message. The `CONTAINER_NAME` field has the encoded k8s metadata (see below). The `CONTAINER_ID_FULL` field has the full container uuid. This requires docker to use the `--log-driver=journald` log driver.
|
49
50
|
* `container_name_to_kubernetes_regexp` - The regular expression used to extract the k8s metadata encoded in the journal `CONTAINER_NAME` field (default: `'^(?<name_prefix>[^_]+)_(?<container_name>[^\._]+)(\.(?<container_hash>[^_]+))?_(?<pod_name>[^_]+)_(?<namespace>[^_]+)_[^_]+_[^_]+$'`
|
50
51
|
* This corresponds to the definition [in the source](https://github.com/kubernetes/kubernetes/blob/master/pkg/kubelet/dockertools/docker.go#L317)
|
51
52
|
* `annotation_match` - Array of regular expressions matching annotation field names. Matched annotations are added to a log record.
|
@@ -53,23 +54,6 @@ if available, otherwise, will use the tag in the `tag_to_kubernetes_name_regexp`
|
|
53
54
|
when true (default: `true`)
|
54
55
|
* `orphaned_namespace_name` - The namespace to associate with records where the namespace can not be determined (default: `.orphaned`)
|
55
56
|
* `orphaned_namespace_id` - The namespace id to associate with records where the namespace can not be determined (default: `orphaned`)
|
56
|
-
* `lookup_from_k8s_field` - If the field `kubernetes` is present, lookup the metadata from the given subfields such as `kubernetes.namespace_name`, `kubernetes.pod_name`, etc. This allows you to avoid having to pass in metadata to lookup in an explicitly formatted tag name or in an explicitly formatted `CONTAINER_NAME` value. For example, set `kubernetes.namespace_name`, `kubernetes.pod_name`, `kubernetes.container_name`, and `docker.id` in the record, and the filter will fill in the rest. (default: `true`)
|
57
|
-
|
58
|
-
**NOTE:** As of the release 1.1.x of this plugin, it no longer supports parsing the source message into JSON and attaching it to the
|
59
|
-
payload. The following configuration options are removed:
|
60
|
-
|
61
|
-
* `merge_json_log`
|
62
|
-
* `preserve_json_log`
|
63
|
-
|
64
|
-
**NOTE** As of this release, the use of `use_journal` is **DEPRECATED**. If this setting is not present, the plugin will
|
65
|
-
attempt to figure out the source of the metadata fields from the following:
|
66
|
-
- If `lookup_from_k8s_field true` (the default) and the following fields are present in the record:
|
67
|
-
`docker.container_id`, `kubernetes.namespace_name`, `kubernetes.pod_name`, `kubernetes.container_name`,
|
68
|
-
then the plugin will use those values as the source to use to lookup the metadata
|
69
|
-
- If `use_journal true`, or `use_journal` is unset, and the fields `CONTAINER_NAME` and `CONTAINER_ID_FULL` are present in the record,
|
70
|
-
then the plugin will parse those values using `container_name_to_kubernetes_regexp` and use those as the source to lookup the metadata
|
71
|
-
- Otherwise, if the tag matches `tag_to_kubernetes_name_regexp`, the plugin will parse the tag and use those values to
|
72
|
-
lookup the metdata
|
73
57
|
|
74
58
|
Reading from the JSON formatted log files with `in_tail` and wildcard filenames:
|
75
59
|
```
|
@@ -120,22 +104,6 @@ Reading from the systemd journal (requires the fluentd `fluent-plugin-systemd` a
|
|
120
104
|
</match>
|
121
105
|
```
|
122
106
|
|
123
|
-
## Environment variables for Kubernetes
|
124
|
-
|
125
|
-
If the name of the Kubernetes node the plugin is running on is set as
|
126
|
-
an environment variable with the name `K8S_NODE_NAME`, it will reduce cache
|
127
|
-
misses and needless calls to the Kubernetes API.
|
128
|
-
|
129
|
-
In the Kubernetes container definition, this is easily accomplished by:
|
130
|
-
|
131
|
-
```yaml
|
132
|
-
env:
|
133
|
-
- name: K8S_NODE_NAME
|
134
|
-
valueFrom:
|
135
|
-
fieldRef:
|
136
|
-
fieldPath: spec.nodeName
|
137
|
-
```
|
138
|
-
|
139
107
|
## Example input/output
|
140
108
|
|
141
109
|
Kubernetes creates symlinks to Docker log files in `/var/log/containers/*.log`. Docker logs in JSON format.
|
data/circle.yml
CHANGED
@@ -7,9 +7,11 @@ dependencies:
|
|
7
7
|
- 'rvm-exec 2.1.9 bundle install'
|
8
8
|
- 'rvm-exec 2.2.5 bundle install'
|
9
9
|
- 'rvm-exec 2.3.1 bundle install'
|
10
|
+
- 'rvm-exec 2.4.3 bundle install'
|
10
11
|
|
11
12
|
test:
|
12
13
|
override:
|
13
14
|
- 'rvm-exec 2.1.9 bundle exec rake test'
|
14
15
|
- 'rvm-exec 2.2.5 bundle exec rake test'
|
15
16
|
- 'rvm-exec 2.3.1 bundle exec rake test'
|
17
|
+
- 'rvm-exec 2.4.3 bundle exec rake test'
|
@@ -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 = "
|
7
|
+
gem.version = "2.0.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}
|
@@ -18,23 +18,14 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
gem.has_rdoc = false
|
20
20
|
|
21
|
-
gem.required_ruby_version = '>= 2.
|
21
|
+
gem.required_ruby_version = '>= 2.1.0'
|
22
22
|
|
23
|
-
gem.add_runtime_dependency
|
23
|
+
gem.add_runtime_dependency 'fluentd', ['>= 0.14.0', '< 2']
|
24
24
|
gem.add_runtime_dependency "lru_redux"
|
25
25
|
gem.add_runtime_dependency "kubeclient", "~> 1.1.4"
|
26
|
-
if RUBY_VERSION == "2.0.0"
|
27
|
-
gem.add_runtime_dependency "public_suffix", "< 3"
|
28
|
-
gem.add_runtime_dependency "parallel", "< 1.14"
|
29
|
-
gem.add_runtime_dependency "rainbow", "< 3"
|
30
|
-
end
|
31
26
|
|
32
27
|
gem.add_development_dependency "bundler", "~> 1.3"
|
33
|
-
|
34
|
-
gem.add_development_dependency "rake", "< 13"
|
35
|
-
else
|
36
|
-
gem.add_development_dependency "rake"
|
37
|
-
end
|
28
|
+
gem.add_development_dependency "rake"
|
38
29
|
gem.add_development_dependency "minitest", "~> 4.0"
|
39
30
|
gem.add_development_dependency "test-unit", "~> 3.0.2"
|
40
31
|
gem.add_development_dependency "test-unit-rr", "~> 1.0.3"
|
@@ -23,8 +23,10 @@ require_relative 'kubernetes_metadata_stats'
|
|
23
23
|
require_relative 'kubernetes_metadata_watch_namespaces'
|
24
24
|
require_relative 'kubernetes_metadata_watch_pods'
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
require 'fluent/plugin/filter'
|
27
|
+
|
28
|
+
module Fluent::Plugin
|
29
|
+
class KubernetesMetadataFilter < Fluent::Plugin::Filter
|
28
30
|
K8_POD_CA_CERT = 'ca.crt'
|
29
31
|
K8_POD_TOKEN = 'token'
|
30
32
|
|
@@ -48,6 +50,8 @@ module Fluent
|
|
48
50
|
:string,
|
49
51
|
:default => 'var\.log\.containers\.(?<pod_name>[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace>[^_]+)_(?<container_name>.+)-(?<docker_id>[a-z0-9]{64})\.log$'
|
50
52
|
config_param :bearer_token_file, :string, default: nil
|
53
|
+
config_param :merge_json_log, :bool, default: true
|
54
|
+
config_param :preserve_json_log, :bool, default: true
|
51
55
|
config_param :secret_dir, :string, default: '/var/run/secrets/kubernetes.io/serviceaccount'
|
52
56
|
config_param :de_dot, :bool, default: true
|
53
57
|
config_param :de_dot_separator, :string, default: '_'
|
@@ -55,7 +59,7 @@ module Fluent
|
|
55
59
|
# format:
|
56
60
|
# CONTAINER_NAME=k8s_$containername.$containerhash_$podname_$namespacename_$poduuid_$rand32bitashex
|
57
61
|
# CONTAINER_FULL_ID=dockeridassha256hexvalue
|
58
|
-
config_param :use_journal, :bool, default:
|
62
|
+
config_param :use_journal, :bool, default: false
|
59
63
|
# Field 2 is the container_hash, field 5 is the pod_id, and field 6 is the pod_randhex
|
60
64
|
# I would have included them as named groups, but you can't have named groups that are
|
61
65
|
# non-capturing :P
|
@@ -69,7 +73,6 @@ module Fluent
|
|
69
73
|
config_param :allow_orphans, :bool, default: true
|
70
74
|
config_param :orphaned_namespace_name, :string, default: '.orphaned'
|
71
75
|
config_param :orphaned_namespace_id, :string, default: 'orphaned'
|
72
|
-
config_param :lookup_from_k8s_field, :bool, default: true
|
73
76
|
|
74
77
|
def fetch_pod_metadata(namespace_name, pod_name)
|
75
78
|
log.trace("fetching pod metadata: #{namespace_name}/#{pod_name}") if log.trace?
|
@@ -89,12 +92,12 @@ module Fluent
|
|
89
92
|
rescue Exception=>e
|
90
93
|
log.debug(e)
|
91
94
|
@stats.bump(:pod_cache_api_nil_bad_resp_payload)
|
92
|
-
log.trace("returning empty metadata for #{namespace_name}/#{pod_name} due to error
|
95
|
+
log.trace("returning empty metadata for #{namespace_name}/#{pod_name} due to error") if log.trace?
|
93
96
|
end
|
94
97
|
end
|
95
|
-
rescue
|
98
|
+
rescue KubeException=>e
|
96
99
|
@stats.bump(:pod_cache_api_nil_error)
|
97
|
-
log.debug "Exception
|
100
|
+
log.debug "Exception encountered fetching pod metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}: #{e.message}"
|
98
101
|
end
|
99
102
|
{}
|
100
103
|
end
|
@@ -126,17 +129,17 @@ module Fluent
|
|
126
129
|
metadata = parse_namespace_metadata(metadata)
|
127
130
|
@stats.bump(:namespace_cache_api_updates)
|
128
131
|
log.trace("parsed metadata for #{namespace_name}: #{metadata}") if log.trace?
|
129
|
-
|
132
|
+
@namespace_cache[metadata['namespace_id']] = metadata
|
130
133
|
return metadata
|
131
134
|
rescue Exception => e
|
132
135
|
log.debug(e)
|
133
136
|
@stats.bump(:namespace_cache_api_nil_bad_resp_payload)
|
134
|
-
log.trace("returning empty metadata for #{namespace_name} due to error
|
137
|
+
log.trace("returning empty metadata for #{namespace_name} due to error") if log.trace?
|
135
138
|
end
|
136
139
|
end
|
137
|
-
rescue
|
140
|
+
rescue KubeException => kube_error
|
138
141
|
@stats.bump(:namespace_cache_api_nil_error)
|
139
|
-
log.debug "Exception
|
142
|
+
log.debug "Exception encountered fetching namespace metadata from Kubernetes API #{@apiVersion} endpoint #{@kubernetes_url}: #{kube_error.message}"
|
140
143
|
end
|
141
144
|
{}
|
142
145
|
end
|
@@ -154,6 +157,7 @@ module Fluent
|
|
154
157
|
end
|
155
158
|
|
156
159
|
require 'kubeclient'
|
160
|
+
require 'active_support/core_ext/object/blank'
|
157
161
|
require 'lru_redux'
|
158
162
|
@stats = KubernetesMetadata::Stats.new
|
159
163
|
|
@@ -180,23 +184,29 @@ module Fluent
|
|
180
184
|
|
181
185
|
# Use Kubernetes default service account if we're in a pod.
|
182
186
|
if @kubernetes_url.nil?
|
187
|
+
log.debug "Kubernetes URL is not set - inspecting environ"
|
188
|
+
|
183
189
|
env_host = ENV['KUBERNETES_SERVICE_HOST']
|
184
190
|
env_port = ENV['KUBERNETES_SERVICE_PORT']
|
185
191
|
if env_host.present? && env_port.present?
|
186
192
|
@kubernetes_url = "https://#{env_host}:#{env_port}/api"
|
193
|
+
log.debug "Kubernetes URL is now '#{@kubernetes_url}'"
|
187
194
|
end
|
188
195
|
end
|
189
196
|
|
190
197
|
# Use SSL certificate and bearer token from Kubernetes service account.
|
191
198
|
if Dir.exist?(@secret_dir)
|
199
|
+
log.debug "Found directory with secrets: #{@secret_dir}"
|
192
200
|
ca_cert = File.join(@secret_dir, K8_POD_CA_CERT)
|
193
201
|
pod_token = File.join(@secret_dir, K8_POD_TOKEN)
|
194
202
|
|
195
203
|
if !@ca_file.present? and File.exist?(ca_cert)
|
204
|
+
log.debug "Found CA certificate: #{ca_cert}"
|
196
205
|
@ca_file = ca_cert
|
197
206
|
end
|
198
207
|
|
199
208
|
if !@bearer_token_file.present? and File.exist?(pod_token)
|
209
|
+
log.debug "Found pod token: #{pod_token}"
|
200
210
|
@bearer_token_file = pod_token
|
201
211
|
end
|
202
212
|
end
|
@@ -217,6 +227,7 @@ module Fluent
|
|
217
227
|
auth_options[:bearer_token] = bearer_token
|
218
228
|
end
|
219
229
|
|
230
|
+
log.debug "Creating K8S client"
|
220
231
|
@client = Kubeclient::Client.new @kubernetes_url, @apiVersion,
|
221
232
|
ssl_options: ssl_options,
|
222
233
|
auth_options: auth_options
|
@@ -234,10 +245,15 @@ module Fluent
|
|
234
245
|
namespace_thread.abort_on_exception = true
|
235
246
|
end
|
236
247
|
end
|
237
|
-
@
|
238
|
-
|
239
|
-
|
240
|
-
|
248
|
+
if @use_journal
|
249
|
+
log.debug "Will stream from the journal"
|
250
|
+
@merge_json_log_key = 'MESSAGE'
|
251
|
+
self.class.class_eval { alias_method :filter_stream, :filter_stream_from_journal }
|
252
|
+
else
|
253
|
+
log.debug "Will stream from the files"
|
254
|
+
@merge_json_log_key = 'log'
|
255
|
+
self.class.class_eval { alias_method :filter_stream, :filter_stream_from_files }
|
256
|
+
end
|
241
257
|
|
242
258
|
@annotations_regexps = []
|
243
259
|
@annotation_match.each do |regexp|
|
@@ -250,93 +266,114 @@ module Fluent
|
|
250
266
|
|
251
267
|
end
|
252
268
|
|
253
|
-
def get_metadata_for_record(
|
269
|
+
def get_metadata_for_record(match_data, cache_key, create_time, batch_miss_cache)
|
270
|
+
namespace_name = match_data['namespace']
|
271
|
+
pod_name = match_data['pod_name']
|
254
272
|
metadata = {
|
255
|
-
'
|
256
|
-
'
|
257
|
-
|
258
|
-
'namespace_name' => namespace_name,
|
259
|
-
'pod_name' => pod_name
|
260
|
-
}
|
273
|
+
'container_name' => match_data['container_name'],
|
274
|
+
'namespace_name' => namespace_name,
|
275
|
+
'pod_name' => pod_name
|
261
276
|
}
|
262
277
|
if @kubernetes_url.present?
|
263
|
-
pod_metadata = get_pod_metadata(
|
278
|
+
pod_metadata = get_pod_metadata(cache_key, namespace_name, pod_name, create_time, batch_miss_cache)
|
279
|
+
metadata.merge!(pod_metadata) if pod_metadata
|
280
|
+
end
|
281
|
+
metadata
|
282
|
+
end
|
264
283
|
|
265
|
-
|
266
|
-
|
267
|
-
|
284
|
+
def create_time_from_record(record)
|
285
|
+
time = if @use_journal
|
286
|
+
record['_SOURCE_REALTIME_TIMESTAMP'].nil? ? record['_SOURCE_REALTIME_TIMESTAMP'] : record['__REALTIME_TIMESTAMP']
|
287
|
+
else
|
288
|
+
record['time']
|
268
289
|
end
|
290
|
+
(time.nil? || time.chop.empty?) ? Time.now : Time.parse(time)
|
291
|
+
end
|
269
292
|
|
270
|
-
|
271
|
-
|
272
|
-
end
|
273
|
-
metadata
|
293
|
+
def filter_stream(tag, es)
|
294
|
+
es
|
274
295
|
end
|
275
296
|
|
276
|
-
def
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
297
|
+
def filter_stream_from_files(tag, es)
|
298
|
+
new_es = Fluent::MultiEventStream.new
|
299
|
+
|
300
|
+
match_data = tag.match(@tag_to_kubernetes_name_regexp_compiled)
|
301
|
+
batch_miss_cache = {}
|
302
|
+
if match_data
|
303
|
+
container_id = match_data['docker_id']
|
304
|
+
metadata = {
|
305
|
+
'docker' => {
|
306
|
+
'container_id' => container_id
|
307
|
+
},
|
308
|
+
'kubernetes' => get_metadata_for_record(match_data, container_id, create_time_from_record(es.first[1]), batch_miss_cache)
|
309
|
+
}
|
285
310
|
end
|
286
|
-
|
311
|
+
|
312
|
+
es.each { |time, record|
|
313
|
+
record = merge_json_log(record) if @merge_json_log
|
314
|
+
|
315
|
+
record = record.merge(Marshal.load(Marshal.dump(metadata))) if metadata
|
316
|
+
|
317
|
+
new_es.add(time, record)
|
318
|
+
}
|
319
|
+
dump_stats
|
320
|
+
new_es
|
287
321
|
end
|
288
322
|
|
289
|
-
def
|
290
|
-
return es if (es.respond_to?(:empty?) && es.empty?) || !es.is_a?(Fluent::EventStream)
|
323
|
+
def filter_stream_from_journal(tag, es)
|
291
324
|
new_es = Fluent::MultiEventStream.new
|
292
|
-
tag_match_data = tag.match(@tag_to_kubernetes_name_regexp_compiled) unless @use_journal
|
293
|
-
tag_metadata = nil
|
294
325
|
batch_miss_cache = {}
|
295
|
-
es.each
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
326
|
+
es.each { |time, record|
|
327
|
+
record = merge_json_log(record) if @merge_json_log
|
328
|
+
metadata = nil
|
329
|
+
if record.has_key?('CONTAINER_NAME') && record.has_key?('CONTAINER_ID_FULL')
|
330
|
+
metadata = record['CONTAINER_NAME'].match(@container_name_to_kubernetes_regexp_compiled) do |match_data|
|
331
|
+
container_id = record['CONTAINER_ID_FULL']
|
332
|
+
metadata = {
|
333
|
+
'docker' => {
|
334
|
+
'container_id' => container_id
|
335
|
+
},
|
336
|
+
'kubernetes' => get_metadata_for_record(match_data, container_id, create_time_from_record(record), batch_miss_cache)
|
337
|
+
}
|
338
|
+
|
339
|
+
metadata
|
340
|
+
end
|
341
|
+
unless metadata
|
342
|
+
log.debug "Error: could not match CONTAINER_NAME from record #{record}"
|
343
|
+
@stats.bump(:container_name_match_failed)
|
344
|
+
end
|
345
|
+
elsif record.has_key?('CONTAINER_NAME') && record['CONTAINER_NAME'].start_with?('k8s_')
|
346
|
+
log.debug "Error: no container name and id in record #{record}"
|
347
|
+
@stats.bump(:container_name_id_missing)
|
304
348
|
end
|
305
|
-
|
306
|
-
|
307
|
-
record
|
308
|
-
record['kubernetes'].has_key?('pod_name') &&
|
309
|
-
record['kubernetes'].has_key?('container_name') &&
|
310
|
-
record['docker'].has_key?('container_id') &&
|
311
|
-
(k_metadata = get_metadata_for_record(record['kubernetes']['namespace_name'], record['kubernetes']['pod_name'],
|
312
|
-
record['kubernetes']['container_name'], record['docker']['container_id'],
|
313
|
-
create_time_from_record(record, time), batch_miss_cache))
|
314
|
-
metadata = k_metadata
|
349
|
+
|
350
|
+
if metadata
|
351
|
+
record = record.merge(metadata)
|
315
352
|
end
|
316
353
|
|
317
|
-
record = record.merge(metadata) if metadata
|
318
354
|
new_es.add(time, record)
|
319
|
-
|
355
|
+
}
|
356
|
+
|
320
357
|
dump_stats
|
321
358
|
new_es
|
322
359
|
end
|
323
360
|
|
324
|
-
def
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
record
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
361
|
+
def merge_json_log(record)
|
362
|
+
if record.has_key?(@merge_json_log_key)
|
363
|
+
value = record[@merge_json_log_key].strip
|
364
|
+
if value[0].eql?('{') && value[-1].eql?('}')
|
365
|
+
begin
|
366
|
+
record = JSON.parse(value).merge(record)
|
367
|
+
unless @preserve_json_log
|
368
|
+
record.delete(@merge_json_log_key)
|
369
|
+
end
|
370
|
+
rescue JSON::ParserError=>e
|
371
|
+
@stats.bump(:merge_json_parse_errors)
|
372
|
+
log.debug(e)
|
373
|
+
end
|
334
374
|
end
|
335
|
-
elsif record.has_key?('CONTAINER_NAME') && record['CONTAINER_NAME'].start_with?('k8s_')
|
336
|
-
log.debug "Error: no container name and id in record #{record}"
|
337
|
-
@stats.bump(:container_name_id_missing)
|
338
375
|
end
|
339
|
-
|
376
|
+
record
|
340
377
|
end
|
341
378
|
|
342
379
|
def de_dot!(h)
|