fluent-plugin-vadimberezniker-gcp 0.1.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 +7 -0
- data/CONTRIBUTING +24 -0
- data/Gemfile +3 -0
- data/LICENSE +201 -0
- data/README.rdoc +53 -0
- data/Rakefile +43 -0
- data/fluent-plugin-google-cloud.gemspec +43 -0
- data/fluent-plugin-vadimberezniker-gcp-0.13.2.gem +0 -0
- data/lib/fluent/plugin/common.rb +399 -0
- data/lib/fluent/plugin/filter_add_insert_ids.rb +86 -0
- data/lib/fluent/plugin/filter_analyze_config.rb +410 -0
- data/lib/fluent/plugin/in_object_space_dump.rb +62 -0
- data/lib/fluent/plugin/monitoring.rb +265 -0
- data/lib/fluent/plugin/out_google_cloud.rb +2209 -0
- data/lib/fluent/plugin/statusz.rb +124 -0
- data/test/helper.rb +46 -0
- data/test/plugin/asserts.rb +87 -0
- data/test/plugin/base_test.rb +2680 -0
- data/test/plugin/constants.rb +1114 -0
- data/test/plugin/data/c31e573fd7f62ed495c9ca3821a5a85cb036dee1-privatekey.p12 +0 -0
- data/test/plugin/data/credentials.json +7 -0
- data/test/plugin/data/google-fluentd-baseline.conf +24 -0
- data/test/plugin/data/google-fluentd-custom.conf +40 -0
- data/test/plugin/data/iam-credentials.json +11 -0
- data/test/plugin/data/invalid_credentials.json +8 -0
- data/test/plugin/data/new-style-credentials.json +12 -0
- data/test/plugin/test_driver.rb +56 -0
- data/test/plugin/test_filter_add_insert_ids.rb +137 -0
- data/test/plugin/test_filter_analyze_config.rb +257 -0
- data/test/plugin/test_out_google_cloud.rb +465 -0
- data/test/plugin/test_out_google_cloud_grpc.rb +478 -0
- data/test/plugin/utils.rb +148 -0
- metadata +347 -0
@@ -0,0 +1,465 @@
|
|
1
|
+
# Copyright 2014 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 'fluent/test/startup_shutdown'
|
16
|
+
require 'net/http'
|
17
|
+
|
18
|
+
require_relative 'base_test'
|
19
|
+
require_relative 'test_driver'
|
20
|
+
|
21
|
+
# Unit tests for Google Cloud Logging plugin
|
22
|
+
class GoogleCloudOutputTest < Test::Unit::TestCase
|
23
|
+
include BaseTest
|
24
|
+
extend Fluent::Test::StartupShutdown
|
25
|
+
|
26
|
+
def test_configure_use_grpc
|
27
|
+
setup_gce_metadata_stubs
|
28
|
+
d = create_driver
|
29
|
+
assert_false d.instance.instance_variable_get(:@use_grpc)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_user_agent
|
33
|
+
setup_gce_metadata_stubs
|
34
|
+
user_agent = nil
|
35
|
+
stub_request(:post, WRITE_LOG_ENTRIES_URI).to_return do |request|
|
36
|
+
user_agent = request.headers['User-Agent']
|
37
|
+
{ body: '' }
|
38
|
+
end
|
39
|
+
d = create_driver
|
40
|
+
d.emit('message' => log_entry(0))
|
41
|
+
d.run
|
42
|
+
assert_match Regexp.new("#{Fluent::GoogleCloudOutput::PLUGIN_NAME}/" \
|
43
|
+
"#{Fluent::GoogleCloudOutput::PLUGIN_VERSION}"), \
|
44
|
+
user_agent
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_client_status400
|
48
|
+
setup_gce_metadata_stubs
|
49
|
+
# The API Client should not retry this and the plugin should consume
|
50
|
+
# the exception.
|
51
|
+
stub_request(:post, WRITE_LOG_ENTRIES_URI)
|
52
|
+
.to_return(status: 400, body: 'Bad Request')
|
53
|
+
d = create_driver
|
54
|
+
d.emit('message' => log_entry(0))
|
55
|
+
d.run
|
56
|
+
assert_requested(:post, WRITE_LOG_ENTRIES_URI, times: 1)
|
57
|
+
end
|
58
|
+
|
59
|
+
# All credentials errors resolve to a 401.
|
60
|
+
def test_client_status401
|
61
|
+
setup_gce_metadata_stubs
|
62
|
+
stub_request(:post, WRITE_LOG_ENTRIES_URI)
|
63
|
+
.to_return(status: 401, body: 'Unauthorized')
|
64
|
+
d = create_driver
|
65
|
+
d.emit('message' => log_entry(0))
|
66
|
+
begin
|
67
|
+
d.run
|
68
|
+
rescue Google::Apis::AuthorizationError => e
|
69
|
+
assert_equal 'Unauthorized', e.message
|
70
|
+
end
|
71
|
+
assert_requested(:post, WRITE_LOG_ENTRIES_URI, times: 2)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_partial_success
|
75
|
+
setup_gce_metadata_stubs
|
76
|
+
clear_metrics
|
77
|
+
# The API Client should not retry this and the plugin should consume
|
78
|
+
# the exception.
|
79
|
+
root_error_code = PARTIAL_SUCCESS_RESPONSE_BODY['error']['code']
|
80
|
+
stub_request(:post, WRITE_LOG_ENTRIES_URI)
|
81
|
+
.to_return(status: root_error_code,
|
82
|
+
body: PARTIAL_SUCCESS_RESPONSE_BODY.to_json)
|
83
|
+
d = create_driver(ENABLE_PROMETHEUS_CONFIG)
|
84
|
+
4.times do |i|
|
85
|
+
d.emit('message' => log_entry(i.to_s))
|
86
|
+
end
|
87
|
+
d.run
|
88
|
+
assert_prometheus_metric_value(
|
89
|
+
:stackdriver_successful_requests_count, 1,
|
90
|
+
'agent.googleapis.com/agent', OpenCensus::Stats::Aggregation::Sum, d,
|
91
|
+
grpc: false, code: 200
|
92
|
+
)
|
93
|
+
assert_prometheus_metric_value(
|
94
|
+
:stackdriver_ingested_entries_count, 1,
|
95
|
+
'agent.googleapis.com/agent', OpenCensus::Stats::Aggregation::Sum, d,
|
96
|
+
grpc: false, code: 200
|
97
|
+
)
|
98
|
+
assert_prometheus_metric_value(
|
99
|
+
:stackdriver_dropped_entries_count, 2,
|
100
|
+
'agent.googleapis.com/agent', OpenCensus::Stats::Aggregation::Sum, d,
|
101
|
+
grpc: false, code: 3
|
102
|
+
)
|
103
|
+
assert_prometheus_metric_value(
|
104
|
+
:stackdriver_dropped_entries_count, 1,
|
105
|
+
'agent.googleapis.com/agent', OpenCensus::Stats::Aggregation::Sum, d,
|
106
|
+
grpc: false, code: 7
|
107
|
+
)
|
108
|
+
assert_requested(:post, WRITE_LOG_ENTRIES_URI, times: 1)
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_non_api_error
|
112
|
+
setup_gce_metadata_stubs
|
113
|
+
clear_metrics
|
114
|
+
# The API Client should not retry this and the plugin should consume
|
115
|
+
# the exception.
|
116
|
+
root_error_code = PARSE_ERROR_RESPONSE_BODY['error']['code']
|
117
|
+
stub_request(:post, WRITE_LOG_ENTRIES_URI)
|
118
|
+
.to_return(status: root_error_code,
|
119
|
+
body: PARSE_ERROR_RESPONSE_BODY.to_json)
|
120
|
+
d = create_driver(ENABLE_PROMETHEUS_CONFIG)
|
121
|
+
d.emit('message' => log_entry(0))
|
122
|
+
d.run
|
123
|
+
assert_prometheus_metric_value(
|
124
|
+
:stackdriver_successful_requests_count, 0,
|
125
|
+
'agent.googleapis.com/agent', OpenCensus::Stats::Aggregation::Sum, d,
|
126
|
+
grpc: false, code: 200
|
127
|
+
)
|
128
|
+
assert_prometheus_metric_value(
|
129
|
+
:stackdriver_failed_requests_count, 1,
|
130
|
+
'agent.googleapis.com/agent', OpenCensus::Stats::Aggregation::Sum, d,
|
131
|
+
grpc: false, code: 400
|
132
|
+
)
|
133
|
+
assert_prometheus_metric_value(
|
134
|
+
:stackdriver_ingested_entries_count, 0,
|
135
|
+
'agent.googleapis.com/agent', OpenCensus::Stats::Aggregation::Sum, d,
|
136
|
+
grpc: false, code: 200
|
137
|
+
)
|
138
|
+
assert_prometheus_metric_value(
|
139
|
+
:stackdriver_dropped_entries_count, 1,
|
140
|
+
'agent.googleapis.com/agent', OpenCensus::Stats::Aggregation::Sum, d,
|
141
|
+
grpc: false, code: 400
|
142
|
+
)
|
143
|
+
assert_requested(:post, WRITE_LOG_ENTRIES_URI, times: 1)
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_server_error
|
147
|
+
setup_gce_metadata_stubs
|
148
|
+
# The API client should retry this once, then throw an exception which
|
149
|
+
# gets propagated through the plugin.
|
150
|
+
stub_request(:post, WRITE_LOG_ENTRIES_URI)
|
151
|
+
.to_return(status: 500, body: 'Server Error')
|
152
|
+
d = create_driver
|
153
|
+
d.emit('message' => log_entry(0))
|
154
|
+
exception_count = 0
|
155
|
+
begin
|
156
|
+
d.run
|
157
|
+
rescue Google::Apis::ServerError => e
|
158
|
+
assert_equal 'Server error', e.message
|
159
|
+
exception_count += 1
|
160
|
+
end
|
161
|
+
assert_requested(:post, WRITE_LOG_ENTRIES_URI, times: 1)
|
162
|
+
assert_equal 1, exception_count
|
163
|
+
end
|
164
|
+
|
165
|
+
# This test looks similar between the grpc and non-grpc paths except that when
|
166
|
+
# parsing "105", the grpc path responds with "DEBUG", while the non-grpc path
|
167
|
+
# responds with "100".
|
168
|
+
#
|
169
|
+
# TODO(lingshi) consolidate the tests between the grpc path and the non-grpc
|
170
|
+
# path, or at least split into two tests, one with string severities and one
|
171
|
+
# with numeric severities.
|
172
|
+
def test_severities
|
173
|
+
setup_gce_metadata_stubs
|
174
|
+
expected_severity = []
|
175
|
+
emit_index = 0
|
176
|
+
setup_logging_stubs do
|
177
|
+
d = create_driver
|
178
|
+
# Array of pairs of [parsed_severity, expected_severity]
|
179
|
+
[%w[INFO INFO], %w[warn WARNING], %w[E ERROR], %w[BLAH DEFAULT],
|
180
|
+
['105', 100], ['', 'DEFAULT']].each do |sev|
|
181
|
+
d.emit('message' => log_entry(emit_index), 'severity' => sev[0])
|
182
|
+
expected_severity.push(sev[1])
|
183
|
+
emit_index += 1
|
184
|
+
end
|
185
|
+
d.run
|
186
|
+
end
|
187
|
+
verify_index = 0
|
188
|
+
verify_log_entries(emit_index, COMPUTE_PARAMS) do |entry|
|
189
|
+
assert_equal expected_severity[verify_index],
|
190
|
+
entry['severity'], entry
|
191
|
+
verify_index += 1
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_parse_severity
|
196
|
+
test_obj = Fluent::GoogleCloudOutput.new
|
197
|
+
|
198
|
+
# known severities should translate to themselves, regardless of case
|
199
|
+
%w[DEFAULT DEBUG INFO NOTICE WARNING ERROR CRITICAL ALERT EMERGENCY].each \
|
200
|
+
do |severity|
|
201
|
+
assert_equal(severity, test_obj.parse_severity(severity))
|
202
|
+
assert_equal(severity, test_obj.parse_severity(severity.downcase))
|
203
|
+
assert_equal(severity, test_obj.parse_severity(severity.capitalize))
|
204
|
+
end
|
205
|
+
|
206
|
+
# numeric levels
|
207
|
+
assert_equal(0, test_obj.parse_severity('0'))
|
208
|
+
assert_equal(100, test_obj.parse_severity('100'))
|
209
|
+
assert_equal(200, test_obj.parse_severity('200'))
|
210
|
+
assert_equal(300, test_obj.parse_severity('300'))
|
211
|
+
assert_equal(400, test_obj.parse_severity('400'))
|
212
|
+
assert_equal(500, test_obj.parse_severity('500'))
|
213
|
+
assert_equal(600, test_obj.parse_severity('600'))
|
214
|
+
assert_equal(700, test_obj.parse_severity('700'))
|
215
|
+
assert_equal(800, test_obj.parse_severity('800'))
|
216
|
+
|
217
|
+
assert_equal(800, test_obj.parse_severity('900'))
|
218
|
+
assert_equal(0, test_obj.parse_severity('1'))
|
219
|
+
assert_equal(100, test_obj.parse_severity('105'))
|
220
|
+
assert_equal(400, test_obj.parse_severity('420'))
|
221
|
+
assert_equal(700, test_obj.parse_severity('799'))
|
222
|
+
|
223
|
+
assert_equal(100, test_obj.parse_severity('105 '))
|
224
|
+
assert_equal(100, test_obj.parse_severity(' 105'))
|
225
|
+
assert_equal(100, test_obj.parse_severity(' 105 '))
|
226
|
+
|
227
|
+
assert_equal(100, test_obj.parse_severity(100))
|
228
|
+
|
229
|
+
assert_equal('DEFAULT', test_obj.parse_severity('-100'))
|
230
|
+
assert_equal('DEFAULT', test_obj.parse_severity('105 100'))
|
231
|
+
|
232
|
+
# synonyms for existing log levels
|
233
|
+
assert_equal('ERROR', test_obj.parse_severity('ERR'))
|
234
|
+
assert_equal('ERROR', test_obj.parse_severity('SEVERE'))
|
235
|
+
assert_equal('WARNING', test_obj.parse_severity('WARN'))
|
236
|
+
assert_equal('CRITICAL', test_obj.parse_severity('FATAL'))
|
237
|
+
assert_equal('DEBUG', test_obj.parse_severity('TRACE'))
|
238
|
+
assert_equal('DEBUG', test_obj.parse_severity('TRACE_INT'))
|
239
|
+
assert_equal('DEBUG', test_obj.parse_severity('FINE'))
|
240
|
+
assert_equal('DEBUG', test_obj.parse_severity('FINER'))
|
241
|
+
assert_equal('DEBUG', test_obj.parse_severity('FINEST'))
|
242
|
+
assert_equal('DEBUG', test_obj.parse_severity('CONFIG'))
|
243
|
+
|
244
|
+
# single letters.
|
245
|
+
assert_equal('DEBUG', test_obj.parse_severity('D'))
|
246
|
+
assert_equal('INFO', test_obj.parse_severity('I'))
|
247
|
+
assert_equal('NOTICE', test_obj.parse_severity('N'))
|
248
|
+
assert_equal('WARNING', test_obj.parse_severity('W'))
|
249
|
+
assert_equal('ERROR', test_obj.parse_severity('E'))
|
250
|
+
assert_equal('CRITICAL', test_obj.parse_severity('C'))
|
251
|
+
assert_equal('ALERT', test_obj.parse_severity('A'))
|
252
|
+
assert_equal('ERROR', test_obj.parse_severity('e'))
|
253
|
+
|
254
|
+
assert_equal('DEFAULT', test_obj.parse_severity('x'))
|
255
|
+
assert_equal('DEFAULT', test_obj.parse_severity('-'))
|
256
|
+
|
257
|
+
# leading/trailing whitespace should be stripped
|
258
|
+
assert_equal('ERROR', test_obj.parse_severity(' ERROR'))
|
259
|
+
assert_equal('ERROR', test_obj.parse_severity('ERROR '))
|
260
|
+
assert_equal('ERROR', test_obj.parse_severity(' ERROR '))
|
261
|
+
assert_equal('ERROR', test_obj.parse_severity("\t ERROR "))
|
262
|
+
# space in the middle should not be stripped.
|
263
|
+
assert_equal('DEFAULT', test_obj.parse_severity('ER ROR'))
|
264
|
+
|
265
|
+
# anything else should translate to 'DEFAULT'
|
266
|
+
assert_equal('DEFAULT', test_obj.parse_severity(nil))
|
267
|
+
assert_equal('DEFAULT', test_obj.parse_severity(Object.new))
|
268
|
+
assert_equal('DEFAULT', test_obj.parse_severity({}))
|
269
|
+
assert_equal('DEFAULT', test_obj.parse_severity([]))
|
270
|
+
assert_equal('DEFAULT', test_obj.parse_severity(100.0))
|
271
|
+
assert_equal('DEFAULT', test_obj.parse_severity(''))
|
272
|
+
assert_equal('DEFAULT', test_obj.parse_severity('garbage'))
|
273
|
+
assert_equal('DEFAULT', test_obj.parse_severity('er'))
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_non_integer_timestamp
|
277
|
+
setup_gce_metadata_stubs
|
278
|
+
time = Time.now
|
279
|
+
[
|
280
|
+
{ 'seconds' => nil, 'nanos' => nil },
|
281
|
+
{ 'seconds' => nil, 'nanos' => time.tv_nsec },
|
282
|
+
{ 'seconds' => 'seconds', 'nanos' => time.tv_nsec },
|
283
|
+
{ 'seconds' => time.tv_sec, 'nanos' => 'nanos' },
|
284
|
+
{ 'seconds' => time.tv_sec, 'nanos' => nil }
|
285
|
+
].each do |timestamp|
|
286
|
+
setup_logging_stubs do
|
287
|
+
d = create_driver
|
288
|
+
@logs_sent = []
|
289
|
+
d.emit('message' => log_entry(0), 'timestamp' => timestamp)
|
290
|
+
d.run
|
291
|
+
end
|
292
|
+
verify_log_entries(1, COMPUTE_PARAMS) do |entry|
|
293
|
+
assert_equal timestamp, entry['timestamp'], 'Test with timestamp ' \
|
294
|
+
"'#{timestamp}' failed for entry: '#{entry}'."
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_statusz_endpoint
|
300
|
+
setup_gce_metadata_stubs
|
301
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
302
|
+
# TODO(davidbtucker): Consider searching for an unused port
|
303
|
+
# instead of hardcoding a constant here.
|
304
|
+
d = create_driver(CONFIG_STATUSZ)
|
305
|
+
d.run do
|
306
|
+
resp = Net::HTTP.get('127.0.0.1', '/statusz', 5678)
|
307
|
+
must_match = [
|
308
|
+
'<h1>Status for .*</h1>.*',
|
309
|
+
'\bStarted: .*<br>',
|
310
|
+
'\bUp \d+ hr \d{2} min \d{2} sec<br>',
|
311
|
+
|
312
|
+
'\badjust_invalid_timestamps\b.*\bfalse\b',
|
313
|
+
'\bautoformat_stackdriver_trace\b.*\bfalse\b',
|
314
|
+
'\bcoerce_to_utf8\b.*\bfalse\b',
|
315
|
+
'\bdetect_json\b.*\btrue\b',
|
316
|
+
'\bdetect_subservice\b.*\bfalse\b',
|
317
|
+
'\benable_monitoring\b.*\btrue\b',
|
318
|
+
'\bhttp_request_key\b.*\btest_http_request_key\b',
|
319
|
+
'\binsert_id_key\b.*\btest_insert_id_key\b',
|
320
|
+
'\bk8s_cluster_location\b.*\btest-k8s-cluster-location\b',
|
321
|
+
'\bk8s_cluster_name\b.*\btest-k8s-cluster-name\b',
|
322
|
+
'\bkubernetes_tag_regexp\b.*\b.*test-regexp.*\b',
|
323
|
+
'\blabel_map\b.*{"label_map_key"=>"label_map_value"}',
|
324
|
+
'\blabels_key\b.*\btest_labels_key\b',
|
325
|
+
'\blabels\b.*{"labels_key"=>"labels_value"}',
|
326
|
+
'\blogging_api_url\b.*\bhttp://localhost:52000\b',
|
327
|
+
'\bmonitoring_type\b.*\bnot_prometheus\b',
|
328
|
+
'\bnon_utf8_replacement_string\b.*\bzzz\b',
|
329
|
+
'\boperation_key\b.*\btest_operation_key\b',
|
330
|
+
'\bproject_id\b.*\btest-project-id-123\b',
|
331
|
+
'\brequire_valid_tags\b.*\btrue\b',
|
332
|
+
'\bsource_location_key\b.*\btest_source_location_key\b',
|
333
|
+
'\bspan_id_key\b.*\btest_span_id_key\b',
|
334
|
+
'\bsplit_logs_by_tag\b.*\btrue\b',
|
335
|
+
'\bstatusz_port\b.*\b5678\b',
|
336
|
+
'\bsubservice_name\b.*\btest_subservice_name\b',
|
337
|
+
'\btrace_key\b.*\btest_trace_key\b',
|
338
|
+
'\btrace_sampled_key\b.*\btest_trace_sampled_key\b',
|
339
|
+
'\buse_aws_availability_zone\b.*\bfalse\b',
|
340
|
+
'\buse_grpc\b.*\btrue\b',
|
341
|
+
'\buse_metadata_service\b.*\bfalse\b',
|
342
|
+
'\bvm_id\b.*\b12345\b',
|
343
|
+
'\bvm_name\b.*\btest.hostname.org\b',
|
344
|
+
'\bzone\b.*\basia-east2\b',
|
345
|
+
|
346
|
+
'^</html>$'
|
347
|
+
]
|
348
|
+
must_match.each do |re|
|
349
|
+
assert_match Regexp.new(re), resp
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
private
|
355
|
+
|
356
|
+
WRITE_LOG_ENTRIES_URI =
|
357
|
+
'https://logging.googleapis.com/v2/entries:write'.freeze
|
358
|
+
|
359
|
+
def rename_key(hash, old_key, new_key)
|
360
|
+
hash.merge(new_key => hash[old_key]).reject { |k, _| k == old_key }
|
361
|
+
end
|
362
|
+
|
363
|
+
# Set up http stubs to mock the external calls.
|
364
|
+
def setup_logging_stubs(_error = nil, code = nil, message = 'some message')
|
365
|
+
stub_request(:post, WRITE_LOG_ENTRIES_URI).to_return do |request|
|
366
|
+
@logs_sent << JSON.parse(request.body)
|
367
|
+
{ status: code, body: message }
|
368
|
+
end
|
369
|
+
yield
|
370
|
+
end
|
371
|
+
|
372
|
+
# Whether this is the grpc path
|
373
|
+
def use_grpc
|
374
|
+
false
|
375
|
+
end
|
376
|
+
|
377
|
+
# The OK status code for the grpc path.
|
378
|
+
def ok_status_code
|
379
|
+
200
|
380
|
+
end
|
381
|
+
|
382
|
+
# A client side error status code for the grpc path.
|
383
|
+
def client_error_status_code
|
384
|
+
401
|
385
|
+
end
|
386
|
+
|
387
|
+
# A server side error status code for the grpc path.
|
388
|
+
def server_error_status_code
|
389
|
+
500
|
390
|
+
end
|
391
|
+
|
392
|
+
# The parent error type to expect in the mock
|
393
|
+
def mock_error_type
|
394
|
+
Google::Apis::Error
|
395
|
+
end
|
396
|
+
|
397
|
+
# The conversions from user input to output.
|
398
|
+
def latency_conversion
|
399
|
+
{
|
400
|
+
'32 s' => { 'seconds' => 32 },
|
401
|
+
'32s' => { 'seconds' => 32 },
|
402
|
+
'0.32s' => { 'nanos' => 320_000_000 },
|
403
|
+
' 123 s ' => { 'seconds' => 123 },
|
404
|
+
'1.3442 s' => { 'seconds' => 1, 'nanos' => 344_200_000 },
|
405
|
+
|
406
|
+
# Test whitespace.
|
407
|
+
# \t: tab. \r: carriage return. \n: line break.
|
408
|
+
# \v: vertical whitespace. \f: form feed.
|
409
|
+
"\t123.5\ts\t" => { 'seconds' => 123, 'nanos' => 500_000_000 },
|
410
|
+
"\r123.5\rs\r" => { 'seconds' => 123, 'nanos' => 500_000_000 },
|
411
|
+
"\n123.5\ns\n" => { 'seconds' => 123, 'nanos' => 500_000_000 },
|
412
|
+
"\v123.5\vs\v" => { 'seconds' => 123, 'nanos' => 500_000_000 },
|
413
|
+
"\f123.5\fs\f" => { 'seconds' => 123, 'nanos' => 500_000_000 },
|
414
|
+
"\r123.5\ts\f" => { 'seconds' => 123, 'nanos' => 500_000_000 }
|
415
|
+
}
|
416
|
+
end
|
417
|
+
|
418
|
+
# Create a Fluentd output test driver with the Google Cloud Output plugin.
|
419
|
+
def create_driver(conf = APPLICATION_DEFAULT_CONFIG,
|
420
|
+
tag = 'test',
|
421
|
+
multi_tags = false)
|
422
|
+
driver = if multi_tags
|
423
|
+
Fluent::Test::MultiTagBufferedOutputTestDriver.new(
|
424
|
+
Fluent::GoogleCloudOutput
|
425
|
+
)
|
426
|
+
else
|
427
|
+
Fluent::Test::BufferedOutputTestDriver.new(
|
428
|
+
Fluent::GoogleCloudOutput, tag
|
429
|
+
)
|
430
|
+
end
|
431
|
+
driver.configure(conf, true)
|
432
|
+
end
|
433
|
+
|
434
|
+
# Verify the number and the content of the log entries match the expectation.
|
435
|
+
# The caller can optionally provide a block which is called for each entry.
|
436
|
+
def verify_log_entries(expected_count, params, payload_type = 'textPayload',
|
437
|
+
check_exact_entry_labels = true, &block)
|
438
|
+
verify_json_log_entries(expected_count, params, payload_type,
|
439
|
+
check_exact_entry_labels, &block)
|
440
|
+
end
|
441
|
+
|
442
|
+
# For an optional field with default values, Protobuf omits the field when it
|
443
|
+
# is deserialized to json. So we need to add an extra check for gRPC which
|
444
|
+
# uses Protobuf.
|
445
|
+
#
|
446
|
+
# An optional block can be passed in if we need to assert something other than
|
447
|
+
# a plain equal. e.g. assert_in_delta.
|
448
|
+
def assert_equal_with_default(field, expected_value, _default_value, entry)
|
449
|
+
if block_given?
|
450
|
+
yield
|
451
|
+
else
|
452
|
+
assert_equal expected_value, field, entry
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
def expected_operation_message2
|
457
|
+
OPERATION_MESSAGE2
|
458
|
+
end
|
459
|
+
|
460
|
+
# Directly return the timestamp value, which should be a hash two keys:
|
461
|
+
# "seconds" and "nanos".
|
462
|
+
def timestamp_parse(timestamp)
|
463
|
+
timestamp
|
464
|
+
end
|
465
|
+
end
|