fluent-plugin-google-cloud 0.6.6 → 0.6.7.pre.1
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 +4 -4
- data/fluent-plugin-google-cloud.gemspec +1 -1
- data/lib/fluent/plugin/out_google_cloud.rb +330 -236
- data/test/plugin/base_test.rb +407 -46
- data/test/plugin/constants.rb +152 -13
- data/test/plugin/test_out_google_cloud.rb +2 -0
- metadata +4 -4
data/test/plugin/base_test.rb
CHANGED
@@ -256,10 +256,10 @@ module BaseTest
|
|
256
256
|
'some_null_field' => nil)
|
257
257
|
d.run
|
258
258
|
end
|
259
|
-
verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload') do |entry|
|
259
|
+
verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload') do |entry, i|
|
260
260
|
fields = get_fields(entry['jsonPayload'])
|
261
261
|
assert_equal 4, fields.size, entry
|
262
|
-
|
262
|
+
verify_default_log_entry_text(get_string(fields['msg']), i, entry)
|
263
263
|
assert_equal 'test', get_string(fields['tag2']), entry
|
264
264
|
assert_equal 5000, get_number(fields['data']), entry
|
265
265
|
assert_equal null_value, fields['some_null_field'], entry
|
@@ -302,42 +302,143 @@ module BaseTest
|
|
302
302
|
end
|
303
303
|
end
|
304
304
|
|
305
|
-
def
|
305
|
+
def test_structured_payload_json_log_default_not_parsed_text
|
306
306
|
setup_gce_metadata_stubs
|
307
|
+
json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
|
308
|
+
'"data": 5000, "some_null_field": null}'
|
307
309
|
setup_logging_stubs do
|
308
|
-
d = create_driver
|
309
|
-
json_string = '{"msg": "test log entry 0", "tag2": "test", "data": 5000}'
|
310
|
+
d = create_driver(APPLICATION_DEFAULT_CONFIG)
|
310
311
|
d.emit('message' => 'notJSON ' + json_string)
|
311
312
|
d.emit('message' => json_string)
|
312
|
-
d.emit('message' => "\t" + json_string)
|
313
|
-
d.
|
313
|
+
d.emit('message' => " \r\n \t" + json_string)
|
314
|
+
d.run
|
315
|
+
end
|
316
|
+
verify_log_entries(3, COMPUTE_PARAMS, 'textPayload') do
|
317
|
+
# Only check for the existence of textPayload.
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
def test_structured_payload_json_log_default_not_parsed_json
|
322
|
+
setup_gce_metadata_stubs
|
323
|
+
json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
|
324
|
+
'"data": 5000, "some_null_field": null}'
|
325
|
+
setup_logging_stubs do
|
326
|
+
d = create_driver(APPLICATION_DEFAULT_CONFIG)
|
327
|
+
%w(log msg).each do |field|
|
328
|
+
d.emit(field => 'notJSON ' + json_string)
|
329
|
+
d.emit(field => json_string)
|
330
|
+
d.emit(field => " \r\n \t" + json_string)
|
331
|
+
end
|
332
|
+
d.run
|
333
|
+
end
|
334
|
+
verify_log_entries(6, COMPUTE_PARAMS, 'jsonPayload') do |entry|
|
335
|
+
fields = get_fields(entry['jsonPayload'])
|
336
|
+
assert !fields.key?('tag2'), 'Did not expect tag2'
|
337
|
+
assert !fields.key?('data'), 'Did not expect data'
|
338
|
+
assert !fields.key?('some_null_field'), 'Did not expect some_null_field'
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
def test_structured_payload_json_log_detect_json_not_parsed_text
|
343
|
+
setup_gce_metadata_stubs
|
344
|
+
json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
|
345
|
+
'"data": 5000, "some_null_field": null}'
|
346
|
+
setup_logging_stubs do
|
347
|
+
d = create_driver(DETECT_JSON_CONFIG)
|
348
|
+
d.emit('message' => 'notJSON ' + json_string)
|
314
349
|
d.run
|
315
350
|
end
|
316
|
-
verify_log_entries(
|
317
|
-
|
351
|
+
verify_log_entries(1, COMPUTE_PARAMS, 'textPayload') do
|
352
|
+
# Only check for the existence of textPayload.
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def test_structured_payload_json_log_detect_json_not_parsed_json
|
357
|
+
setup_gce_metadata_stubs
|
358
|
+
json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
|
359
|
+
'"data": 5000, "some_null_field": null}'
|
360
|
+
setup_logging_stubs do
|
361
|
+
d = create_driver(DETECT_JSON_CONFIG)
|
362
|
+
%w(log msg).each do |field|
|
363
|
+
d.emit(field => 'notJSON ' + json_string)
|
364
|
+
end
|
365
|
+
d.run
|
366
|
+
end
|
367
|
+
verify_log_entries(2, COMPUTE_PARAMS, 'jsonPayload') do |entry|
|
368
|
+
fields = get_fields(entry['jsonPayload'])
|
369
|
+
assert !fields.key?('tag2'), 'Did not expect tag2'
|
370
|
+
assert !fields.key?('data'), 'Did not expect data'
|
371
|
+
assert !fields.key?('some_null_field'), 'Did not expect some_null_field'
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
def test_structured_payload_json_log_detect_json_parsed
|
376
|
+
setup_gce_metadata_stubs
|
377
|
+
json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
|
378
|
+
'"data": 5000, "some_null_field": null}'
|
379
|
+
setup_logging_stubs do
|
380
|
+
d = create_driver(DETECT_JSON_CONFIG)
|
381
|
+
%w(message log msg).each do |field|
|
382
|
+
d.emit(field => json_string)
|
383
|
+
d.emit(field => " \r\n \t" + json_string)
|
384
|
+
end
|
385
|
+
d.run
|
386
|
+
end
|
387
|
+
verify_log_entries(6, COMPUTE_PARAMS, 'jsonPayload') do |entry|
|
388
|
+
fields = get_fields(entry['jsonPayload'])
|
389
|
+
assert_equal 4, fields.size, entry
|
390
|
+
assert_equal 'test log entry 0', get_string(fields['msg']), entry
|
391
|
+
assert_equal 'test', get_string(fields['tag2']), entry
|
392
|
+
assert_equal 5000, get_number(fields['data']), entry
|
393
|
+
assert_equal null_value, fields['some_null_field'], entry
|
318
394
|
end
|
319
395
|
end
|
320
396
|
|
321
|
-
def
|
397
|
+
def test_structured_payload_json_log_default_container_not_parsed
|
322
398
|
setup_gce_metadata_stubs
|
323
399
|
setup_container_metadata_stubs
|
400
|
+
json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
|
401
|
+
'"data": 5000, "some_null_field": null}'
|
324
402
|
setup_logging_stubs do
|
325
403
|
d = create_driver(APPLICATION_DEFAULT_CONFIG, CONTAINER_TAG)
|
326
|
-
json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
|
327
|
-
'"data": 5000, "some_null_field": null}'
|
328
404
|
d.emit(container_log_entry_with_metadata('notJSON' + json_string))
|
329
405
|
d.emit(container_log_entry_with_metadata(json_string))
|
330
406
|
d.emit(container_log_entry_with_metadata(" \r\n \t" + json_string))
|
331
407
|
d.run
|
332
408
|
end
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
409
|
+
verify_log_entries(3, CONTAINER_FROM_METADATA_PARAMS, 'textPayload') do
|
410
|
+
# Only check for the existence of textPayload.
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
def test_structured_payload_json_log_detect_json_container_not_parsed
|
415
|
+
setup_gce_metadata_stubs
|
416
|
+
setup_container_metadata_stubs
|
417
|
+
json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
|
418
|
+
'"data": 5000, "some_null_field": null}'
|
419
|
+
setup_logging_stubs do
|
420
|
+
d = create_driver(DETECT_JSON_CONFIG, CONTAINER_TAG)
|
421
|
+
d.emit(container_log_entry_with_metadata('notJSON' + json_string))
|
422
|
+
d.run
|
423
|
+
end
|
424
|
+
verify_log_entries(1, CONTAINER_FROM_METADATA_PARAMS, 'textPayload') do
|
425
|
+
# Only check for the existence of textPayload.
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
def test_structured_payload_json_log_detect_json_container_parsed
|
430
|
+
setup_gce_metadata_stubs
|
431
|
+
setup_container_metadata_stubs
|
432
|
+
json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
|
433
|
+
'"data": 5000, "some_null_field": null}'
|
434
|
+
setup_logging_stubs do
|
435
|
+
d = create_driver(DETECT_JSON_CONFIG, CONTAINER_TAG)
|
436
|
+
d.emit(container_log_entry_with_metadata(json_string))
|
437
|
+
d.emit(container_log_entry_with_metadata(" \r\n \t" + json_string))
|
438
|
+
d.run
|
439
|
+
end
|
440
|
+
verify_log_entries(2, CONTAINER_FROM_METADATA_PARAMS, 'jsonPayload') \
|
441
|
+
do |entry|
|
341
442
|
fields = get_fields(entry['jsonPayload'])
|
342
443
|
assert_equal 4, fields.size, entry
|
343
444
|
assert_equal 'test log entry 0', get_string(fields['msg']), entry
|
@@ -345,7 +446,6 @@ module BaseTest
|
|
345
446
|
assert_equal 5000, get_number(fields['data']), entry
|
346
447
|
assert_equal null_value, fields['some_null_field'], entry
|
347
448
|
end
|
348
|
-
end
|
349
449
|
end
|
350
450
|
|
351
451
|
# Verify that we drop the log entries when 'require_valid_tags' is true and
|
@@ -403,7 +503,7 @@ module BaseTest
|
|
403
503
|
end
|
404
504
|
params = CONTAINER_FROM_METADATA_PARAMS.merge(
|
405
505
|
labels: CONTAINER_FROM_METADATA_PARAMS[:labels].merge(
|
406
|
-
"#{
|
506
|
+
"#{GKE_CONSTANTS[:service]}/container_name" =>
|
407
507
|
URI.decode(encoded_name)),
|
408
508
|
log_name: encoded_name)
|
409
509
|
verify_log_entries(0, params, 'textPayload')
|
@@ -525,7 +625,8 @@ module BaseTest
|
|
525
625
|
end
|
526
626
|
end
|
527
627
|
verify_index = 0
|
528
|
-
verify_log_entries(emit_index, COMPUTE_PARAMS) do |entry|
|
628
|
+
verify_log_entries(emit_index, COMPUTE_PARAMS) do |entry, i|
|
629
|
+
verify_default_log_entry_text(entry['textPayload'], i, entry)
|
529
630
|
assert_equal_with_default entry['timestamp']['seconds'],
|
530
631
|
expected_ts[verify_index].tv_sec, 0, entry
|
531
632
|
assert_equal_with_default entry['timestamp']['nanos'],
|
@@ -643,10 +744,10 @@ module BaseTest
|
|
643
744
|
params[:labels]['sent_label_1'] = 'value1'
|
644
745
|
params[:labels]['foo.googleapis.com/bar'] = 'value2'
|
645
746
|
params[:labels]['label3'] = 'value3'
|
646
|
-
verify_log_entries(1, params, 'jsonPayload') do |entry|
|
747
|
+
verify_log_entries(1, params, 'jsonPayload') do |entry, i|
|
647
748
|
fields = get_fields(entry['jsonPayload'])
|
648
749
|
assert_equal 2, fields.size, entry
|
649
|
-
|
750
|
+
verify_default_log_entry_text(get_string(fields['message']), i, entry)
|
650
751
|
assert_equal 'value4', get_string(fields['not_a_label']), entry
|
651
752
|
end
|
652
753
|
end
|
@@ -729,9 +830,10 @@ module BaseTest
|
|
729
830
|
d.run
|
730
831
|
end
|
731
832
|
expected_params = CONTAINER_FROM_TAG_PARAMS.merge(
|
732
|
-
labels: { "#{
|
833
|
+
labels: { "#{GKE_CONSTANTS[:service]}/stream" => 'stderr' }
|
733
834
|
) { |_, oldval, newval| oldval.merge(newval) }
|
734
|
-
verify_log_entries(1, expected_params) do |entry|
|
835
|
+
verify_log_entries(1, expected_params) do |entry, i|
|
836
|
+
verify_default_log_entry_text(entry['textPayload'], i, entry)
|
735
837
|
assert_equal CONTAINER_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
|
736
838
|
assert_equal CONTAINER_NANOS, entry['timestamp']['nanos'], entry
|
737
839
|
assert_equal 'ERROR', entry['severity'], entry
|
@@ -742,7 +844,7 @@ module BaseTest
|
|
742
844
|
setup_gce_metadata_stubs
|
743
845
|
setup_container_metadata_stubs
|
744
846
|
setup_logging_stubs do
|
745
|
-
d = create_driver(
|
847
|
+
d = create_driver(DETECT_JSON_CONFIG, CONTAINER_TAG)
|
746
848
|
d.emit(container_log_entry_with_metadata('{"msg": "test log entry 0", ' \
|
747
849
|
'"tag2": "test", "data": ' \
|
748
850
|
'5000, "severity": "WARNING"}'))
|
@@ -765,7 +867,7 @@ module BaseTest
|
|
765
867
|
setup_gce_metadata_stubs
|
766
868
|
setup_container_metadata_stubs
|
767
869
|
setup_logging_stubs do
|
768
|
-
d = create_driver(
|
870
|
+
d = create_driver(DETECT_JSON_CONFIG, CONTAINER_TAG)
|
769
871
|
d.emit(container_log_entry('{"msg": "test log entry 0", ' \
|
770
872
|
'"tag2": "test", "data": 5000, ' \
|
771
873
|
'"severity": "W"}'))
|
@@ -797,7 +899,8 @@ module BaseTest
|
|
797
899
|
n.times { |i| d.emit(cloudfunctions_log_entry(i)) }
|
798
900
|
d.run
|
799
901
|
end
|
800
|
-
verify_log_entries(n, CLOUDFUNCTIONS_PARAMS) do |entry|
|
902
|
+
verify_log_entries(n, CLOUDFUNCTIONS_PARAMS) do |entry, i|
|
903
|
+
verify_default_log_entry_text(entry['textPayload'], i, entry)
|
801
904
|
assert_equal 'DEBUG', entry['severity'],
|
802
905
|
"Test with #{n} logs failed. \n#{entry}"
|
803
906
|
end
|
@@ -838,13 +941,12 @@ module BaseTest
|
|
838
941
|
n.times { |i| d.emit(cloudfunctions_log_entry(i)) }
|
839
942
|
d.run
|
840
943
|
end
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
end
|
944
|
+
verify_log_entries(n, CONTAINER_FROM_TAG_PARAMS, 'textPayload') \
|
945
|
+
do |entry, i|
|
946
|
+
assert_equal '[D][2015-09-25T12:34:56.789Z][123-0] test log entry ' \
|
947
|
+
"#{i}", entry['textPayload'],
|
948
|
+
"Test with #{n} logs failed. \n#{entry}"
|
949
|
+
end
|
848
950
|
end
|
849
951
|
end
|
850
952
|
|
@@ -1004,6 +1106,197 @@ module BaseTest
|
|
1004
1106
|
end
|
1005
1107
|
end
|
1006
1108
|
|
1109
|
+
# Metadata Agent related tests.
|
1110
|
+
|
1111
|
+
# Test enable_metadata_agent not set or set to false.
|
1112
|
+
def test_configure_enable_metadata_agent_default_and_false
|
1113
|
+
setup_gce_metadata_stubs
|
1114
|
+
[create_driver, create_driver(DISABLE_METADATA_AGENT_CONFIG)].each do |d|
|
1115
|
+
assert_false d.instance.instance_variable_get(:@enable_metadata_agent)
|
1116
|
+
end
|
1117
|
+
end
|
1118
|
+
|
1119
|
+
# Test enable_metadata_agent set to true.
|
1120
|
+
def test_configure_enable_metadata_agent_true
|
1121
|
+
new_stub_context do
|
1122
|
+
setup_gce_metadata_stubs
|
1123
|
+
setup_metadata_agent_stubs
|
1124
|
+
d = create_driver(ENABLE_METADATA_AGENT_CONFIG)
|
1125
|
+
assert_true d.instance.instance_variable_get(:@enable_metadata_agent)
|
1126
|
+
assert_requested_metadata_agent_stub(IMPLICIT_LOCAL_RESOURCE_ID)
|
1127
|
+
end
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
# Test that an implicit monitored resource can be retrieved from Metadata
|
1131
|
+
# Agent with an empty string as the local_resource_id.
|
1132
|
+
def test_retrieve_implicit_monitored_resource
|
1133
|
+
# GCE metadata stubs has VM_ID and ZONE, while the Metadata Agent stub has
|
1134
|
+
# METADATA_VM_ID and METADATA_ZONE.
|
1135
|
+
new_stub_context do
|
1136
|
+
setup_gce_metadata_stubs
|
1137
|
+
setup_metadata_agent_stubs
|
1138
|
+
setup_logging_stubs do
|
1139
|
+
d = create_driver(ENABLE_METADATA_AGENT_CONFIG)
|
1140
|
+
d.emit('message' => log_entry(0))
|
1141
|
+
d.run
|
1142
|
+
end
|
1143
|
+
verify_log_entries(1, COMPUTE_PARAMS_WITH_METADATA_VM_ID_AND_ZONE)
|
1144
|
+
assert_requested_metadata_agent_stub(IMPLICIT_LOCAL_RESOURCE_ID)
|
1145
|
+
end
|
1146
|
+
end
|
1147
|
+
|
1148
|
+
# Docker Container.
|
1149
|
+
|
1150
|
+
# Test textPayload logs from Docker container stdout / stderr.
|
1151
|
+
def test_docker_container_stdout_stderr_logs_text_payload
|
1152
|
+
[1, 2, 3, 5, 11, 50].each do |n|
|
1153
|
+
new_stub_context do
|
1154
|
+
setup_gce_metadata_stubs
|
1155
|
+
setup_metadata_agent_stubs
|
1156
|
+
setup_logging_stubs do
|
1157
|
+
d = create_driver(DOCKER_CONTAINER_CONFIG)
|
1158
|
+
n.times do |i|
|
1159
|
+
d.emit(docker_container_stdout_stderr_log_entry(log_entry(i)))
|
1160
|
+
end
|
1161
|
+
d.run
|
1162
|
+
end
|
1163
|
+
verify_log_entries(n, DOCKER_CONTAINER_PARAMS)
|
1164
|
+
assert_requested_metadata_agent_stub(IMPLICIT_LOCAL_RESOURCE_ID)
|
1165
|
+
assert_requested_metadata_agent_stub("container.#{DOCKER_CONTAINER_ID}")
|
1166
|
+
end
|
1167
|
+
end
|
1168
|
+
end
|
1169
|
+
|
1170
|
+
# Test jsonPayload logs from Docker container stdout / stderr.
|
1171
|
+
def test_docker_container_stdout_stderr_logs_json_payload
|
1172
|
+
[1, 2, 3, 5, 11, 50].each do |n|
|
1173
|
+
new_stub_context do
|
1174
|
+
setup_gce_metadata_stubs
|
1175
|
+
setup_metadata_agent_stubs
|
1176
|
+
setup_logging_stubs do
|
1177
|
+
d = create_driver(DOCKER_CONTAINER_CONFIG)
|
1178
|
+
n.times do
|
1179
|
+
d.emit(docker_container_stdout_stderr_log_entry(
|
1180
|
+
'{"msg": "test log entry ' \
|
1181
|
+
"#{n}" \
|
1182
|
+
'", "tag2": "test", "data": ' \
|
1183
|
+
'5000, "severity": "WARNING"}'))
|
1184
|
+
end
|
1185
|
+
d.run
|
1186
|
+
end
|
1187
|
+
verify_log_entries(n, DOCKER_CONTAINER_PARAMS, 'jsonPayload') do |entry|
|
1188
|
+
fields = get_fields(entry['jsonPayload'])
|
1189
|
+
assert_equal 3, fields.size, entry
|
1190
|
+
assert_equal "test log entry #{n}", get_string(fields['msg']), entry
|
1191
|
+
assert_equal 'test', get_string(fields['tag2']), entry
|
1192
|
+
assert_equal 5000, get_number(fields['data']), entry
|
1193
|
+
end
|
1194
|
+
assert_requested_metadata_agent_stub(IMPLICIT_LOCAL_RESOURCE_ID)
|
1195
|
+
assert_requested_metadata_agent_stub("container.#{DOCKER_CONTAINER_ID}")
|
1196
|
+
end
|
1197
|
+
end
|
1198
|
+
end
|
1199
|
+
|
1200
|
+
# Test logs from applications running in Docker containers. These logs have
|
1201
|
+
# the label "logging.googleapis.com/local_resource_id" set in the format of
|
1202
|
+
# "containerName.<container_name>".
|
1203
|
+
def test_docker_container_application_logs
|
1204
|
+
new_stub_context do
|
1205
|
+
setup_gce_metadata_stubs
|
1206
|
+
setup_metadata_agent_stubs
|
1207
|
+
setup_logging_stubs do
|
1208
|
+
# Metadata Agent is not enabled. Will call Docker Remote API for
|
1209
|
+
# container info.
|
1210
|
+
d = create_driver(ENABLE_METADATA_AGENT_CONFIG)
|
1211
|
+
d.emit(docker_container_application_log_entry(log_entry(0)))
|
1212
|
+
d.run
|
1213
|
+
end
|
1214
|
+
verify_log_entries(1, DOCKER_CONTAINER_PARAMS_WITH_NO_STREAM)
|
1215
|
+
assert_requested_metadata_agent_stub(IMPLICIT_LOCAL_RESOURCE_ID)
|
1216
|
+
assert_requested_metadata_agent_stub(
|
1217
|
+
"containerName.#{DOCKER_CONTAINER_NAME}")
|
1218
|
+
end
|
1219
|
+
end
|
1220
|
+
|
1221
|
+
# Test that the 'time' field from the json record is extracted and set to
|
1222
|
+
# entry.timestamp for Docker container logs.
|
1223
|
+
def test_time_field_extraction_for_docker_container_logs
|
1224
|
+
new_stub_context do
|
1225
|
+
setup_gce_metadata_stubs
|
1226
|
+
setup_metadata_agent_stubs
|
1227
|
+
setup_logging_stubs do
|
1228
|
+
d = create_driver(ENABLE_METADATA_AGENT_CONFIG)
|
1229
|
+
d.emit(docker_container_application_log_entry(log_entry(0)))
|
1230
|
+
d.run
|
1231
|
+
end
|
1232
|
+
verify_log_entries(1, DOCKER_CONTAINER_PARAMS_WITH_NO_STREAM) do |entry|
|
1233
|
+
# Timestamp in 'time' field from log entry should be set properly.
|
1234
|
+
assert_equal DOCKER_CONTAINER_SECONDS_EPOCH,
|
1235
|
+
entry['timestamp']['seconds'], entry
|
1236
|
+
assert_equal DOCKER_CONTAINER_NANOS,
|
1237
|
+
entry['timestamp']['nanos'], entry
|
1238
|
+
end
|
1239
|
+
assert_requested_metadata_agent_stub(IMPLICIT_LOCAL_RESOURCE_ID)
|
1240
|
+
assert_requested_metadata_agent_stub(
|
1241
|
+
"containerName.#{DOCKER_CONTAINER_NAME}")
|
1242
|
+
end
|
1243
|
+
end
|
1244
|
+
|
1245
|
+
# Test that the 'source' field is properly extracted from the record json and
|
1246
|
+
# set as a common label 'stream'. Also entry.severity is set accordingly for
|
1247
|
+
# Docker container logs.
|
1248
|
+
def test_source_and_severity_for_docker_container_logs
|
1249
|
+
{
|
1250
|
+
docker_container_stdout_stderr_log_entry(
|
1251
|
+
log_entry(0), DOCKER_CONTAINER_STREAM_STDOUT) =>
|
1252
|
+
DOCKER_CONTAINER_PARAMS,
|
1253
|
+
docker_container_stdout_stderr_log_entry(
|
1254
|
+
log_entry(0), DOCKER_CONTAINER_STREAM_STDERR) =>
|
1255
|
+
DOCKER_CONTAINER_PARAMS_WITH_STREAM_STDERR,
|
1256
|
+
docker_container_application_log_entry(log_entry(0)) =>
|
1257
|
+
DOCKER_CONTAINER_PARAMS_WITH_NO_STREAM,
|
1258
|
+
docker_container_application_log_entry(log_entry(0)) \
|
1259
|
+
.merge('severity' => 'warning') =>
|
1260
|
+
DOCKER_CONTAINER_PARAMS_WITH_NO_STREAM
|
1261
|
+
}.each do |log_entry, expected_params|
|
1262
|
+
new_stub_context do
|
1263
|
+
setup_gce_metadata_stubs
|
1264
|
+
setup_metadata_agent_stubs
|
1265
|
+
setup_logging_stubs do
|
1266
|
+
d = create_driver(DOCKER_CONTAINER_CONFIG)
|
1267
|
+
d.emit(log_entry)
|
1268
|
+
d.run
|
1269
|
+
end
|
1270
|
+
verify_log_entries(1, expected_params)
|
1271
|
+
end
|
1272
|
+
end
|
1273
|
+
end
|
1274
|
+
|
1275
|
+
# Test GKE container logs. These logs have the label
|
1276
|
+
# "logging.googleapis.com/local_resource_id" set in the format of
|
1277
|
+
# "gke_containerName.<namespace_id>.<pod_name>.<container_name>".
|
1278
|
+
def test_gke_container_logs
|
1279
|
+
[1, 2, 3, 5, 11, 50].each do |n|
|
1280
|
+
new_stub_context do
|
1281
|
+
setup_gce_metadata_stubs
|
1282
|
+
setup_container_metadata_stubs
|
1283
|
+
setup_metadata_agent_stubs
|
1284
|
+
setup_logging_stubs do
|
1285
|
+
d = create_driver(ENABLE_METADATA_AGENT_CONFIG)
|
1286
|
+
n.times do |i|
|
1287
|
+
d.emit(gke_container_log_entry(log_entry(i)))
|
1288
|
+
end
|
1289
|
+
d.run
|
1290
|
+
end
|
1291
|
+
verify_log_entries(n, CONTAINER_FROM_APPLICATION_PARAMS)
|
1292
|
+
assert_requested_metadata_agent_stub(IMPLICIT_LOCAL_RESOURCE_ID)
|
1293
|
+
assert_requested_metadata_agent_stub(
|
1294
|
+
"gke_containerName.#{CONTAINER_NAMESPACE_ID}.#{CONTAINER_POD_NAME}." \
|
1295
|
+
"#{CONTAINER_CONTAINER_NAME}")
|
1296
|
+
end
|
1297
|
+
end
|
1298
|
+
end
|
1299
|
+
|
1007
1300
|
private
|
1008
1301
|
|
1009
1302
|
def stub_metadata_request(metadata_path, response_body)
|
@@ -1119,6 +1412,33 @@ module BaseTest
|
|
1119
1412
|
Prometheus::Client.registry.instance_variable_set('@metrics', {})
|
1120
1413
|
end
|
1121
1414
|
|
1415
|
+
# Metadata Agent.
|
1416
|
+
|
1417
|
+
def metadata_request_url(local_resource_id)
|
1418
|
+
"#{DEFAULT_METADATA_AGENT_URL}/monitoredResource/#{local_resource_id}"
|
1419
|
+
end
|
1420
|
+
|
1421
|
+
# Provide a stub context that initializes @logs_sent, executes the block and
|
1422
|
+
# resets WebMock at the end.
|
1423
|
+
def new_stub_context
|
1424
|
+
@logs_sent = []
|
1425
|
+
yield
|
1426
|
+
WebMock.reset!
|
1427
|
+
end
|
1428
|
+
|
1429
|
+
def setup_metadata_agent_stubs
|
1430
|
+
MONITORED_RESOURCE_STUBS.each do |local_resource_id, resource|
|
1431
|
+
stub_request(:get, metadata_request_url(local_resource_id))
|
1432
|
+
.to_return(status: 200, body: resource)
|
1433
|
+
end
|
1434
|
+
end
|
1435
|
+
|
1436
|
+
def assert_requested_metadata_agent_stub(local_resource_id)
|
1437
|
+
assert_requested :get, metadata_request_url(local_resource_id)
|
1438
|
+
end
|
1439
|
+
|
1440
|
+
# GKE Container.
|
1441
|
+
|
1122
1442
|
def container_tag_with_container_name(container_name)
|
1123
1443
|
"kubernetes.#{CONTAINER_POD_NAME}_#{CONTAINER_NAMESPACE_NAME}_" \
|
1124
1444
|
"#{container_name}"
|
@@ -1151,6 +1471,40 @@ module BaseTest
|
|
1151
1471
|
}
|
1152
1472
|
end
|
1153
1473
|
|
1474
|
+
def gke_container_log_entry(log)
|
1475
|
+
{
|
1476
|
+
log: log,
|
1477
|
+
LOCAL_RESOURCE_ID_KEY =>
|
1478
|
+
"gke_containerName.#{CONTAINER_NAMESPACE_ID}" \
|
1479
|
+
".#{CONTAINER_POD_NAME}.#{CONTAINER_CONTAINER_NAME}"
|
1480
|
+
}
|
1481
|
+
end
|
1482
|
+
|
1483
|
+
# Docker Container.
|
1484
|
+
|
1485
|
+
def docker_container_stdout_stderr_log_entry(
|
1486
|
+
log, stream = DOCKER_CONTAINER_STREAM_STDOUT)
|
1487
|
+
severity = if stream == DOCKER_CONTAINER_STREAM_STDOUT
|
1488
|
+
'INFO'
|
1489
|
+
else
|
1490
|
+
'ERROR'
|
1491
|
+
end
|
1492
|
+
{
|
1493
|
+
log: log,
|
1494
|
+
source: stream,
|
1495
|
+
severity: severity,
|
1496
|
+
LOCAL_RESOURCE_ID_KEY => "container.#{DOCKER_CONTAINER_ID}"
|
1497
|
+
}
|
1498
|
+
end
|
1499
|
+
|
1500
|
+
def docker_container_application_log_entry(log)
|
1501
|
+
{
|
1502
|
+
log: log,
|
1503
|
+
time: DOCKER_CONTAINER_TIMESTAMP,
|
1504
|
+
LOCAL_RESOURCE_ID_KEY => "containerName.#{DOCKER_CONTAINER_NAME}"
|
1505
|
+
}
|
1506
|
+
end
|
1507
|
+
|
1154
1508
|
def cloudfunctions_log_entry(i)
|
1155
1509
|
{
|
1156
1510
|
stream: 'stdout',
|
@@ -1189,7 +1543,7 @@ module BaseTest
|
|
1189
1543
|
end
|
1190
1544
|
|
1191
1545
|
def log_entry(i)
|
1192
|
-
|
1546
|
+
"test log entry #{i}"
|
1193
1547
|
end
|
1194
1548
|
|
1195
1549
|
def check_labels(labels, expected_labels)
|
@@ -1205,18 +1559,19 @@ module BaseTest
|
|
1205
1559
|
"#{labels.length} labels: #{labels}"
|
1206
1560
|
end
|
1207
1561
|
|
1562
|
+
def verify_default_log_entry_text(text, i, entry)
|
1563
|
+
assert_equal "test log entry #{i}", text,
|
1564
|
+
"Entry ##{i} had unexpected text: #{entry}"
|
1565
|
+
end
|
1566
|
+
|
1208
1567
|
# The caller can optionally provide a block which is called for each entry.
|
1209
1568
|
def verify_json_log_entries(n, params, payload_type = 'textPayload')
|
1210
1569
|
i = 0
|
1211
1570
|
@logs_sent.each do |request|
|
1212
1571
|
request['entries'].each do |entry|
|
1213
1572
|
unless payload_type.empty?
|
1214
|
-
assert entry.key?(payload_type),
|
1215
|
-
"#{payload_type} key: "
|
1216
|
-
# Check the payload for textPayload, otherwise it's up to the caller.
|
1217
|
-
if payload_type == 'textPayload'
|
1218
|
-
assert_equal "test log entry #{i}", entry['textPayload'], request
|
1219
|
-
end
|
1573
|
+
assert entry.key?(payload_type), "Entry ##{i} did not contain " \
|
1574
|
+
"expected #{payload_type} key: #{entry}"
|
1220
1575
|
end
|
1221
1576
|
|
1222
1577
|
# per-entry resource or log_name overrides the corresponding field
|
@@ -1233,7 +1588,12 @@ module BaseTest
|
|
1233
1588
|
assert_equal params[:resource][:type], resource['type']
|
1234
1589
|
check_labels resource['labels'], params[:resource][:labels]
|
1235
1590
|
check_labels labels, params[:labels]
|
1236
|
-
|
1591
|
+
if block_given?
|
1592
|
+
yield(entry, i)
|
1593
|
+
elsif payload_type == 'textPayload'
|
1594
|
+
# Check the payload for textPayload, otherwise it's up to the caller.
|
1595
|
+
verify_default_log_entry_text(entry['textPayload'], i, entry)
|
1596
|
+
end
|
1237
1597
|
i += 1
|
1238
1598
|
assert i <= n, "Number of entries #{i} exceeds expected number #{n}"
|
1239
1599
|
end
|
@@ -1251,7 +1611,8 @@ module BaseTest
|
|
1251
1611
|
n.times { |i| d.emit(log_entry_factory.call(log_entry(i))) }
|
1252
1612
|
d.run
|
1253
1613
|
end
|
1254
|
-
verify_log_entries(n, expected_params) do |entry|
|
1614
|
+
verify_log_entries(n, expected_params) do |entry, i|
|
1615
|
+
verify_default_log_entry_text(entry['textPayload'], i, entry)
|
1255
1616
|
assert_equal CONTAINER_SECONDS_EPOCH, entry['timestamp']['seconds'],
|
1256
1617
|
entry
|
1257
1618
|
assert_equal CONTAINER_NANOS, entry['timestamp']['nanos'], entry
|