fluent-plugin-google-cloud 0.7.4 → 0.7.5.pre.multiworkers
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/fluent-plugin-google-cloud.gemspec +1 -1
- data/lib/fluent/plugin/out_google_cloud.rb +77 -14
- data/test/plugin/base_test.rb +310 -52
- data/test/plugin/constants.rb +123 -0
- data/test/plugin/test_out_google_cloud.rb +4 -2
- data/test/plugin/test_out_google_cloud_grpc.rb +4 -2
- metadata +5 -7
- data/CUSTOM_SPONGE_CONFIG +0 -0
- data/Gemfile.lock +0 -160
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: be98011ce135e9570444d3c55967c316a96a858c
|
4
|
+
data.tar.gz: 88271c68f053f89f462ad8b5ed6b1fb2220e2bdc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 279c39e5dcb334c48894dc970234fe780dfde6bb342f76715988730e72731accade84a6fafdcbc39ddd65087609ac11d274d693047818786034c3219ebcc22cb
|
7
|
+
data.tar.gz: 34e85bc20d7abf886508d1036a00b4ff1296dcea427da2b3870ca858a11e3217a57a397d4d72c0cfc06c74f015ccf5eb9a9dcd4fede4930c2625968b74fd31a4
|
@@ -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.7.
|
13
|
+
gem.version = '0.7.5.pre.multiworkers'
|
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')
|
@@ -95,6 +95,9 @@ module Fluent
|
|
95
95
|
K8S_CONTAINER_CONSTANTS = {
|
96
96
|
resource_type: 'k8s_container'
|
97
97
|
}.freeze
|
98
|
+
K8S_POD_CONSTANTS = {
|
99
|
+
resource_type: 'k8s_pod'
|
100
|
+
}.freeze
|
98
101
|
K8S_NODE_CONSTANTS = {
|
99
102
|
resource_type: 'k8s_node'
|
100
103
|
}.freeze
|
@@ -143,12 +146,13 @@ module Fluent
|
|
143
146
|
# Default values for JSON payload keys to set the "httpRequest",
|
144
147
|
# "operation", "sourceLocation", "trace" fields in the LogEntry.
|
145
148
|
DEFAULT_HTTP_REQUEST_KEY = 'httpRequest'.freeze
|
149
|
+
DEFAULT_INSERT_ID_KEY = 'logging.googleapis.com/insertId'.freeze
|
150
|
+
DEFAULT_LABELS_KEY = 'logging.googleapis.com/labels'.freeze
|
146
151
|
DEFAULT_OPERATION_KEY = 'logging.googleapis.com/operation'.freeze
|
147
152
|
DEFAULT_SOURCE_LOCATION_KEY =
|
148
153
|
'logging.googleapis.com/sourceLocation'.freeze
|
149
|
-
DEFAULT_TRACE_KEY = 'logging.googleapis.com/trace'.freeze
|
150
154
|
DEFAULT_SPAN_ID_KEY = 'logging.googleapis.com/spanId'.freeze
|
151
|
-
|
155
|
+
DEFAULT_TRACE_KEY = 'logging.googleapis.com/trace'.freeze
|
152
156
|
|
153
157
|
DEFAULT_METADATA_AGENT_URL =
|
154
158
|
'http://local-metadata-agent.stackdriver.com:8000'.freeze
|
@@ -201,16 +205,6 @@ module Fluent
|
|
201
205
|
# The non-grpc version class name.
|
202
206
|
'Google::Apis::LoggingV2::HttpRequest'
|
203
207
|
],
|
204
|
-
'source_location' => [
|
205
|
-
'@source_location_key',
|
206
|
-
[
|
207
|
-
%w(file file parse_string),
|
208
|
-
%w(function function parse_string),
|
209
|
-
%w(line line parse_int)
|
210
|
-
],
|
211
|
-
'Google::Logging::V2::LogEntrySourceLocation',
|
212
|
-
'Google::Apis::LoggingV2::LogEntrySourceLocation'
|
213
|
-
],
|
214
208
|
'operation' => [
|
215
209
|
'@operation_key',
|
216
210
|
[
|
@@ -221,6 +215,16 @@ module Fluent
|
|
221
215
|
],
|
222
216
|
'Google::Logging::V2::LogEntryOperation',
|
223
217
|
'Google::Apis::LoggingV2::LogEntryOperation'
|
218
|
+
],
|
219
|
+
'source_location' => [
|
220
|
+
'@source_location_key',
|
221
|
+
[
|
222
|
+
%w(file file parse_string),
|
223
|
+
%w(function function parse_string),
|
224
|
+
%w(line line parse_int)
|
225
|
+
],
|
226
|
+
'Google::Logging::V2::LogEntrySourceLocation',
|
227
|
+
'Google::Apis::LoggingV2::LogEntrySourceLocation'
|
224
228
|
]
|
225
229
|
}.freeze
|
226
230
|
|
@@ -295,12 +299,13 @@ module Fluent
|
|
295
299
|
# Map keys from a JSON payload to corresponding LogEntry fields.
|
296
300
|
config_param :http_request_key, :string, :default =>
|
297
301
|
DEFAULT_HTTP_REQUEST_KEY
|
302
|
+
config_param :insert_id_key, :string, :default => DEFAULT_INSERT_ID_KEY
|
303
|
+
config_param :labels_key, :string, :default => DEFAULT_LABELS_KEY
|
298
304
|
config_param :operation_key, :string, :default => DEFAULT_OPERATION_KEY
|
299
305
|
config_param :source_location_key, :string, :default =>
|
300
306
|
DEFAULT_SOURCE_LOCATION_KEY
|
301
|
-
config_param :trace_key, :string, :default => DEFAULT_TRACE_KEY
|
302
307
|
config_param :span_id_key, :string, :default => DEFAULT_SPAN_ID_KEY
|
303
|
-
config_param :
|
308
|
+
config_param :trace_key, :string, :default => DEFAULT_TRACE_KEY
|
304
309
|
|
305
310
|
# Whether to try to detect if the record is a text log entry with JSON
|
306
311
|
# content that needs to be parsed.
|
@@ -617,6 +622,7 @@ module Fluent
|
|
617
622
|
'severity',
|
618
623
|
@http_request_key,
|
619
624
|
@insert_id_key,
|
625
|
+
@labels_key,
|
620
626
|
@operation_key,
|
621
627
|
@source_location_key,
|
622
628
|
@span_id_key,
|
@@ -650,6 +656,11 @@ module Fluent
|
|
650
656
|
severity = compute_severity(
|
651
657
|
entry_level_resource.type, record, entry_level_common_labels)
|
652
658
|
|
659
|
+
dynamic_labels_from_payload = parse_labels(record)
|
660
|
+
|
661
|
+
entry_level_common_labels = entry_level_common_labels.merge!(
|
662
|
+
dynamic_labels_from_payload) if dynamic_labels_from_payload
|
663
|
+
|
653
664
|
entry = @construct_log_entry.call(entry_level_common_labels,
|
654
665
|
entry_level_resource,
|
655
666
|
severity,
|
@@ -1178,6 +1189,8 @@ module Fluent
|
|
1178
1189
|
|
1179
1190
|
# GCE.
|
1180
1191
|
when COMPUTE_CONSTANTS[:resource_type]
|
1192
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
1193
|
+
unless @vm_id && @zone
|
1181
1194
|
return {
|
1182
1195
|
'instance_id' => @vm_id,
|
1183
1196
|
'zone' => @zone
|
@@ -1185,6 +1198,8 @@ module Fluent
|
|
1185
1198
|
|
1186
1199
|
# GKE container.
|
1187
1200
|
when GKE_CONSTANTS[:resource_type]
|
1201
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
1202
|
+
unless @vm_id && @zone
|
1188
1203
|
return {
|
1189
1204
|
'instance_id' => @vm_id,
|
1190
1205
|
'zone' => @zone,
|
@@ -1205,6 +1220,8 @@ module Fluent
|
|
1205
1220
|
|
1206
1221
|
# EC2.
|
1207
1222
|
when EC2_CONSTANTS[:resource_type]
|
1223
|
+
raise "Cannot construct a #{type} resource without vm_id and zone" \
|
1224
|
+
unless @vm_id && @zone
|
1208
1225
|
labels = {
|
1209
1226
|
'instance_id' => @vm_id,
|
1210
1227
|
'region' => @zone
|
@@ -1366,6 +1383,7 @@ module Fluent
|
|
1366
1383
|
# TODO(qingling128): Temporary fallback for metadata agent restarts.
|
1367
1384
|
# K8s resources.
|
1368
1385
|
when K8S_CONTAINER_CONSTANTS[:resource_type],
|
1386
|
+
K8S_POD_CONSTANTS[:resource_type],
|
1369
1387
|
K8S_NODE_CONSTANTS[:resource_type]
|
1370
1388
|
common_labels.delete("#{COMPUTE_CONSTANTS[:service]}/resource_name")
|
1371
1389
|
|
@@ -1685,6 +1703,10 @@ module Fluent
|
|
1685
1703
|
end
|
1686
1704
|
|
1687
1705
|
def set_log_entry_fields(record, entry)
|
1706
|
+
# TODO(qingling128) On the next major after 0.7.4, make all logEntry
|
1707
|
+
# subfields behave the same way: if the field is not in the correct
|
1708
|
+
# format, log an error in the Fluentd log and remove this field from
|
1709
|
+
# payload. This is the preferred behavior per PM decision.
|
1688
1710
|
LOG_ENTRY_FIELDS_MAP.each do |field_name, config|
|
1689
1711
|
payload_key, subfields, grpc_class, non_grpc_class = config
|
1690
1712
|
begin
|
@@ -1728,6 +1750,31 @@ module Fluent
|
|
1728
1750
|
end
|
1729
1751
|
end
|
1730
1752
|
|
1753
|
+
# Parse labels. Return nil if not set.
|
1754
|
+
def parse_labels(record)
|
1755
|
+
payload_labels = record.delete(@labels_key)
|
1756
|
+
return nil unless payload_labels
|
1757
|
+
unless payload_labels.is_a?(Hash)
|
1758
|
+
@log.error "Invalid value of '#{@labels_key}' in the payload: " \
|
1759
|
+
"#{payload_labels}. Labels need to be a JSON object."
|
1760
|
+
return nil
|
1761
|
+
end
|
1762
|
+
|
1763
|
+
non_string_keys = payload_labels.each_with_object([]) do |(k, v), a|
|
1764
|
+
a << k unless k.is_a?(String) && v.is_a?(String)
|
1765
|
+
end
|
1766
|
+
unless non_string_keys.empty?
|
1767
|
+
@log.error "Invalid value of '#{@labels_key}' in the payload: " \
|
1768
|
+
"#{payload_labels}. Labels need string values for all " \
|
1769
|
+
"keys; keys #{non_string_keys} don't."
|
1770
|
+
return nil
|
1771
|
+
end
|
1772
|
+
payload_labels
|
1773
|
+
rescue StandardError => err
|
1774
|
+
@log.error "Failed to extract '#{@labels_key}' from payload.", err
|
1775
|
+
return nil
|
1776
|
+
end
|
1777
|
+
|
1731
1778
|
# Values permitted by the API for 'severity' (which is an enum).
|
1732
1779
|
VALID_SEVERITIES = Set.new(
|
1733
1780
|
%w(DEFAULT DEBUG INFO NOTICE WARNING ERROR CRITICAL ALERT EMERGENCY)
|
@@ -1875,6 +1922,10 @@ module Fluent
|
|
1875
1922
|
.gsub('p.p', '.')
|
1876
1923
|
end
|
1877
1924
|
|
1925
|
+
def multi_workers_ready?
|
1926
|
+
true
|
1927
|
+
end
|
1928
|
+
|
1878
1929
|
def format(tag, time, record)
|
1879
1930
|
Fluent::Engine.msgpack_factory.packer.write([tag, time, record]).to_s
|
1880
1931
|
end
|
@@ -2260,6 +2311,10 @@ module Fluent
|
|
2260
2311
|
\.(?<namespace_name>[0-9a-z-]+)
|
2261
2312
|
\.(?<pod_name>[.0-9a-z-]+)
|
2262
2313
|
\.(?<container_name>[0-9a-z-]+)$/x =~ local_resource_id ||
|
2314
|
+
/^
|
2315
|
+
(?<resource_type>k8s_pod)
|
2316
|
+
\.(?<namespace_name>[0-9a-z-]+)
|
2317
|
+
\.(?<pod_name>[.0-9a-z-]+)$/x =~ local_resource_id ||
|
2263
2318
|
/^
|
2264
2319
|
(?<resource_type>k8s_node)
|
2265
2320
|
\.(?<node_name>[0-9a-z-]+)$/x =~ local_resource_id
|
@@ -2287,6 +2342,14 @@ module Fluent
|
|
2287
2342
|
'location' => @k8s_cluster_location
|
2288
2343
|
}
|
2289
2344
|
fallback_resource = GKE_CONSTANTS[:resource_type]
|
2345
|
+
when K8S_POD_CONSTANTS[:resource_type]
|
2346
|
+
labels = {
|
2347
|
+
'namespace_name' => namespace_name,
|
2348
|
+
'pod_name' => pod_name,
|
2349
|
+
'cluster_name' => @k8s_cluster_name,
|
2350
|
+
'location' => @k8s_cluster_location
|
2351
|
+
}
|
2352
|
+
fallback_resource = GKE_CONSTANTS[:resource_type]
|
2290
2353
|
when K8S_NODE_CONSTANTS[:resource_type]
|
2291
2354
|
labels = {
|
2292
2355
|
'node_name' => node_name,
|
data/test/plugin/base_test.rb
CHANGED
@@ -626,7 +626,9 @@ module BaseTest
|
|
626
626
|
end
|
627
627
|
d.run
|
628
628
|
end
|
629
|
-
|
629
|
+
expected_params = COMPUTE_PARAMS.merge(
|
630
|
+
labels: COMPUTE_PARAMS[:labels].merge(LABELS_MESSAGE))
|
631
|
+
verify_log_entries(3, expected_params, 'jsonPayload') do |entry|
|
630
632
|
fields = get_fields(entry['jsonPayload'])
|
631
633
|
assert_equal 4, fields.size, entry
|
632
634
|
assert_equal 'test log entry 0', get_string(fields['msg']), entry
|
@@ -1249,14 +1251,18 @@ module BaseTest
|
|
1249
1251
|
verify_subfields_from_record(DEFAULT_HTTP_REQUEST_KEY)
|
1250
1252
|
end
|
1251
1253
|
|
1252
|
-
def
|
1253
|
-
verify_subfields_from_record(
|
1254
|
+
def test_log_entry_labels_field_from_record
|
1255
|
+
verify_subfields_from_record(DEFAULT_LABELS_KEY, false)
|
1254
1256
|
end
|
1255
1257
|
|
1256
1258
|
def test_log_entry_operation_field_from_record
|
1257
1259
|
verify_subfields_from_record(DEFAULT_OPERATION_KEY)
|
1258
1260
|
end
|
1259
1261
|
|
1262
|
+
def test_log_entry_source_location_field_from_record
|
1263
|
+
verify_subfields_from_record(DEFAULT_SOURCE_LOCATION_KEY)
|
1264
|
+
end
|
1265
|
+
|
1260
1266
|
# Verify the subfields extraction of LogEntry fields when there are other
|
1261
1267
|
# fields.
|
1262
1268
|
|
@@ -1264,26 +1270,48 @@ module BaseTest
|
|
1264
1270
|
verify_subfields_partial_from_record(DEFAULT_HTTP_REQUEST_KEY)
|
1265
1271
|
end
|
1266
1272
|
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1273
|
+
# We don't need a test like 'test_log_entry_labels_field_partial_from_record'
|
1274
|
+
# because labels are free range strings. Everything in the labels field should
|
1275
|
+
# be in the resulting logEntry->labels field. There is no need to check
|
1276
|
+
# partial transformation (aka, some 'labels' fields are extracted, while
|
1277
|
+
# others are left as it is).
|
1270
1278
|
|
1271
1279
|
def test_log_entry_operation_field_partial_from_record
|
1272
1280
|
verify_subfields_partial_from_record(DEFAULT_OPERATION_KEY)
|
1273
1281
|
end
|
1274
1282
|
|
1283
|
+
def test_log_entry_source_location_field_partial_from_record
|
1284
|
+
verify_subfields_partial_from_record(DEFAULT_SOURCE_LOCATION_KEY)
|
1285
|
+
end
|
1286
|
+
|
1275
1287
|
# Verify the subfields extraction of LogEntry fields when they are not hashes.
|
1276
1288
|
|
1277
1289
|
def test_log_entry_http_request_field_when_not_hash
|
1278
|
-
|
1290
|
+
# TODO(qingling128) On the next major after 0.7.4, make all logEntry
|
1291
|
+
# subfields behave the same way: if the field is not in the correct format,
|
1292
|
+
# log an error in the Fluentd log and remove this field from payload. This
|
1293
|
+
# is the preferred behavior per PM decision.
|
1294
|
+
verify_subfields_untouched_when_not_hash(DEFAULT_HTTP_REQUEST_KEY)
|
1279
1295
|
end
|
1280
1296
|
|
1281
|
-
def
|
1282
|
-
|
1297
|
+
def test_log_entry_labels_field_when_not_hash
|
1298
|
+
verify_subfields_removed_when_not_hash(DEFAULT_LABELS_KEY)
|
1283
1299
|
end
|
1284
1300
|
|
1285
1301
|
def test_log_entry_operation_field_when_not_hash
|
1286
|
-
|
1302
|
+
# TODO(qingling128) On the next major after 0.7.4, make all logEntry
|
1303
|
+
# subfields behave the same way: if the field is not in the correct format,
|
1304
|
+
# log an error in the Fluentd log and remove this field from payload. This
|
1305
|
+
# is the preferred behavior per PM decision.
|
1306
|
+
verify_subfields_untouched_when_not_hash(DEFAULT_OPERATION_KEY)
|
1307
|
+
end
|
1308
|
+
|
1309
|
+
def test_log_entry_source_location_field_when_not_hash
|
1310
|
+
# TODO(qingling128) On the next major after 0.7.4, make all logEntry
|
1311
|
+
# subfields behave the same way: if the field is not in the correct format,
|
1312
|
+
# log an error in the Fluentd log and remove this field from payload. This
|
1313
|
+
# is the preferred behavior per PM decision.
|
1314
|
+
verify_subfields_untouched_when_not_hash(DEFAULT_SOURCE_LOCATION_KEY)
|
1287
1315
|
end
|
1288
1316
|
|
1289
1317
|
# Verify the subfields extraction of LogEntry fields when they are nil.
|
@@ -1292,14 +1320,18 @@ module BaseTest
|
|
1292
1320
|
verify_subfields_when_nil(DEFAULT_HTTP_REQUEST_KEY)
|
1293
1321
|
end
|
1294
1322
|
|
1295
|
-
def
|
1296
|
-
verify_subfields_when_nil(
|
1323
|
+
def test_log_entry_labels_field_when_nil
|
1324
|
+
verify_subfields_when_nil(DEFAULT_LABELS_KEY)
|
1297
1325
|
end
|
1298
1326
|
|
1299
1327
|
def test_log_entry_operation_field_when_nil
|
1300
1328
|
verify_subfields_when_nil(DEFAULT_OPERATION_KEY)
|
1301
1329
|
end
|
1302
1330
|
|
1331
|
+
def test_log_entry_source_location_field_when_nil
|
1332
|
+
verify_subfields_when_nil(DEFAULT_SOURCE_LOCATION_KEY)
|
1333
|
+
end
|
1334
|
+
|
1303
1335
|
def test_http_request_from_record_with_referer_nil_or_absent
|
1304
1336
|
setup_gce_metadata_stubs
|
1305
1337
|
[
|
@@ -1360,30 +1392,54 @@ module BaseTest
|
|
1360
1392
|
# Verify the default and customization of LogEntry field extraction key.
|
1361
1393
|
|
1362
1394
|
def test_log_entry_insert_id_field
|
1363
|
-
verify_field_key('insertId',
|
1364
|
-
|
1395
|
+
verify_field_key('insertId',
|
1396
|
+
default_key: DEFAULT_INSERT_ID_KEY,
|
1397
|
+
custom_key: 'custom_insert_id_key',
|
1398
|
+
custom_key_config: CONFIG_CUSTOM_INSERT_ID_KEY_SPECIFIED,
|
1399
|
+
sample_value: INSERT_ID)
|
1400
|
+
end
|
1401
|
+
|
1402
|
+
def test_log_entry_labels_field
|
1403
|
+
verify_field_key('labels',
|
1404
|
+
default_key: DEFAULT_LABELS_KEY,
|
1405
|
+
custom_key: 'custom_labels_key',
|
1406
|
+
custom_key_config: CONFIG_CUSTOM_LABELS_KEY_SPECIFIED,
|
1407
|
+
sample_value: COMPUTE_PARAMS[:labels].merge(
|
1408
|
+
LABELS_MESSAGE),
|
1409
|
+
default_value: COMPUTE_PARAMS[:labels])
|
1365
1410
|
end
|
1366
1411
|
|
1367
1412
|
def test_log_entry_operation_field
|
1368
|
-
verify_field_key('operation',
|
1369
|
-
|
1413
|
+
verify_field_key('operation',
|
1414
|
+
default_key: DEFAULT_OPERATION_KEY,
|
1415
|
+
custom_key: 'custom_operation_key',
|
1416
|
+
custom_key_config: CONFIG_CUSTOM_OPERATION_KEY_SPECIFIED,
|
1417
|
+
sample_value: OPERATION_MESSAGE)
|
1370
1418
|
end
|
1371
1419
|
|
1372
1420
|
def test_log_entry_source_location_field
|
1373
|
-
verify_field_key('sourceLocation',
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1421
|
+
verify_field_key('sourceLocation',
|
1422
|
+
default_key: DEFAULT_SOURCE_LOCATION_KEY,
|
1423
|
+
custom_key: 'custom_source_location_key',
|
1424
|
+
custom_key_config: \
|
1425
|
+
CONFIG_CUSTOM_SOURCE_LOCATION_KEY_SPECIFIED,
|
1426
|
+
sample_value: source_location_message)
|
1377
1427
|
end
|
1378
1428
|
|
1379
1429
|
def test_log_entry_span_id_field
|
1380
|
-
verify_field_key('spanId',
|
1381
|
-
|
1430
|
+
verify_field_key('spanId',
|
1431
|
+
default_key: DEFAULT_SPAN_ID_KEY,
|
1432
|
+
custom_key: 'custom_span_id_key',
|
1433
|
+
custom_key_config: CONFIG_CUSTOM_SPAN_ID_KEY_SPECIFIED,
|
1434
|
+
sample_value: SPAN_ID)
|
1382
1435
|
end
|
1383
1436
|
|
1384
1437
|
def test_log_entry_trace_field
|
1385
|
-
verify_field_key('trace',
|
1386
|
-
|
1438
|
+
verify_field_key('trace',
|
1439
|
+
default_key: DEFAULT_TRACE_KEY,
|
1440
|
+
custom_key: 'custom_trace_key',
|
1441
|
+
custom_key_config: CONFIG_CUSTOM_TRACE_KEY_SPECIFIED,
|
1442
|
+
sample_value: TRACE)
|
1387
1443
|
end
|
1388
1444
|
|
1389
1445
|
# Verify the cascading JSON detection of LogEntry fields.
|
@@ -1395,6 +1451,16 @@ module BaseTest
|
|
1395
1451
|
nested_level_value: INSERT_ID2)
|
1396
1452
|
end
|
1397
1453
|
|
1454
|
+
def test_cascading_json_detection_with_log_entry_labels_field
|
1455
|
+
verify_cascading_json_detection_with_log_entry_fields(
|
1456
|
+
'labels', DEFAULT_LABELS_KEY,
|
1457
|
+
root_level_value: LABELS_MESSAGE,
|
1458
|
+
nested_level_value: LABELS_MESSAGE2,
|
1459
|
+
expected_value_from_root: COMPUTE_PARAMS[:labels].merge(LABELS_MESSAGE),
|
1460
|
+
expected_value_from_nested: COMPUTE_PARAMS[:labels].merge(
|
1461
|
+
LABELS_MESSAGE2))
|
1462
|
+
end
|
1463
|
+
|
1398
1464
|
def test_cascading_json_detection_with_log_entry_operation_field
|
1399
1465
|
verify_cascading_json_detection_with_log_entry_fields(
|
1400
1466
|
'operation', DEFAULT_OPERATION_KEY,
|
@@ -1424,6 +1490,82 @@ module BaseTest
|
|
1424
1490
|
nested_level_value: TRACE2)
|
1425
1491
|
end
|
1426
1492
|
|
1493
|
+
# Verify that labels present in multiple inputs respect the expected priority
|
1494
|
+
# order:
|
1495
|
+
# 1. Labels from the field "logging.googleapis.com/labels" in payload.
|
1496
|
+
# 2. Labels from the config "label_map".
|
1497
|
+
# 3. Labels from the config "labels".
|
1498
|
+
def test_labels_order
|
1499
|
+
[
|
1500
|
+
# Labels from the config "labels".
|
1501
|
+
{
|
1502
|
+
config: CONFIG_LABELS,
|
1503
|
+
emitted_log: {},
|
1504
|
+
expected_labels: LABELS_FROM_LABELS_CONFIG
|
1505
|
+
},
|
1506
|
+
# Labels from the config "label_map".
|
1507
|
+
{
|
1508
|
+
config: CONFIG_LABEL_MAP,
|
1509
|
+
emitted_log: PAYLOAD_FOR_LABEL_MAP,
|
1510
|
+
expected_labels: LABELS_FROM_LABEL_MAP_CONFIG
|
1511
|
+
},
|
1512
|
+
# Labels from the field "logging.googleapis.com/labels" in payload.
|
1513
|
+
{
|
1514
|
+
config: APPLICATION_DEFAULT_CONFIG,
|
1515
|
+
emitted_log: { DEFAULT_LABELS_KEY => LABELS_MESSAGE },
|
1516
|
+
expected_labels: LABELS_MESSAGE
|
1517
|
+
},
|
1518
|
+
# All three types of labels that do not conflict.
|
1519
|
+
{
|
1520
|
+
config: CONFIG_LABLES_AND_LABLE_MAP,
|
1521
|
+
emitted_log: PAYLOAD_FOR_LABEL_MAP.merge(
|
1522
|
+
DEFAULT_LABELS_KEY => LABELS_MESSAGE),
|
1523
|
+
expected_labels: LABELS_MESSAGE.merge(LABELS_FROM_LABELS_CONFIG).merge(
|
1524
|
+
LABELS_FROM_LABEL_MAP_CONFIG)
|
1525
|
+
},
|
1526
|
+
# labels from the config "labels" and "label_map" conflict.
|
1527
|
+
{
|
1528
|
+
config: CONFIG_LABLES_AND_LABLE_MAP_CONFLICTING,
|
1529
|
+
emitted_log: PAYLOAD_FOR_LABEL_MAP_CONFLICTING,
|
1530
|
+
expected_labels: LABELS_FROM_LABEL_MAP_CONFIG_CONFLICTING
|
1531
|
+
},
|
1532
|
+
# labels from the config "labels" and labels from the field
|
1533
|
+
# "logging.googleapis.com/labels" in payload conflict.
|
1534
|
+
{
|
1535
|
+
config: CONFIG_LABELS_CONFLICTING,
|
1536
|
+
emitted_log: { DEFAULT_LABELS_KEY => LABELS_FROM_PAYLOAD_CONFLICTING },
|
1537
|
+
expected_labels: LABELS_FROM_PAYLOAD_CONFLICTING
|
1538
|
+
},
|
1539
|
+
# labels from the config "label_map" and labels from the field
|
1540
|
+
# "logging.googleapis.com/labels" in payload conflict.
|
1541
|
+
{
|
1542
|
+
config: CONFIG_LABEL_MAP_CONFLICTING,
|
1543
|
+
emitted_log: PAYLOAD_FOR_LABEL_MAP_CONFLICTING.merge(
|
1544
|
+
DEFAULT_LABELS_KEY => LABELS_FROM_PAYLOAD_CONFLICTING),
|
1545
|
+
expected_labels: LABELS_FROM_PAYLOAD_CONFLICTING
|
1546
|
+
},
|
1547
|
+
# All three types of labels conflict.
|
1548
|
+
{
|
1549
|
+
config: CONFIG_LABLES_AND_LABLE_MAP_CONFLICTING,
|
1550
|
+
emitted_log: PAYLOAD_FOR_LABEL_MAP_CONFLICTING.merge(
|
1551
|
+
DEFAULT_LABELS_KEY => LABELS_FROM_PAYLOAD_CONFLICTING),
|
1552
|
+
expected_labels: LABELS_FROM_PAYLOAD_CONFLICTING
|
1553
|
+
}
|
1554
|
+
].each do |test_params|
|
1555
|
+
new_stub_context do
|
1556
|
+
setup_gce_metadata_stubs
|
1557
|
+
setup_logging_stubs do
|
1558
|
+
d = create_driver(test_params[:config])
|
1559
|
+
d.emit({ 'message' => log_entry(0) }.merge(test_params[:emitted_log]))
|
1560
|
+
d.run
|
1561
|
+
end
|
1562
|
+
expected_params = COMPUTE_PARAMS.merge(
|
1563
|
+
labels: COMPUTE_PARAMS[:labels].merge(test_params[:expected_labels]))
|
1564
|
+
verify_log_entries(1, expected_params)
|
1565
|
+
end
|
1566
|
+
end
|
1567
|
+
end
|
1568
|
+
|
1427
1569
|
# Metadata Agent related tests.
|
1428
1570
|
|
1429
1571
|
# Test enable_metadata_agent not set or set to false.
|
@@ -1648,6 +1790,66 @@ module BaseTest
|
|
1648
1790
|
end
|
1649
1791
|
end
|
1650
1792
|
|
1793
|
+
# Test k8s_pod monitored resource including the fallback when Metadata Agent
|
1794
|
+
# restarts.
|
1795
|
+
def test_k8s_pod_monitored_resource_fallback
|
1796
|
+
[
|
1797
|
+
{
|
1798
|
+
config: APPLICATION_DEFAULT_CONFIG,
|
1799
|
+
setup_metadata_agent_stub: true,
|
1800
|
+
setup_k8s_stub: true,
|
1801
|
+
log_entry: k8s_pod_log_entry(log_entry(0)),
|
1802
|
+
expected_params: K8S_POD_PARAMS_FROM_LOCAL
|
1803
|
+
},
|
1804
|
+
{
|
1805
|
+
config: ENABLE_METADATA_AGENT_CONFIG,
|
1806
|
+
setup_metadata_agent_stub: false,
|
1807
|
+
setup_k8s_stub: true,
|
1808
|
+
log_entry: k8s_pod_log_entry(log_entry(0)),
|
1809
|
+
expected_params: K8S_POD_PARAMS_FROM_LOCAL
|
1810
|
+
},
|
1811
|
+
{
|
1812
|
+
config: CUSTOM_K8S_ENABLE_METADATA_AGENT_CONFIG,
|
1813
|
+
setup_metadata_agent_stub: false,
|
1814
|
+
setup_k8s_stub: false,
|
1815
|
+
log_entry: k8s_pod_log_entry(log_entry(0)),
|
1816
|
+
expected_params: K8S_POD_PARAMS_CUSTOM
|
1817
|
+
},
|
1818
|
+
{
|
1819
|
+
config: EMPTY_K8S_ENABLE_METADATA_AGENT_CONFIG,
|
1820
|
+
setup_metadata_agent_stub: true,
|
1821
|
+
setup_k8s_stub: true,
|
1822
|
+
log_entry: k8s_pod_log_entry(log_entry(0)),
|
1823
|
+
expected_params: K8S_POD_PARAMS
|
1824
|
+
},
|
1825
|
+
{
|
1826
|
+
config: ENABLE_METADATA_AGENT_CONFIG,
|
1827
|
+
setup_metadata_agent_stub: true,
|
1828
|
+
setup_k8s_stub: true,
|
1829
|
+
log_entry: k8s_pod_log_entry(log_entry(0)),
|
1830
|
+
expected_params: K8S_POD_PARAMS
|
1831
|
+
}
|
1832
|
+
].each do |test_params|
|
1833
|
+
new_stub_context do
|
1834
|
+
setup_gce_metadata_stubs
|
1835
|
+
setup_metadata_agent_stubs(test_params[:setup_metadata_agent_stub])
|
1836
|
+
setup_k8s_metadata_stubs(test_params[:setup_k8s_stub])
|
1837
|
+
setup_logging_stubs do
|
1838
|
+
d = create_driver(test_params[:config])
|
1839
|
+
d.emit(test_params[:log_entry])
|
1840
|
+
d.run
|
1841
|
+
end
|
1842
|
+
verify_log_entries(1, test_params[:expected_params],
|
1843
|
+
'jsonPayload') do |entry|
|
1844
|
+
fields = get_fields(entry['jsonPayload'])
|
1845
|
+
assert_equal 2, fields.size, entry
|
1846
|
+
assert_equal 'test log entry 0', get_string(fields['log']), entry
|
1847
|
+
assert_equal K8S_STREAM, get_string(fields['stream']), entry
|
1848
|
+
end
|
1849
|
+
end
|
1850
|
+
end
|
1851
|
+
end
|
1852
|
+
|
1651
1853
|
# Test k8s_node monitored resource including the fallback when Metadata Agent
|
1652
1854
|
# restarts.
|
1653
1855
|
def test_k8s_node_monitored_resource_fallback
|
@@ -2023,6 +2225,18 @@ module BaseTest
|
|
2023
2225
|
}
|
2024
2226
|
end
|
2025
2227
|
|
2228
|
+
def k8s_pod_log_entry(log)
|
2229
|
+
{
|
2230
|
+
log: log,
|
2231
|
+
stream: K8S_STREAM,
|
2232
|
+
time: K8S_TIMESTAMP,
|
2233
|
+
LOCAL_RESOURCE_ID_KEY =>
|
2234
|
+
"#{K8S_POD_LOCAL_RESOURCE_ID_PREFIX}" \
|
2235
|
+
".#{K8S_NAMESPACE_NAME}" \
|
2236
|
+
".#{K8S_POD_NAME}"
|
2237
|
+
}
|
2238
|
+
end
|
2239
|
+
|
2026
2240
|
def k8s_node_log_entry(log)
|
2027
2241
|
{
|
2028
2242
|
log: log,
|
@@ -2082,18 +2296,25 @@ module BaseTest
|
|
2082
2296
|
"test log entry #{i}"
|
2083
2297
|
end
|
2084
2298
|
|
2085
|
-
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2092
|
-
|
2299
|
+
# If check_exact_labels is true, assert 'labels' and 'expected_labels' match
|
2300
|
+
# exactly. If check_exact_labels is false, assert 'labels' is a subset of
|
2301
|
+
# 'expected_labels'.
|
2302
|
+
def check_labels(expected_labels, labels, check_exact_labels = true)
|
2303
|
+
return if expected_labels.empty? && labels.empty?
|
2304
|
+
expected_labels.each do |expected_key, expected_value|
|
2305
|
+
assert labels.key?(expected_key), "Expected label #{expected_key} not" \
|
2306
|
+
" found. Got labels: #{labels}."
|
2307
|
+
actual_value = labels[expected_key]
|
2308
|
+
assert actual_value.is_a?(String), 'Value for label' \
|
2309
|
+
" #{expected_key} is not a string: #{actual_value}."
|
2310
|
+
assert_equal expected_value, actual_value, "Value for #{expected_key}" \
|
2311
|
+
" mismatch. Expected #{expected_value}. Got #{actual_value}"
|
2312
|
+
end
|
2313
|
+
if check_exact_labels
|
2314
|
+
assert_equal expected_labels.length, labels.length, 'Expected ' \
|
2315
|
+
"#{expected_labels.length} labels: #{expected_labels}, got " \
|
2316
|
+
"#{labels.length} labels: #{labels}"
|
2093
2317
|
end
|
2094
|
-
assert_equal expected_labels.length, labels.length, 'Expected ' \
|
2095
|
-
"#{expected_labels.length} labels: #{expected_labels}, got " \
|
2096
|
-
"#{labels.length} labels: #{labels}"
|
2097
2318
|
end
|
2098
2319
|
|
2099
2320
|
def verify_default_log_entry_text(text, i, entry)
|
@@ -2102,7 +2323,8 @@ module BaseTest
|
|
2102
2323
|
end
|
2103
2324
|
|
2104
2325
|
# The caller can optionally provide a block which is called for each entry.
|
2105
|
-
def verify_json_log_entries(n, params, payload_type = 'textPayload'
|
2326
|
+
def verify_json_log_entries(n, params, payload_type = 'textPayload',
|
2327
|
+
check_exact_entry_labels = true)
|
2106
2328
|
entry_count = 0
|
2107
2329
|
@logs_sent.each do |request|
|
2108
2330
|
request['entries'].each do |entry|
|
@@ -2127,8 +2349,10 @@ module BaseTest
|
|
2127
2349
|
log_name
|
2128
2350
|
end
|
2129
2351
|
assert_equal params[:resource][:type], resource['type']
|
2130
|
-
check_labels resource[
|
2131
|
-
|
2352
|
+
check_labels params[:resource][:labels], resource['labels']
|
2353
|
+
|
2354
|
+
check_labels params[:labels], labels, check_exact_entry_labels
|
2355
|
+
|
2132
2356
|
if block_given?
|
2133
2357
|
yield(entry, entry_count)
|
2134
2358
|
elsif payload_type == 'textPayload'
|
@@ -2170,14 +2394,16 @@ module BaseTest
|
|
2170
2394
|
# the subfield in LogEntry object and the expected value of that field.
|
2171
2395
|
DEFAULT_HTTP_REQUEST_KEY => [
|
2172
2396
|
'httpRequest', http_request_message],
|
2173
|
-
|
2174
|
-
'
|
2397
|
+
DEFAULT_LABELS_KEY => [
|
2398
|
+
'labels', COMPUTE_PARAMS[:labels].merge(LABELS_MESSAGE)],
|
2175
2399
|
DEFAULT_OPERATION_KEY => [
|
2176
|
-
'operation', OPERATION_MESSAGE]
|
2400
|
+
'operation', OPERATION_MESSAGE],
|
2401
|
+
DEFAULT_SOURCE_LOCATION_KEY => [
|
2402
|
+
'sourceLocation', source_location_message]
|
2177
2403
|
}
|
2178
2404
|
end
|
2179
2405
|
|
2180
|
-
def verify_subfields_from_record(payload_key)
|
2406
|
+
def verify_subfields_from_record(payload_key, check_exact_entry_labels = true)
|
2181
2407
|
destination_key, payload_value = log_entry_subfields_params[payload_key]
|
2182
2408
|
@logs_sent = []
|
2183
2409
|
setup_gce_metadata_stubs
|
@@ -2186,7 +2412,8 @@ module BaseTest
|
|
2186
2412
|
d.emit(payload_key => payload_value)
|
2187
2413
|
d.run
|
2188
2414
|
end
|
2189
|
-
verify_log_entries(1, COMPUTE_PARAMS, destination_key
|
2415
|
+
verify_log_entries(1, COMPUTE_PARAMS, destination_key,
|
2416
|
+
check_exact_entry_labels) do |entry|
|
2190
2417
|
assert_equal payload_value, entry[destination_key], entry
|
2191
2418
|
fields = get_fields(entry['jsonPayload'])
|
2192
2419
|
assert_nil fields[payload_key], entry
|
@@ -2210,7 +2437,7 @@ module BaseTest
|
|
2210
2437
|
end
|
2211
2438
|
end
|
2212
2439
|
|
2213
|
-
def
|
2440
|
+
def verify_subfields_removed_when_not_hash(payload_key)
|
2214
2441
|
destination_key = log_entry_subfields_params[payload_key][0]
|
2215
2442
|
@logs_sent = []
|
2216
2443
|
setup_gce_metadata_stubs
|
@@ -2220,6 +2447,25 @@ module BaseTest
|
|
2220
2447
|
d.run
|
2221
2448
|
end
|
2222
2449
|
verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload') do |entry|
|
2450
|
+
# The malformed field has been removed from the payload.
|
2451
|
+
assert_true get_fields(entry['jsonPayload']).empty?, entry
|
2452
|
+
# No additional labels.
|
2453
|
+
assert_equal COMPUTE_PARAMS[:labels].size,
|
2454
|
+
entry[destination_key].size, entry
|
2455
|
+
end
|
2456
|
+
end
|
2457
|
+
|
2458
|
+
def verify_subfields_untouched_when_not_hash(payload_key)
|
2459
|
+
destination_key = log_entry_subfields_params[payload_key][0]
|
2460
|
+
@logs_sent = []
|
2461
|
+
setup_gce_metadata_stubs
|
2462
|
+
setup_logging_stubs do
|
2463
|
+
d = create_driver
|
2464
|
+
d.emit(payload_key => 'a_string')
|
2465
|
+
d.run
|
2466
|
+
end
|
2467
|
+
verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload') do |entry|
|
2468
|
+
# Verify that we leave the malformed field as it is.
|
2223
2469
|
field = get_fields(entry['jsonPayload'])[payload_key]
|
2224
2470
|
assert_equal 'a_string', get_string(field), entry
|
2225
2471
|
assert_false entry.key?(destination_key), entry
|
@@ -2239,7 +2485,13 @@ module BaseTest
|
|
2239
2485
|
verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload') do |entry|
|
2240
2486
|
fields = get_fields(entry['jsonPayload'])
|
2241
2487
|
assert_false fields.key?(payload_key), entry
|
2242
|
-
|
2488
|
+
if payload_key == DEFAULT_LABELS_KEY
|
2489
|
+
# No additional labels.
|
2490
|
+
assert_equal COMPUTE_PARAMS[:labels].size,
|
2491
|
+
entry[destination_key].size, entry
|
2492
|
+
else
|
2493
|
+
assert_false entry.key?(destination_key), entry
|
2494
|
+
end
|
2243
2495
|
end
|
2244
2496
|
end
|
2245
2497
|
|
@@ -2302,7 +2554,7 @@ module BaseTest
|
|
2302
2554
|
d.emit(input_log_entry)
|
2303
2555
|
d.run
|
2304
2556
|
end
|
2305
|
-
verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload') do |entry|
|
2557
|
+
verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload', false) do |entry|
|
2306
2558
|
assert_equal expected_value, entry[log_entry_field],
|
2307
2559
|
"Index #{index} failed. #{expected_value} is expected" \
|
2308
2560
|
" for #{log_entry_field} field."
|
@@ -2315,8 +2567,13 @@ module BaseTest
|
|
2315
2567
|
end
|
2316
2568
|
end
|
2317
2569
|
|
2318
|
-
def verify_field_key(log_entry_field,
|
2319
|
-
|
2570
|
+
def verify_field_key(log_entry_field, test_params)
|
2571
|
+
default_key = test_params[:default_key]
|
2572
|
+
custom_key = test_params[:custom_key]
|
2573
|
+
custom_key_config = test_params[:custom_key_config]
|
2574
|
+
sample_value = test_params[:sample_value]
|
2575
|
+
default_value = test_params.fetch(:default_value, nil)
|
2576
|
+
|
2320
2577
|
setup_gce_metadata_stubs
|
2321
2578
|
message = log_entry(0)
|
2322
2579
|
[
|
@@ -2325,7 +2582,7 @@ module BaseTest
|
|
2325
2582
|
driver_config: APPLICATION_DEFAULT_CONFIG,
|
2326
2583
|
emitted_log: { 'msg' => message },
|
2327
2584
|
expected_payload: { 'msg' => message },
|
2328
|
-
expected_field_value:
|
2585
|
+
expected_field_value: default_value
|
2329
2586
|
},
|
2330
2587
|
{
|
2331
2588
|
# By default, it sets log entry field via a default key.
|
@@ -2346,7 +2603,7 @@ module BaseTest
|
|
2346
2603
|
driver_config: custom_key_config,
|
2347
2604
|
emitted_log: { 'msg' => message, default_key => sample_value },
|
2348
2605
|
expected_payload: { 'msg' => message, default_key => sample_value },
|
2349
|
-
expected_field_value:
|
2606
|
+
expected_field_value: default_value
|
2350
2607
|
}
|
2351
2608
|
].each do |input|
|
2352
2609
|
setup_logging_stubs do
|
@@ -2355,7 +2612,7 @@ module BaseTest
|
|
2355
2612
|
d.emit(input[:emitted_log])
|
2356
2613
|
d.run
|
2357
2614
|
end
|
2358
|
-
verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload') do |entry|
|
2615
|
+
verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload', false) do |entry|
|
2359
2616
|
assert_equal input[:expected_field_value], entry[log_entry_field], input
|
2360
2617
|
payload_fields = get_fields(entry['jsonPayload'])
|
2361
2618
|
assert_equal input[:expected_payload].size, payload_fields.size, input
|
@@ -2413,7 +2670,8 @@ module BaseTest
|
|
2413
2670
|
|
2414
2671
|
# Verify the number and the content of the log entries match the expectation.
|
2415
2672
|
# The caller can optionally provide a block which is called for each entry.
|
2416
|
-
def verify_log_entries(_n, _params, _payload_type = 'textPayload',
|
2673
|
+
def verify_log_entries(_n, _params, _payload_type = 'textPayload',
|
2674
|
+
_check_exact_entry_labels = true, &_block)
|
2417
2675
|
_undefined
|
2418
2676
|
end
|
2419
2677
|
|
data/test/plugin/constants.rb
CHANGED
@@ -156,6 +156,7 @@ module Constants
|
|
156
156
|
K8S_SECONDS_EPOCH = 1_234_567_890
|
157
157
|
K8S_NANOS = 987_654_321
|
158
158
|
K8S_CONTAINER_LOCAL_RESOURCE_ID_PREFIX = 'k8s_container'.freeze
|
159
|
+
K8S_POD_LOCAL_RESOURCE_ID_PREFIX = 'k8s_pod'.freeze
|
159
160
|
K8S_NODE_LOCAL_RESOURCE_ID_PREFIX = 'k8s_node'.freeze
|
160
161
|
K8S_TAG =
|
161
162
|
"var.log.containers.#{K8S_NAMESPACE_NAME}_#{K8S_POD_NAME}_" \
|
@@ -375,6 +376,10 @@ module Constants
|
|
375
376
|
insert_id_key custom_insert_id_key
|
376
377
|
).freeze
|
377
378
|
|
379
|
+
CONFIG_CUSTOM_LABELS_KEY_SPECIFIED = %(
|
380
|
+
labels_key custom_labels_key
|
381
|
+
).freeze
|
382
|
+
|
378
383
|
CONFIG_CUSTOM_OPERATION_KEY_SPECIFIED = %(
|
379
384
|
operation_key custom_operation_key
|
380
385
|
).freeze
|
@@ -391,6 +396,69 @@ module Constants
|
|
391
396
|
trace_key custom_trace_key
|
392
397
|
).freeze
|
393
398
|
|
399
|
+
# For 'labels' config.
|
400
|
+
LABELS_FROM_LABELS_CONFIG = {
|
401
|
+
'a_label_from_labels_config' => 'some_value',
|
402
|
+
'another_label_from_labels_config' => 'some_value'
|
403
|
+
}.freeze
|
404
|
+
CONFIG_LABELS = %(
|
405
|
+
labels #{LABELS_FROM_LABELS_CONFIG.to_json}
|
406
|
+
).freeze
|
407
|
+
|
408
|
+
# For 'label_map' config.
|
409
|
+
LABEL_MAP_HASH = {
|
410
|
+
'target_field_from_payload' => 'a_label_from_label_map_config',
|
411
|
+
'another_target_field_from_payload' => 'another_label_from_label_map_config'
|
412
|
+
}.freeze
|
413
|
+
PAYLOAD_FOR_LABEL_MAP = {
|
414
|
+
'target_field_from_payload' => 'a_value',
|
415
|
+
'another_target_field_from_payload' => 'b_value'
|
416
|
+
}.freeze
|
417
|
+
LABELS_FROM_LABEL_MAP_CONFIG = {
|
418
|
+
'a_label_from_label_map_config' => 'a_value',
|
419
|
+
'another_label_from_label_map_config' => 'b_value'
|
420
|
+
}.freeze
|
421
|
+
CONFIG_LABEL_MAP = %(
|
422
|
+
label_map #{LABEL_MAP_HASH.to_json}
|
423
|
+
).freeze
|
424
|
+
|
425
|
+
CONFIG_LABLES_AND_LABLE_MAP = %(
|
426
|
+
#{CONFIG_LABELS}
|
427
|
+
#{CONFIG_LABEL_MAP}
|
428
|
+
).freeze
|
429
|
+
|
430
|
+
# For conflicting labels.
|
431
|
+
CONFLICTING_LABEL_NAME = 'conflicting_label_key'.freeze
|
432
|
+
CONFLICTING_LABEL_VALUE1 = 'conflicting_value_1'.freeze
|
433
|
+
CONFLICTING_LABEL_VALUE2 = 'conflicting_value_2'.freeze
|
434
|
+
CONFLICTING_LABEL_VALUE3 = 'conflicting_value_3'.freeze
|
435
|
+
LABELS_FROM_PAYLOAD_CONFLICTING = {
|
436
|
+
CONFLICTING_LABEL_NAME => CONFLICTING_LABEL_VALUE1
|
437
|
+
}.freeze
|
438
|
+
LABELS_FROM_LABEL_MAP_CONFIG_CONFLICTING = {
|
439
|
+
CONFLICTING_LABEL_NAME => CONFLICTING_LABEL_VALUE2
|
440
|
+
}.freeze
|
441
|
+
LABELS_FROM_LABELS_CONFIG_CONFLICTING = {
|
442
|
+
CONFLICTING_LABEL_NAME => CONFLICTING_LABEL_VALUE3
|
443
|
+
}.freeze
|
444
|
+
|
445
|
+
LABEL_MAP_HASH_CONFLICTING = {
|
446
|
+
'target_field_from_payload' => CONFLICTING_LABEL_NAME
|
447
|
+
}.freeze
|
448
|
+
PAYLOAD_FOR_LABEL_MAP_CONFLICTING = {
|
449
|
+
'target_field_from_payload' => CONFLICTING_LABEL_VALUE2
|
450
|
+
}.freeze
|
451
|
+
CONFIG_LABEL_MAP_CONFLICTING = %(
|
452
|
+
label_map #{LABEL_MAP_HASH_CONFLICTING.to_json}
|
453
|
+
).freeze
|
454
|
+
CONFIG_LABELS_CONFLICTING = %(
|
455
|
+
labels #{LABELS_FROM_LABELS_CONFIG_CONFLICTING.to_json}
|
456
|
+
).freeze
|
457
|
+
CONFIG_LABLES_AND_LABLE_MAP_CONFLICTING = %(
|
458
|
+
#{CONFIG_LABELS_CONFLICTING}
|
459
|
+
#{CONFIG_LABEL_MAP_CONFLICTING}
|
460
|
+
).freeze
|
461
|
+
|
394
462
|
# Service configurations for various services.
|
395
463
|
|
396
464
|
# GCE.
|
@@ -543,6 +611,36 @@ module Constants
|
|
543
611
|
log_name: CONTAINER_TAG
|
544
612
|
).freeze
|
545
613
|
|
614
|
+
# K8s Pod.
|
615
|
+
K8S_POD_PARAMS = {
|
616
|
+
resource: {
|
617
|
+
type: K8S_POD_CONSTANTS[:resource_type],
|
618
|
+
labels: {
|
619
|
+
'namespace_name' => K8S_NAMESPACE_NAME,
|
620
|
+
'pod_name' => K8S_POD_NAME,
|
621
|
+
'cluster_name' => K8S_CLUSTER_NAME,
|
622
|
+
'location' => K8S_LOCATION
|
623
|
+
}
|
624
|
+
},
|
625
|
+
project_id: PROJECT_ID,
|
626
|
+
labels: {}
|
627
|
+
}.freeze
|
628
|
+
K8S_POD_PARAMS_FROM_LOCAL = K8S_POD_PARAMS.merge(
|
629
|
+
resource: K8S_POD_PARAMS[:resource].merge(
|
630
|
+
labels: K8S_POD_PARAMS[:resource][:labels].merge(
|
631
|
+
'location' => K8S_LOCATION2
|
632
|
+
)
|
633
|
+
)
|
634
|
+
).freeze
|
635
|
+
K8S_POD_PARAMS_CUSTOM = K8S_POD_PARAMS.merge(
|
636
|
+
resource: K8S_POD_PARAMS[:resource].merge(
|
637
|
+
labels: K8S_POD_PARAMS[:resource][:labels].merge(
|
638
|
+
'cluster_name' => CUSTOM_K8S_CLUSTER_NAME,
|
639
|
+
'location' => CUSTOM_K8S_LOCATION
|
640
|
+
)
|
641
|
+
)
|
642
|
+
).freeze
|
643
|
+
|
546
644
|
# K8s Node.
|
547
645
|
K8S_NODE_PARAMS = {
|
548
646
|
resource: {
|
@@ -781,6 +879,18 @@ module Constants
|
|
781
879
|
'last' => false
|
782
880
|
}.freeze
|
783
881
|
|
882
|
+
LABELS_MESSAGE = {
|
883
|
+
'component' => 'front-end',
|
884
|
+
'source' => 'user',
|
885
|
+
'app' => 'request-router'
|
886
|
+
}.freeze
|
887
|
+
|
888
|
+
LABELS_MESSAGE2 = {
|
889
|
+
'component' => 'front-end',
|
890
|
+
'source' => 'system',
|
891
|
+
'app' => 'request-router'
|
892
|
+
}.freeze
|
893
|
+
|
784
894
|
CUSTOM_LABELS_MESSAGE = {
|
785
895
|
'customKey' => 'value'
|
786
896
|
}.freeze
|
@@ -858,6 +968,18 @@ module Constants
|
|
858
968
|
'location' => K8S_LOCATION
|
859
969
|
}
|
860
970
|
}.to_json,
|
971
|
+
# K8s pod logs.
|
972
|
+
"#{K8S_POD_LOCAL_RESOURCE_ID_PREFIX}.#{K8S_NAMESPACE_NAME}" \
|
973
|
+
".#{K8S_POD_NAME}" =>
|
974
|
+
{
|
975
|
+
'type' => K8S_POD_CONSTANTS[:resource_type],
|
976
|
+
'labels' => {
|
977
|
+
'namespace_name' => K8S_NAMESPACE_NAME,
|
978
|
+
'pod_name' => K8S_POD_NAME,
|
979
|
+
'cluster_name' => K8S_CLUSTER_NAME,
|
980
|
+
'location' => K8S_LOCATION
|
981
|
+
}
|
982
|
+
}.to_json,
|
861
983
|
# K8s node logs.
|
862
984
|
"#{K8S_NODE_LOCAL_RESOURCE_ID_PREFIX}.#{K8S_NODE_NAME}" =>
|
863
985
|
{
|
@@ -980,6 +1102,7 @@ module Constants
|
|
980
1102
|
'severity' => CONTAINER_SEVERITY,
|
981
1103
|
DEFAULT_HTTP_REQUEST_KEY => HTTP_REQUEST_MESSAGE,
|
982
1104
|
DEFAULT_INSERT_ID_KEY => INSERT_ID,
|
1105
|
+
DEFAULT_LABELS_KEY => LABELS_MESSAGE,
|
983
1106
|
DEFAULT_OPERATION_KEY => OPERATION_MESSAGE,
|
984
1107
|
DEFAULT_SOURCE_LOCATION_KEY => SOURCE_LOCATION_MESSAGE,
|
985
1108
|
DEFAULT_SPAN_ID_KEY => SPAN_ID,
|
@@ -364,8 +364,10 @@ class GoogleCloudOutputTest < Test::Unit::TestCase
|
|
364
364
|
|
365
365
|
# Verify the number and the content of the log entries match the expectation.
|
366
366
|
# The caller can optionally provide a block which is called for each entry.
|
367
|
-
def verify_log_entries(n, params, payload_type = 'textPayload',
|
368
|
-
|
367
|
+
def verify_log_entries(n, params, payload_type = 'textPayload',
|
368
|
+
check_exact_entry_labels = true, &block)
|
369
|
+
verify_json_log_entries(n, params, payload_type, check_exact_entry_labels,
|
370
|
+
&block)
|
369
371
|
end
|
370
372
|
|
371
373
|
# For an optional field with default values, Protobuf omits the field when it
|
@@ -413,7 +413,8 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
|
|
413
413
|
|
414
414
|
# Verify the number and the content of the log entries match the expectation.
|
415
415
|
# The caller can optionally provide a block which is called for each entry.
|
416
|
-
def verify_log_entries(n, params, payload_type = 'textPayload',
|
416
|
+
def verify_log_entries(n, params, payload_type = 'textPayload',
|
417
|
+
check_exact_entry_labels = true, &block)
|
417
418
|
@requests_sent.each do |request|
|
418
419
|
@logs_sent << {
|
419
420
|
'entries' => request.entries.map { |entry| JSON.parse(entry.to_json) },
|
@@ -422,7 +423,8 @@ class GoogleCloudOutputGRPCTest < Test::Unit::TestCase
|
|
422
423
|
'logName' => request.log_name
|
423
424
|
}
|
424
425
|
end
|
425
|
-
verify_json_log_entries(n, params, payload_type,
|
426
|
+
verify_json_log_entries(n, params, payload_type, check_exact_entry_labels,
|
427
|
+
&block)
|
426
428
|
end
|
427
429
|
|
428
430
|
# Use the right single quotation mark as the sample non-utf8 character.
|
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.7.
|
4
|
+
version: 0.7.5.pre.multiworkers
|
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: 2019-02-
|
11
|
+
date: 2019-02-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -218,9 +218,7 @@ extensions: []
|
|
218
218
|
extra_rdoc_files: []
|
219
219
|
files:
|
220
220
|
- CONTRIBUTING
|
221
|
-
- CUSTOM_SPONGE_CONFIG
|
222
221
|
- Gemfile
|
223
|
-
- Gemfile.lock
|
224
222
|
- LICENSE
|
225
223
|
- README.rdoc
|
226
224
|
- Rakefile
|
@@ -255,12 +253,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
255
253
|
version: '2.2'
|
256
254
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
257
255
|
requirements:
|
258
|
-
- - "
|
256
|
+
- - ">"
|
259
257
|
- !ruby/object:Gem::Version
|
260
|
-
version:
|
258
|
+
version: 1.3.1
|
261
259
|
requirements: []
|
262
260
|
rubyforge_project:
|
263
|
-
rubygems_version: 2.
|
261
|
+
rubygems_version: 2.6.14
|
264
262
|
signing_key:
|
265
263
|
specification_version: 4
|
266
264
|
summary: fluentd plugins for the Stackdriver Logging API
|
data/CUSTOM_SPONGE_CONFIG
DELETED
File without changes
|
data/Gemfile.lock
DELETED
@@ -1,160 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
fluent-plugin-google-cloud (0.7.4)
|
5
|
-
fluentd (= 1.2.5)
|
6
|
-
google-api-client (= 0.23.9)
|
7
|
-
google-cloud-logging (= 1.5.4)
|
8
|
-
google-protobuf (= 3.6.1)
|
9
|
-
googleapis-common-protos (= 1.3.7)
|
10
|
-
googleauth (= 0.6.6)
|
11
|
-
grpc (= 1.8.3)
|
12
|
-
json (= 2.1.0)
|
13
|
-
|
14
|
-
GEM
|
15
|
-
remote: https://rubygems.org/
|
16
|
-
specs:
|
17
|
-
addressable (2.6.0)
|
18
|
-
public_suffix (>= 2.0.2, < 4.0)
|
19
|
-
ast (2.4.0)
|
20
|
-
cool.io (1.5.3)
|
21
|
-
crack (0.4.3)
|
22
|
-
safe_yaml (~> 1.0.0)
|
23
|
-
declarative (0.0.10)
|
24
|
-
declarative-option (0.1.0)
|
25
|
-
dig_rb (1.0.1)
|
26
|
-
faraday (0.15.4)
|
27
|
-
multipart-post (>= 1.2, < 3)
|
28
|
-
fluentd (1.2.5)
|
29
|
-
cool.io (>= 1.4.5, < 2.0.0)
|
30
|
-
dig_rb (~> 1.0.0)
|
31
|
-
http_parser.rb (>= 0.5.1, < 0.7.0)
|
32
|
-
msgpack (>= 0.7.0, < 2.0.0)
|
33
|
-
serverengine (>= 2.0.4, < 3.0.0)
|
34
|
-
sigdump (~> 0.2.2)
|
35
|
-
strptime (>= 0.2.2, < 1.0.0)
|
36
|
-
tzinfo (~> 1.0)
|
37
|
-
tzinfo-data (~> 1.0)
|
38
|
-
yajl-ruby (~> 1.0)
|
39
|
-
google-api-client (0.23.9)
|
40
|
-
addressable (~> 2.5, >= 2.5.1)
|
41
|
-
googleauth (>= 0.5, < 0.7.0)
|
42
|
-
httpclient (>= 2.8.1, < 3.0)
|
43
|
-
mime-types (~> 3.0)
|
44
|
-
representable (~> 3.0)
|
45
|
-
retriable (>= 2.0, < 4.0)
|
46
|
-
signet (~> 0.9)
|
47
|
-
google-cloud-core (1.3.0)
|
48
|
-
google-cloud-env (~> 1.0)
|
49
|
-
google-cloud-env (1.0.5)
|
50
|
-
faraday (~> 0.11)
|
51
|
-
google-cloud-logging (1.5.4)
|
52
|
-
google-cloud-core (~> 1.2)
|
53
|
-
google-gax (~> 1.3)
|
54
|
-
googleapis-common-protos-types (>= 1.0.2)
|
55
|
-
stackdriver-core (~> 1.3)
|
56
|
-
google-gax (1.5.0)
|
57
|
-
google-protobuf (~> 3.2)
|
58
|
-
googleapis-common-protos (>= 1.3.5, < 2.0)
|
59
|
-
googleauth (>= 0.6.2, < 0.10.0)
|
60
|
-
grpc (>= 1.7.2, < 2.0)
|
61
|
-
rly (~> 0.2.3)
|
62
|
-
google-protobuf (3.6.1)
|
63
|
-
googleapis-common-protos (1.3.7)
|
64
|
-
google-protobuf (~> 3.0)
|
65
|
-
googleapis-common-protos-types (~> 1.0)
|
66
|
-
grpc (~> 1.0)
|
67
|
-
googleapis-common-protos-types (1.0.2)
|
68
|
-
google-protobuf (~> 3.0)
|
69
|
-
googleauth (0.6.6)
|
70
|
-
faraday (~> 0.12)
|
71
|
-
jwt (>= 1.4, < 3.0)
|
72
|
-
memoist (~> 0.12)
|
73
|
-
multi_json (~> 1.11)
|
74
|
-
os (>= 0.9, < 2.0)
|
75
|
-
signet (~> 0.7)
|
76
|
-
grpc (1.8.3)
|
77
|
-
google-protobuf (~> 3.1)
|
78
|
-
googleapis-common-protos-types (~> 1.0.0)
|
79
|
-
googleauth (>= 0.5.1, < 0.7)
|
80
|
-
hashdiff (0.3.8)
|
81
|
-
http_parser.rb (0.6.0)
|
82
|
-
httpclient (2.8.3)
|
83
|
-
json (2.1.0)
|
84
|
-
jwt (2.1.0)
|
85
|
-
memoist (0.16.0)
|
86
|
-
metaclass (0.0.4)
|
87
|
-
mime-types (3.2.2)
|
88
|
-
mime-types-data (~> 3.2015)
|
89
|
-
mime-types-data (3.2018.0812)
|
90
|
-
mocha (1.8.0)
|
91
|
-
metaclass (~> 0.0.1)
|
92
|
-
msgpack (1.2.6)
|
93
|
-
multi_json (1.13.1)
|
94
|
-
multipart-post (2.0.0)
|
95
|
-
os (1.0.0)
|
96
|
-
parser (2.6.0.0)
|
97
|
-
ast (~> 2.4.0)
|
98
|
-
power_assert (1.1.3)
|
99
|
-
powerpack (0.1.2)
|
100
|
-
prometheus-client (0.7.1)
|
101
|
-
quantile (~> 0.2.0)
|
102
|
-
public_suffix (3.0.3)
|
103
|
-
quantile (0.2.1)
|
104
|
-
rainbow (2.2.2)
|
105
|
-
rake
|
106
|
-
rake (10.5.0)
|
107
|
-
representable (3.0.4)
|
108
|
-
declarative (< 0.1.0)
|
109
|
-
declarative-option (< 0.2.0)
|
110
|
-
uber (< 0.2.0)
|
111
|
-
retriable (3.1.2)
|
112
|
-
rly (0.2.3)
|
113
|
-
rubocop (0.39.0)
|
114
|
-
parser (>= 2.3.0.7, < 3.0)
|
115
|
-
powerpack (~> 0.1)
|
116
|
-
rainbow (>= 1.99.1, < 3.0)
|
117
|
-
ruby-progressbar (~> 1.7)
|
118
|
-
unicode-display_width (~> 1.0, >= 1.0.1)
|
119
|
-
ruby-progressbar (1.10.0)
|
120
|
-
safe_yaml (1.0.4)
|
121
|
-
serverengine (2.1.0)
|
122
|
-
sigdump (~> 0.2.2)
|
123
|
-
sigdump (0.2.4)
|
124
|
-
signet (0.11.0)
|
125
|
-
addressable (~> 2.3)
|
126
|
-
faraday (~> 0.9)
|
127
|
-
jwt (>= 1.5, < 3.0)
|
128
|
-
multi_json (~> 1.10)
|
129
|
-
stackdriver-core (1.3.3)
|
130
|
-
google-cloud-core (~> 1.2)
|
131
|
-
strptime (0.2.3)
|
132
|
-
test-unit (3.3.0)
|
133
|
-
power_assert
|
134
|
-
thread_safe (0.3.6)
|
135
|
-
tzinfo (1.2.5)
|
136
|
-
thread_safe (~> 0.1)
|
137
|
-
tzinfo-data (1.2018.9)
|
138
|
-
tzinfo (>= 1.0.0)
|
139
|
-
uber (0.1.0)
|
140
|
-
unicode-display_width (1.4.1)
|
141
|
-
webmock (2.3.2)
|
142
|
-
addressable (>= 2.3.6)
|
143
|
-
crack (>= 0.3.2)
|
144
|
-
hashdiff
|
145
|
-
yajl-ruby (1.4.1)
|
146
|
-
|
147
|
-
PLATFORMS
|
148
|
-
ruby
|
149
|
-
|
150
|
-
DEPENDENCIES
|
151
|
-
fluent-plugin-google-cloud!
|
152
|
-
mocha (~> 1.1)
|
153
|
-
prometheus-client (~> 0.7.1)
|
154
|
-
rake (~> 10.3)
|
155
|
-
rubocop (~> 0.39.0)
|
156
|
-
test-unit (~> 3.0)
|
157
|
-
webmock (~> 2.3.1)
|
158
|
-
|
159
|
-
BUNDLED WITH
|
160
|
-
1.16.6
|