fluent-plugin-google-cloud 0.8.5 → 0.8.6
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 +4 -4
- data/Gemfile.lock +5 -5
- data/fluent-plugin-google-cloud.gemspec +1 -1
- data/lib/fluent/plugin/filter_analyze_config.rb +306 -0
- data/lib/fluent/plugin/out_google_cloud.rb +1 -1
- data/test/plugin/asserts.rb +75 -0
- data/test/plugin/base_test.rb +2 -59
- data/test/plugin/constants.rb +8 -0
- data/test/plugin/data/google-fluentd-baseline.conf +24 -0
- data/test/plugin/data/google-fluentd-custom.conf +40 -0
- data/test/plugin/test_filter_analyze_config.rb +187 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44d38e36606e310f5ec6dae2931125f139b1e40c8c2b5eafd45c3497e6aeb1c9
|
4
|
+
data.tar.gz: b2aecc00518d8787a9d3a2fcd2fad880246cf63cfddc3b4967277eb07baa2e5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4b3ead22e4a4ee3bcb20cbd5102f4847be31bf99606e1072b668a75176b452feb5cf84fd6d19297739ca76fba6c261fa33e562faabc07553587510554e8c867
|
7
|
+
data.tar.gz: c5659ca5819695d2799331bb22fe5f05fe39434b7f744e324ad8aa43eeb3b917f5e530868e9c11d2916b896ae2c1f2dee74880a11b0f278da1a0742db3fd6b82
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fluent-plugin-google-cloud (0.8.
|
4
|
+
fluent-plugin-google-cloud (0.8.6)
|
5
5
|
fluentd (= 1.7.4)
|
6
6
|
google-api-client (= 0.30.8)
|
7
7
|
google-cloud-logging (= 1.6.6)
|
@@ -57,9 +57,9 @@ GEM
|
|
57
57
|
google-cloud-core (1.5.0)
|
58
58
|
google-cloud-env (~> 1.0)
|
59
59
|
google-cloud-errors (~> 1.0)
|
60
|
-
google-cloud-env (1.3.
|
60
|
+
google-cloud-env (1.3.2)
|
61
61
|
faraday (>= 0.17.3, < 2.0)
|
62
|
-
google-cloud-errors (1.0.
|
62
|
+
google-cloud-errors (1.0.1)
|
63
63
|
google-cloud-logging (1.6.6)
|
64
64
|
concurrent-ruby (~> 1.1)
|
65
65
|
google-cloud-core (~> 1.2)
|
@@ -117,7 +117,7 @@ GEM
|
|
117
117
|
google-cloud-trace (~> 0.35)
|
118
118
|
opencensus (~> 0.5)
|
119
119
|
os (1.1.0)
|
120
|
-
parser (2.7.1.
|
120
|
+
parser (2.7.1.3)
|
121
121
|
ast (~> 2.4.0)
|
122
122
|
power_assert (1.2.0)
|
123
123
|
powerpack (0.1.2)
|
@@ -164,7 +164,7 @@ GEM
|
|
164
164
|
test-unit (3.3.3)
|
165
165
|
power_assert
|
166
166
|
thor (1.0.1)
|
167
|
-
tins (1.
|
167
|
+
tins (1.25.0)
|
168
168
|
sync
|
169
169
|
tzinfo (2.0.2)
|
170
170
|
concurrent-ruby (~> 1.0)
|
@@ -10,7 +10,7 @@ eos
|
|
10
10
|
gem.homepage =
|
11
11
|
'https://github.com/GoogleCloudPlatform/fluent-plugin-google-cloud'
|
12
12
|
gem.license = 'Apache-2.0'
|
13
|
-
gem.version = '0.8.
|
13
|
+
gem.version = '0.8.6'
|
14
14
|
gem.authors = ['Stackdriver Agents Team']
|
15
15
|
gem.email = ['stackdriver-agents@google.com']
|
16
16
|
gem.required_ruby_version = Gem::Requirement.new('>= 2.2')
|
@@ -0,0 +1,306 @@
|
|
1
|
+
# Copyright 2020 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require 'fileutils'
|
16
|
+
require 'fluent/config'
|
17
|
+
require 'fluent/config/v1_parser'
|
18
|
+
require 'set'
|
19
|
+
|
20
|
+
require_relative 'monitoring'
|
21
|
+
|
22
|
+
module Fluent
|
23
|
+
# Fluentd filter plugin to analyze configuration usage.
|
24
|
+
#
|
25
|
+
# For documentation on inspecting parsed configuration elements, see
|
26
|
+
# https://www.rubydoc.info/github/fluent/fluentd/Fluent/Config/Element
|
27
|
+
class AnalyzeConfigFilter < Filter
|
28
|
+
include Fluent::Config
|
29
|
+
Fluent::Plugin.register_filter('analyze_config', self)
|
30
|
+
|
31
|
+
module Constants
|
32
|
+
# Built-in plugins that are ok to reference in metrics.
|
33
|
+
KNOWN_PLUGINS = {
|
34
|
+
'filter' => Set[
|
35
|
+
'geoip',
|
36
|
+
'grep',
|
37
|
+
'parser',
|
38
|
+
'record_transformer',
|
39
|
+
'stdout',
|
40
|
+
],
|
41
|
+
'match' => Set[
|
42
|
+
'copy',
|
43
|
+
'elasticsearch',
|
44
|
+
'exec',
|
45
|
+
'exec_filter',
|
46
|
+
'file',
|
47
|
+
'forward',
|
48
|
+
'http',
|
49
|
+
'kafka',
|
50
|
+
'mongo',
|
51
|
+
'mongo_replset',
|
52
|
+
'null',
|
53
|
+
'relabel',
|
54
|
+
'rewrite_tag_filter',
|
55
|
+
'roundrobin',
|
56
|
+
's3',
|
57
|
+
'secondary_file',
|
58
|
+
'stdout',
|
59
|
+
'webhdfs',
|
60
|
+
],
|
61
|
+
'source' => Set[
|
62
|
+
'dummy',
|
63
|
+
'exec',
|
64
|
+
'forward',
|
65
|
+
'http',
|
66
|
+
'monitor_agent',
|
67
|
+
'syslog',
|
68
|
+
'tail',
|
69
|
+
'tcp',
|
70
|
+
'udp',
|
71
|
+
'unix',
|
72
|
+
'windows_eventlog',
|
73
|
+
]
|
74
|
+
}.freeze
|
75
|
+
|
76
|
+
# For Google plugins, we collect metrics on the params listed here.
|
77
|
+
GOOGLE_PLUGIN_PARAMS = {
|
78
|
+
'google_cloud' => %w(
|
79
|
+
adjust_invalid_timestamps
|
80
|
+
auth_method
|
81
|
+
autoformat_stackdriver_trace
|
82
|
+
coerce_to_utf8
|
83
|
+
detect_json
|
84
|
+
enable_monitoring
|
85
|
+
gcm_service_address
|
86
|
+
grpc_compression_algorithm
|
87
|
+
http_request_key
|
88
|
+
insert_id_key
|
89
|
+
label_map
|
90
|
+
labels
|
91
|
+
labels_key
|
92
|
+
logging_api_url
|
93
|
+
monitoring_type
|
94
|
+
non_utf8_replacement_string
|
95
|
+
operation_key
|
96
|
+
private_key_email
|
97
|
+
private_key_passphrase
|
98
|
+
private_key_path
|
99
|
+
project_id
|
100
|
+
source_location_key
|
101
|
+
span_id_key
|
102
|
+
statusz_port
|
103
|
+
trace_key
|
104
|
+
trace_sampled_key
|
105
|
+
use_grpc
|
106
|
+
use_metadata_service
|
107
|
+
vm_id
|
108
|
+
vm_name
|
109
|
+
zone
|
110
|
+
),
|
111
|
+
'detect_exceptions' => %w(
|
112
|
+
languages
|
113
|
+
max_bytes
|
114
|
+
max_lines
|
115
|
+
message
|
116
|
+
multiline_flush_interval
|
117
|
+
remove_tag_prefix
|
118
|
+
stream
|
119
|
+
)
|
120
|
+
}.freeze
|
121
|
+
end
|
122
|
+
|
123
|
+
include self::Constants
|
124
|
+
|
125
|
+
# The root configuration file of google-fluentd package.
|
126
|
+
# This only applies to Linux.
|
127
|
+
config_param :google_fluentd_config_path,
|
128
|
+
:string,
|
129
|
+
default: '/etc/google-fluentd/google-fluentd.conf'
|
130
|
+
# Baseline configuration for comparing with local
|
131
|
+
# customizations.
|
132
|
+
config_param :google_fluentd_baseline_config_path,
|
133
|
+
:string,
|
134
|
+
default: '/etc/google-fluentd/baseline/google-fluentd.conf'
|
135
|
+
|
136
|
+
def start
|
137
|
+
super
|
138
|
+
@log = $log # rubocop:disable Style/GlobalVars
|
139
|
+
|
140
|
+
# Initialize the insertID.
|
141
|
+
@log.info 'Started the analyze_config plugin to analyze configuration.'
|
142
|
+
end
|
143
|
+
|
144
|
+
def parse_config(path)
|
145
|
+
data = File.open(path, 'r', &:read)
|
146
|
+
fname = File.basename(path)
|
147
|
+
basepath = File.dirname(path)
|
148
|
+
eval_context = Kernel.binding
|
149
|
+
# Override instance_eval so that LiteralParser does not actually
|
150
|
+
# evaluate the embedded Ruby, but instead just returns the
|
151
|
+
# source string. See
|
152
|
+
# https://github.com/fluent/fluentd/blob/master/lib/fluent/config/literal_parser.rb
|
153
|
+
def eval_context.instance_eval(code)
|
154
|
+
code
|
155
|
+
end
|
156
|
+
Fluent::Config::V1Parser.parse(data, fname, basepath, eval_context)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Returns a name for identifying plugins we ship by default.
|
160
|
+
def default_plugin_name(e)
|
161
|
+
case e['@type']
|
162
|
+
when 'syslog'
|
163
|
+
"#{e.name}/syslog/#{e['protocol_type']}"
|
164
|
+
when 'tail'
|
165
|
+
"#{e.name}/tail/#{File.basename(e['pos_file'], '.pos')}"
|
166
|
+
else
|
167
|
+
"#{e.name}/#{e['@type']}"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Returns a name for identifying plugins not in our default
|
172
|
+
# config. This should not contain arbitrary user-supplied data.
|
173
|
+
def custom_plugin_name(e)
|
174
|
+
if KNOWN_PLUGINS.key?(e.name) &&
|
175
|
+
KNOWN_PLUGINS[e.name].include?(e['@type'])
|
176
|
+
"#{e.name}/#{e['@type']}"
|
177
|
+
else
|
178
|
+
e.name.to_s
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def embedded_ruby?(e)
|
183
|
+
(e.arg.include?('#{') ||
|
184
|
+
e.any? { |_, v| v.include?('#{') } ||
|
185
|
+
e.elements.any? { |ee| embedded_ruby?(ee) })
|
186
|
+
end
|
187
|
+
|
188
|
+
def configure(conf)
|
189
|
+
super
|
190
|
+
if File.file?(@google_fluentd_config_path) &&
|
191
|
+
File.file?(@google_fluentd_baseline_config_path)
|
192
|
+
@log.info(
|
193
|
+
'google-fluentd configuration file found at' \
|
194
|
+
" #{@google_fluentd_config_path}. " \
|
195
|
+
'google-fluentd baseline configuration file found at' \
|
196
|
+
" #{@google_fluentd_baseline_config_path}. " \
|
197
|
+
'google-fluentd Analyzing configuration.')
|
198
|
+
|
199
|
+
# TODO: Add OpenCensus support.
|
200
|
+
registry = Monitoring::MonitoringRegistryFactory.create(
|
201
|
+
Monitoring::PrometheusMonitoringRegistry.name, nil, nil, nil)
|
202
|
+
|
203
|
+
plugin_usage = registry.counter(
|
204
|
+
:stackdriver_enabled_plugins,
|
205
|
+
[:plugin_name, :is_default_plugin, :has_default_value],
|
206
|
+
'Enabled plugins')
|
207
|
+
config_usage = registry.counter(
|
208
|
+
:stackdriver_config_usage,
|
209
|
+
[:plugin_name, :param, :is_present, :has_default_value],
|
210
|
+
'Parameter usage for Google Cloud plugins')
|
211
|
+
config_bool_values = registry.counter(
|
212
|
+
:stackdriver_config_bool_values,
|
213
|
+
[:plugin_name, :param, :value],
|
214
|
+
'Values for bool parameters in Google Cloud plugins')
|
215
|
+
|
216
|
+
config = parse_config(@google_fluentd_config_path)
|
217
|
+
baseline_config = parse_config(@google_fluentd_baseline_config_path)
|
218
|
+
|
219
|
+
# Create hash of all baseline elements by their plugin names.
|
220
|
+
baseline_elements = Hash[baseline_config.elements.collect do |e|
|
221
|
+
[default_plugin_name(e), e]
|
222
|
+
end]
|
223
|
+
baseline_google_element = baseline_config.elements.find do |e|
|
224
|
+
e['@type'] == 'google_cloud'
|
225
|
+
end
|
226
|
+
|
227
|
+
# Look at each top-level config element and see whether it
|
228
|
+
# matches the baseline value.
|
229
|
+
#
|
230
|
+
# Note on custom configurations: If the plugin has a custom
|
231
|
+
# value (e.g. if a tail plugin has pos_file
|
232
|
+
# /var/lib/google-fluentd/pos/my-custom-value.pos), then the
|
233
|
+
# default_plugin_name (e.g. source/tail/my-custom-value) won't
|
234
|
+
# be a key in baseline_elements below, so it won't be
|
235
|
+
# used. Instead it will use the custom_plugin_name
|
236
|
+
# (e.g. source/tail).
|
237
|
+
config.elements.each do |e|
|
238
|
+
plugin_name = default_plugin_name(e)
|
239
|
+
if baseline_elements.key?(plugin_name)
|
240
|
+
is_default_plugin = true
|
241
|
+
has_default_value = (baseline_elements[plugin_name] == e)
|
242
|
+
else
|
243
|
+
plugin_name = custom_plugin_name(e)
|
244
|
+
is_default_plugin = false
|
245
|
+
has_default_value = false
|
246
|
+
end
|
247
|
+
plugin_usage.increment(
|
248
|
+
labels: {
|
249
|
+
plugin_name: plugin_name,
|
250
|
+
is_default_plugin: is_default_plugin,
|
251
|
+
has_default_value: has_default_value,
|
252
|
+
has_ruby_snippet: embedded_ruby?(e)
|
253
|
+
},
|
254
|
+
by: 1)
|
255
|
+
|
256
|
+
# Additional metric for Google plugins (google_cloud and
|
257
|
+
# detect_exceptions).
|
258
|
+
next unless GOOGLE_PLUGIN_PARAMS.key?(e['@type'])
|
259
|
+
GOOGLE_PLUGIN_PARAMS[e['@type']].each do |p|
|
260
|
+
config_usage.increment(
|
261
|
+
labels: {
|
262
|
+
plugin_name: e['@type'],
|
263
|
+
param: p,
|
264
|
+
is_present: e.key?(p),
|
265
|
+
has_default_value: (e.key?(p) &&
|
266
|
+
baseline_google_element.key?(p) &&
|
267
|
+
e[p] == baseline_google_element[p])
|
268
|
+
},
|
269
|
+
by: 1)
|
270
|
+
next unless e.key?(p) && %w(true false).include?(e[p])
|
271
|
+
config_bool_values.increment(
|
272
|
+
labels: {
|
273
|
+
plugin_name: e['@type'],
|
274
|
+
param: p,
|
275
|
+
value: e[p] == 'true'
|
276
|
+
},
|
277
|
+
by: 1)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
else
|
281
|
+
@log.info(
|
282
|
+
'google-fluentd configuration file does not exist at' \
|
283
|
+
" #{@google_fluentd_config_path} or " \
|
284
|
+
'google-fluentd baseline configuration file does not exist at' \
|
285
|
+
" #{@google_fluentd_baseline_config_path} or " \
|
286
|
+
'. Skipping configuration analysis.')
|
287
|
+
end
|
288
|
+
rescue => e
|
289
|
+
# Do not crash the agent due to configuration analysis failures.
|
290
|
+
@log.warn(
|
291
|
+
'Failed to optionally analyze the google-fluentd configuration' \
|
292
|
+
" file. Proceeding anyway. Error: #{e}")
|
293
|
+
end
|
294
|
+
|
295
|
+
def shutdown
|
296
|
+
super
|
297
|
+
end
|
298
|
+
|
299
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
300
|
+
def filter(tag, time, record)
|
301
|
+
# Skip the actual filtering process.
|
302
|
+
record
|
303
|
+
end
|
304
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
305
|
+
end
|
306
|
+
end
|
@@ -103,7 +103,7 @@ module Fluent
|
|
103
103
|
}.freeze
|
104
104
|
GKE_CONSTANTS = {
|
105
105
|
service: 'container.googleapis.com',
|
106
|
-
resource_type: '
|
106
|
+
resource_type: 'gke_container',
|
107
107
|
extra_resource_labels: %w(namespace_id pod_id container_name),
|
108
108
|
extra_common_labels: %w(namespace_name pod_name),
|
109
109
|
metadata_attributes: %w(cluster-name cluster-location),
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# Copyright 2020 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# Additional assert functions.
|
16
|
+
module Asserts
|
17
|
+
# For an optional field with default values, Protobuf omits the field when it
|
18
|
+
# is deserialized to json. So we need to add an extra check for gRPC which
|
19
|
+
# uses Protobuf.
|
20
|
+
#
|
21
|
+
# An optional block can be passed in if we need to assert something other than
|
22
|
+
# a plain equal. e.g. assert_in_delta.
|
23
|
+
def assert_equal_with_default(_field, _expected_value, _default_value, _entry)
|
24
|
+
_undefined
|
25
|
+
end
|
26
|
+
|
27
|
+
# Compare the timestamp seconds and nanoseconds with the expected timestamp.
|
28
|
+
def assert_timestamp_matches(expected_ts, ts_secs, ts_nanos, entry)
|
29
|
+
assert_equal expected_ts.tv_sec, ts_secs, entry
|
30
|
+
# Fluentd v0.14 onwards supports nanosecond timestamp values.
|
31
|
+
# Added in 600 ns delta to avoid flaky tests introduced
|
32
|
+
# due to rounding error in double-precision floating-point numbers
|
33
|
+
# (to account for the missing 9 bits of precision ~ 512 ns).
|
34
|
+
# See http://wikipedia.org/wiki/Double-precision_floating-point_format.
|
35
|
+
assert_in_delta expected_ts.tv_nsec, ts_nanos, 600, entry
|
36
|
+
end
|
37
|
+
|
38
|
+
def assert_prometheus_metric_value(metric_name, expected_value, labels = {})
|
39
|
+
metric = Prometheus::Client.registry.get(metric_name)
|
40
|
+
assert_not_nil(metric)
|
41
|
+
metric_value = if labels == :aggregate
|
42
|
+
# Sum up all metric values regardless of the labels.
|
43
|
+
metric.values.values.reduce(0.0, :+)
|
44
|
+
else
|
45
|
+
metric.get(labels)
|
46
|
+
end
|
47
|
+
assert_equal(expected_value, metric_value)
|
48
|
+
end
|
49
|
+
|
50
|
+
def assert_opencensus_metric_value(metric_name, expected_value, labels = {})
|
51
|
+
translator = Monitoring::MetricTranslator.new(metric_name, labels)
|
52
|
+
metric_name = translator.name
|
53
|
+
labels = translator.translate_labels(labels)
|
54
|
+
# The next line collapses the labels to assert against the aggregated data,
|
55
|
+
# which can have some labels removed. Without this, it would test against
|
56
|
+
# the raw data. The view is more representative of the user experience, even
|
57
|
+
# though both tests should work because currently we only aggregate away one
|
58
|
+
# label that never changes during runtime.
|
59
|
+
labels.select! { |k, _| translator.view_labels.include? k }
|
60
|
+
labels = labels.map { |k, v| [k.to_s, v.to_s] }.to_h
|
61
|
+
stats_recorder = OpenCensus::Stats.ensure_recorder
|
62
|
+
view_data = stats_recorder.view_data metric_name
|
63
|
+
assert_not_nil(view_data)
|
64
|
+
# For now assume all metrics are counters.
|
65
|
+
assert_kind_of(OpenCensus::Stats::Aggregation::Sum,
|
66
|
+
view_data.view.aggregation)
|
67
|
+
assert_true(view_data.view.measure.int64?)
|
68
|
+
tag_values = view_data.view.columns.map { |column| labels[column] }
|
69
|
+
metric_value = 0
|
70
|
+
if view_data.data.key? tag_values
|
71
|
+
metric_value = view_data.data[tag_values].value
|
72
|
+
end
|
73
|
+
assert_equal(expected_value, metric_value)
|
74
|
+
end
|
75
|
+
end
|
data/test/plugin/base_test.rb
CHANGED
@@ -22,6 +22,7 @@ require 'mocha/test_unit'
|
|
22
22
|
require 'webmock/test_unit'
|
23
23
|
require 'prometheus/client'
|
24
24
|
|
25
|
+
require_relative 'asserts'
|
25
26
|
require_relative 'constants'
|
26
27
|
|
27
28
|
module Monitoring
|
@@ -35,6 +36,7 @@ end
|
|
35
36
|
|
36
37
|
# Unit tests for Google Cloud Logging plugin
|
37
38
|
module BaseTest
|
39
|
+
include Asserts
|
38
40
|
include Constants
|
39
41
|
|
40
42
|
def setup
|
@@ -2534,65 +2536,6 @@ module BaseTest
|
|
2534
2536
|
_undefined
|
2535
2537
|
end
|
2536
2538
|
|
2537
|
-
# For an optional field with default values, Protobuf omits the field when it
|
2538
|
-
# is deserialized to json. So we need to add an extra check for gRPC which
|
2539
|
-
# uses Protobuf.
|
2540
|
-
#
|
2541
|
-
# An optional block can be passed in if we need to assert something other than
|
2542
|
-
# a plain equal. e.g. assert_in_delta.
|
2543
|
-
def assert_equal_with_default(_field, _expected_value, _default_value, _entry)
|
2544
|
-
_undefined
|
2545
|
-
end
|
2546
|
-
|
2547
|
-
# Compare the timestamp seconds and nanoseconds with the expected timestamp.
|
2548
|
-
def assert_timestamp_matches(expected_ts, ts_secs, ts_nanos, entry)
|
2549
|
-
assert_equal expected_ts.tv_sec, ts_secs, entry
|
2550
|
-
# Fluentd v0.14 onwards supports nanosecond timestamp values.
|
2551
|
-
# Added in 600 ns delta to avoid flaky tests introduced
|
2552
|
-
# due to rounding error in double-precision floating-point numbers
|
2553
|
-
# (to account for the missing 9 bits of precision ~ 512 ns).
|
2554
|
-
# See http://wikipedia.org/wiki/Double-precision_floating-point_format.
|
2555
|
-
assert_in_delta expected_ts.tv_nsec, ts_nanos, 600, entry
|
2556
|
-
end
|
2557
|
-
|
2558
|
-
def assert_prometheus_metric_value(metric_name, expected_value, labels = {})
|
2559
|
-
metric = Prometheus::Client.registry.get(metric_name)
|
2560
|
-
assert_not_nil(metric)
|
2561
|
-
metric_value = if labels == :aggregate
|
2562
|
-
# Sum up all metric values regardless of the labels.
|
2563
|
-
metric.values.values.reduce(0.0, :+)
|
2564
|
-
else
|
2565
|
-
metric.get(labels)
|
2566
|
-
end
|
2567
|
-
assert_equal(expected_value, metric_value)
|
2568
|
-
end
|
2569
|
-
|
2570
|
-
def assert_opencensus_metric_value(metric_name, expected_value, labels = {})
|
2571
|
-
translator = Monitoring::MetricTranslator.new(metric_name, labels)
|
2572
|
-
metric_name = translator.name
|
2573
|
-
labels = translator.translate_labels(labels)
|
2574
|
-
# The next line collapses the labels to assert against the aggregated data,
|
2575
|
-
# which can have some labels removed. Without this, it would test against
|
2576
|
-
# the raw data. The view is more representative of the user experience, even
|
2577
|
-
# though both tests should work because currently we only aggregate away one
|
2578
|
-
# label that never changes during runtime.
|
2579
|
-
labels.select! { |k, _| translator.view_labels.include? k }
|
2580
|
-
labels = labels.map { |k, v| [k.to_s, v.to_s] }.to_h
|
2581
|
-
stats_recorder = OpenCensus::Stats.ensure_recorder
|
2582
|
-
view_data = stats_recorder.view_data metric_name
|
2583
|
-
assert_not_nil(view_data)
|
2584
|
-
# For now assume all metrics are counters.
|
2585
|
-
assert_kind_of(OpenCensus::Stats::Aggregation::Sum,
|
2586
|
-
view_data.view.aggregation)
|
2587
|
-
assert_true(view_data.view.measure.int64?)
|
2588
|
-
tag_values = view_data.view.columns.map { |column| labels[column] }
|
2589
|
-
metric_value = 0
|
2590
|
-
if view_data.data.key? tag_values
|
2591
|
-
metric_value = view_data.data[tag_values].value
|
2592
|
-
end
|
2593
|
-
assert_equal(expected_value, metric_value)
|
2594
|
-
end
|
2595
|
-
|
2596
2539
|
# Defined in specific gRPC or REST files.
|
2597
2540
|
def expected_operation_message2
|
2598
2541
|
_undefined
|
data/test/plugin/constants.rb
CHANGED
@@ -471,6 +471,14 @@ module Constants
|
|
471
471
|
zone asia-east2
|
472
472
|
).freeze
|
473
473
|
|
474
|
+
# For analyze_config.
|
475
|
+
CONFIG_ANALYZE_CONFIG = %(
|
476
|
+
google_fluentd_config_path \
|
477
|
+
test/plugin/data/google-fluentd-custom.conf
|
478
|
+
google_fluentd_baseline_config_path \
|
479
|
+
test/plugin/data/google-fluentd-baseline.conf
|
480
|
+
).freeze
|
481
|
+
|
474
482
|
# Service configurations for various services.
|
475
483
|
|
476
484
|
# GCE.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<source>
|
2
|
+
@type syslog
|
3
|
+
port 514
|
4
|
+
protocol_type tcp
|
5
|
+
bind 127.0.0.1
|
6
|
+
tag syslog
|
7
|
+
</source>
|
8
|
+
|
9
|
+
<source>
|
10
|
+
@type tail
|
11
|
+
path /var/log/apache*/access.log,/var/log/apache*/access_log,/var/log/httpd/access.log,/var/log/httpd/access_log
|
12
|
+
pos_file /var/lib/google-fluentd/pos/apache-access.pos
|
13
|
+
tag apache-access
|
14
|
+
</source>
|
15
|
+
|
16
|
+
<filter **>
|
17
|
+
@type add_insert_ids
|
18
|
+
</filter>
|
19
|
+
|
20
|
+
<match **>
|
21
|
+
@type google_cloud
|
22
|
+
adjust_invalid_timestamps true
|
23
|
+
autoformat_stackdriver_trace true
|
24
|
+
</match>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<source>
|
2
|
+
@type syslog
|
3
|
+
port 514
|
4
|
+
protocol_type tcp
|
5
|
+
bind 127.0.0.1
|
6
|
+
tag syslog
|
7
|
+
</source>
|
8
|
+
|
9
|
+
<source>
|
10
|
+
@type tail
|
11
|
+
path /var/log/apache*/access.log,/var/log/apache*/access_log,/var/log/httpd/access.log,/var/log/httpd/access_log
|
12
|
+
pos_file /var/lib/google-fluentd/pos/apache-access.pos
|
13
|
+
tag apache-access
|
14
|
+
</source>
|
15
|
+
|
16
|
+
<filter **>
|
17
|
+
@type add_insert_ids
|
18
|
+
</filter>
|
19
|
+
|
20
|
+
<match **>
|
21
|
+
@type google_cloud
|
22
|
+
adjust_invalid_timestamps true
|
23
|
+
autoformat_stackdriver_trace false
|
24
|
+
coerce_to_utf8 true
|
25
|
+
</match>
|
26
|
+
|
27
|
+
<filter **>
|
28
|
+
@type some_custom_filter
|
29
|
+
</filter>
|
30
|
+
|
31
|
+
<filter **>
|
32
|
+
@type record_transformer
|
33
|
+
<record>
|
34
|
+
host_param "#{Socket.gethostname}"
|
35
|
+
</record>
|
36
|
+
</filter>
|
37
|
+
|
38
|
+
<match "app.#{ENV['FLUENTD_TAG']}">
|
39
|
+
@type stdout
|
40
|
+
</match>
|
@@ -0,0 +1,187 @@
|
|
1
|
+
# Copyright 2020 Google Inc. All rights reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require_relative '../helper'
|
16
|
+
require_relative 'asserts'
|
17
|
+
require_relative 'constants'
|
18
|
+
|
19
|
+
require 'fluent/test/driver/filter'
|
20
|
+
require 'fluent/plugin/filter_analyze_config'
|
21
|
+
|
22
|
+
# Unit tests for filter_analyze_config plugin.
|
23
|
+
class FilterAnalyzeConfigTest < Test::Unit::TestCase
|
24
|
+
include Asserts
|
25
|
+
include Constants
|
26
|
+
include Fluent::AnalyzeConfigFilter::Constants
|
27
|
+
|
28
|
+
APPLICATION_DEFAULT_CONFIG = ''.freeze
|
29
|
+
|
30
|
+
def setup
|
31
|
+
Fluent::Test.setup
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_config_file_does_not_exist
|
35
|
+
# By default, the FilterTestDriver.new does not set up a config file at:
|
36
|
+
# /etc/google-fluentd/google-fluentd.conf. The plugin should still proceed.
|
37
|
+
create_driver
|
38
|
+
# No exceptions were thrown.
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_analyze_config
|
42
|
+
create_driver(CONFIG_ANALYZE_CONFIG)
|
43
|
+
|
44
|
+
# Default plugins, with default config.
|
45
|
+
assert_prometheus_metric_value(
|
46
|
+
:stackdriver_enabled_plugins,
|
47
|
+
1,
|
48
|
+
plugin_name: 'source/syslog/tcp',
|
49
|
+
is_default_plugin: true,
|
50
|
+
has_default_value: true,
|
51
|
+
has_ruby_snippet: false)
|
52
|
+
assert_prometheus_metric_value(
|
53
|
+
:stackdriver_enabled_plugins,
|
54
|
+
1,
|
55
|
+
plugin_name: 'source/tail/apache-access',
|
56
|
+
is_default_plugin: true,
|
57
|
+
has_default_value: true,
|
58
|
+
has_ruby_snippet: false)
|
59
|
+
assert_prometheus_metric_value(
|
60
|
+
:stackdriver_enabled_plugins,
|
61
|
+
1,
|
62
|
+
plugin_name: 'filter/add_insert_ids',
|
63
|
+
is_default_plugin: true,
|
64
|
+
has_default_value: true,
|
65
|
+
has_ruby_snippet: false)
|
66
|
+
|
67
|
+
# Default plugins, with custom config.
|
68
|
+
assert_prometheus_metric_value(
|
69
|
+
:stackdriver_enabled_plugins,
|
70
|
+
1,
|
71
|
+
plugin_name: 'match/google_cloud',
|
72
|
+
is_default_plugin: true,
|
73
|
+
has_default_value: false,
|
74
|
+
has_ruby_snippet: false)
|
75
|
+
|
76
|
+
# Custom plugins, some with embedded Ruby.
|
77
|
+
assert_prometheus_metric_value(
|
78
|
+
:stackdriver_enabled_plugins,
|
79
|
+
1,
|
80
|
+
plugin_name: 'filter',
|
81
|
+
is_default_plugin: false,
|
82
|
+
has_default_value: false,
|
83
|
+
has_ruby_snippet: false)
|
84
|
+
assert_prometheus_metric_value(
|
85
|
+
:stackdriver_enabled_plugins,
|
86
|
+
1,
|
87
|
+
plugin_name: 'filter/record_transformer',
|
88
|
+
is_default_plugin: false,
|
89
|
+
has_default_value: false,
|
90
|
+
has_ruby_snippet: true)
|
91
|
+
assert_prometheus_metric_value(
|
92
|
+
:stackdriver_enabled_plugins,
|
93
|
+
1,
|
94
|
+
plugin_name: 'match/stdout',
|
95
|
+
is_default_plugin: false,
|
96
|
+
has_default_value: false,
|
97
|
+
has_ruby_snippet: true)
|
98
|
+
|
99
|
+
# For out_google_cloud, 3 params are present.
|
100
|
+
assert_prometheus_metric_value(
|
101
|
+
:stackdriver_config_usage,
|
102
|
+
1,
|
103
|
+
plugin_name: 'google_cloud',
|
104
|
+
param: 'adjust_invalid_timestamps',
|
105
|
+
is_present: true,
|
106
|
+
has_default_value: true)
|
107
|
+
assert_prometheus_metric_value(
|
108
|
+
:stackdriver_config_usage,
|
109
|
+
1,
|
110
|
+
plugin_name: 'google_cloud',
|
111
|
+
param: 'autoformat_stackdriver_trace',
|
112
|
+
is_present: true,
|
113
|
+
has_default_value: false)
|
114
|
+
assert_prometheus_metric_value(
|
115
|
+
:stackdriver_config_usage,
|
116
|
+
1,
|
117
|
+
plugin_name: 'google_cloud',
|
118
|
+
param: 'coerce_to_utf8',
|
119
|
+
is_present: true,
|
120
|
+
has_default_value: false)
|
121
|
+
# The remaining "google_cloud" params are not present.
|
122
|
+
# The are no params for "detect_exceptions".
|
123
|
+
%w(
|
124
|
+
auth_method
|
125
|
+
detect_json
|
126
|
+
enable_monitoring
|
127
|
+
gcm_service_address
|
128
|
+
grpc_compression_algorithm
|
129
|
+
http_request_key
|
130
|
+
insert_id_key
|
131
|
+
label_map
|
132
|
+
labels
|
133
|
+
labels_key
|
134
|
+
logging_api_url
|
135
|
+
monitoring_type
|
136
|
+
non_utf8_replacement_string
|
137
|
+
operation_key
|
138
|
+
private_key_email
|
139
|
+
private_key_passphrase
|
140
|
+
private_key_path
|
141
|
+
project_id
|
142
|
+
source_location_key
|
143
|
+
span_id_key
|
144
|
+
statusz_port
|
145
|
+
trace_key
|
146
|
+
trace_sampled_key
|
147
|
+
use_grpc
|
148
|
+
use_metadata_service
|
149
|
+
vm_id
|
150
|
+
vm_name
|
151
|
+
zone
|
152
|
+
).each do |p|
|
153
|
+
assert_prometheus_metric_value(
|
154
|
+
:stackdriver_config_usage,
|
155
|
+
1,
|
156
|
+
plugin_name: 'google_cloud',
|
157
|
+
param: p,
|
158
|
+
is_present: false,
|
159
|
+
has_default_value: false)
|
160
|
+
end
|
161
|
+
|
162
|
+
# We also export values for the bools.
|
163
|
+
assert_prometheus_metric_value(
|
164
|
+
:stackdriver_config_bool_values,
|
165
|
+
1,
|
166
|
+
plugin_name: 'google_cloud',
|
167
|
+
param: 'adjust_invalid_timestamps',
|
168
|
+
value: true)
|
169
|
+
assert_prometheus_metric_value(
|
170
|
+
:stackdriver_config_bool_values,
|
171
|
+
1,
|
172
|
+
plugin_name: 'google_cloud',
|
173
|
+
param: 'autoformat_stackdriver_trace',
|
174
|
+
value: false)
|
175
|
+
assert_prometheus_metric_value(
|
176
|
+
:stackdriver_config_bool_values,
|
177
|
+
1,
|
178
|
+
plugin_name: 'google_cloud',
|
179
|
+
param: 'coerce_to_utf8',
|
180
|
+
value: true)
|
181
|
+
end
|
182
|
+
|
183
|
+
def create_driver(conf = APPLICATION_DEFAULT_CONFIG)
|
184
|
+
Fluent::Test::FilterTestDriver.new(
|
185
|
+
Fluent::AnalyzeConfigFilter).configure(conf, true)
|
186
|
+
end
|
187
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-google-cloud
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stackdriver Agents Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -267,20 +267,25 @@ files:
|
|
267
267
|
- Rakefile
|
268
268
|
- fluent-plugin-google-cloud.gemspec
|
269
269
|
- lib/fluent/plugin/filter_add_insert_ids.rb
|
270
|
+
- lib/fluent/plugin/filter_analyze_config.rb
|
270
271
|
- lib/fluent/plugin/in_object_space_dump.rb
|
271
272
|
- lib/fluent/plugin/monitoring.rb
|
272
273
|
- lib/fluent/plugin/out_google_cloud.rb
|
273
274
|
- lib/fluent/plugin/statusz.rb
|
274
275
|
- test/helper.rb
|
276
|
+
- test/plugin/asserts.rb
|
275
277
|
- test/plugin/base_test.rb
|
276
278
|
- test/plugin/constants.rb
|
277
279
|
- test/plugin/data/c31e573fd7f62ed495c9ca3821a5a85cb036dee1-privatekey.p12
|
278
280
|
- test/plugin/data/credentials.json
|
281
|
+
- test/plugin/data/google-fluentd-baseline.conf
|
282
|
+
- test/plugin/data/google-fluentd-custom.conf
|
279
283
|
- test/plugin/data/iam-credentials.json
|
280
284
|
- test/plugin/data/invalid_credentials.json
|
281
285
|
- test/plugin/data/new-style-credentials.json
|
282
286
|
- test/plugin/test_driver.rb
|
283
287
|
- test/plugin/test_filter_add_insert_ids.rb
|
288
|
+
- test/plugin/test_filter_analyze_config.rb
|
284
289
|
- test/plugin/test_out_google_cloud.rb
|
285
290
|
- test/plugin/test_out_google_cloud_grpc.rb
|
286
291
|
homepage: https://github.com/GoogleCloudPlatform/fluent-plugin-google-cloud
|
@@ -308,14 +313,18 @@ specification_version: 4
|
|
308
313
|
summary: fluentd plugins for the Stackdriver Logging API
|
309
314
|
test_files:
|
310
315
|
- test/helper.rb
|
316
|
+
- test/plugin/asserts.rb
|
311
317
|
- test/plugin/base_test.rb
|
312
318
|
- test/plugin/constants.rb
|
313
319
|
- test/plugin/data/c31e573fd7f62ed495c9ca3821a5a85cb036dee1-privatekey.p12
|
314
320
|
- test/plugin/data/credentials.json
|
321
|
+
- test/plugin/data/google-fluentd-baseline.conf
|
322
|
+
- test/plugin/data/google-fluentd-custom.conf
|
315
323
|
- test/plugin/data/iam-credentials.json
|
316
324
|
- test/plugin/data/invalid_credentials.json
|
317
325
|
- test/plugin/data/new-style-credentials.json
|
318
326
|
- test/plugin/test_driver.rb
|
319
327
|
- test/plugin/test_filter_add_insert_ids.rb
|
328
|
+
- test/plugin/test_filter_analyze_config.rb
|
320
329
|
- test/plugin/test_out_google_cloud.rb
|
321
330
|
- test/plugin/test_out_google_cloud_grpc.rb
|