fluent-plugin-google-cloud 0.6.25.1 → 0.7.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bb53a82f49086e32adb57a617f0ad53812493815
4
- data.tar.gz: 6964a23f146726e01f71a74378c0fa4327c5b582
3
+ metadata.gz: 5fa418888cc895f5387d6d03b60154d4940a07d7
4
+ data.tar.gz: 06ecdf13e10c1262dabf80aedff34af14d132656
5
5
  SHA512:
6
- metadata.gz: a9074434a1978f326a44fc4651d692a1e0f524c6c8ddeebda4efe89968059df9289749f21d85983a5308ee8629a208fb3963974ac234e8462a85a5c48aab94cb
7
- data.tar.gz: 57e333f19ca5a7e5a9dbd2bd4b4bb65e461222bde2036b9a98a0e99ed2d95159d690c718b2b6bf95fe208dbbea2c7d5c1147a68b7d2dc39ff7f7dbfed1909664
6
+ metadata.gz: e8c1e36fdb141fc017340abcc27c39dd9989e1bda2a9dd16fdd77d8596f3b68203a022b4c221de35240546117f9ad78e67c8ed3dcf570804c62bb9459cd6676d
7
+ data.tar.gz: 1b4cc062cfbfe10db494c3ecb52499df5f5a52f204e863723f1212b72e61ac89d1a137039af4f7ea3d293a50c9f9eb14d043b22dfe1ef293fb888c7b4fc0da48
data/README.rdoc CHANGED
@@ -1,10 +1,9 @@
1
1
  = Google Cloud Logging plugin for {fluentd}[http://github.com/fluent/fluentd]
2
2
 
3
- fluent-plugin-google-cloud gem includes two plugins:
4
- 1. A {filter plugin for fluentd}[http://docs.fluentd.org/articles/filter-plugin-overview]
5
- that embeds insertIds into log entries to guarantee order and uniqueness.
6
- 2. An {output plugin for fluentd}[http://docs.fluentd.org/articles/output-plugin-overview]
7
- which sends logs to the {Stackdriver Logging API}[https://cloud.google.com/logging/docs/api/].
3
+ fluent-plugin-google-cloud is an
4
+ {output plugin for fluentd}[http://docs.fluentd.org/articles/output-plugin-overview]
5
+ which sends logs to the
6
+ {Stackdriver Logging API}[https://cloud.google.com/logging/docs/api/].
8
7
 
9
8
  This is an official Google Ruby gem.
10
9
 
@@ -13,7 +12,8 @@ This is an official Google Ruby gem.
13
12
 
14
13
  == Installation
15
14
 
16
- This gem is hosted at {RubyGems.org}[https://rubygems.org/gems/fluent-plugin-google-cloud]
15
+ This gem is hosted at
16
+ {RubyGems.org}[https://rubygems.org/gems/fluent-plugin-google-cloud]
17
17
  and can be installed using:
18
18
 
19
19
  $ gem install fluent-plugin-google-cloud
@@ -23,31 +23,22 @@ will also install and configure the gem.
23
23
 
24
24
  == Configuration
25
25
 
26
- To embed insertIds into log entries, specify <code>@type add_insert_ids</code>
27
- in a {filter clause}[https://docs.fluentd.org/v1.0/articles/config-file#(3)-%E2%80%9Cfilter%E2%80%9D:-event-processing-pipeline]
28
- of your Fluentd configuration file, for example:
29
-
30
- <filter **>
31
- @type add_insert_ids
32
- insert_id_key my_insert_id_field_name # Optional.
33
- </filter>
34
-
35
- insert_id_key can be used to customize the insertId field name.
36
-
37
- To send logs to Google Cloud Logging, specify <code>@type google_cloud</code>
38
- in a {match clause}[http://docs.fluentd.org/articles/config-file#2-ldquomatchrdquo-tell-fluentd-what-to-do]
39
- of your Fluentd configuration file, for example:
26
+ To send logs to Google Cloud Logging, specify <code>type google_cloud</code>
27
+ in a
28
+ {match clause}[http://docs.fluentd.org/articles/config-file#2-ldquomatchrdquo-tell-fluentd-what-to-do]
29
+ of your fluentd configuration file, for example:
40
30
 
41
31
  <match **>
42
- @type google_cloud
32
+ type google_cloud
43
33
  </match>
44
34
 
45
- See detailed instructions on how to configure this output plugin {here}[https://cloud.google.com/logging/docs/agent/configuration#cloud-fluentd-config].
46
- The plugin uses
35
+ No further configuration is required. The plugin uses
47
36
  {Google Application Default Credentials}[https://developers.google.com/identity/protocols/application-default-credentials]
48
- for authorization - for additional information see
37
+ for authorization - for additional information see
49
38
  {here}[https://cloud.google.com/logging/docs/agent/authorization].
50
39
 
40
+ <em>The previously documented parameters auth_method, private_key_email,
41
+ and private_key_path are removed, and can no longer be used.</em>
51
42
 
52
43
  == Copyright
53
44
 
data/Rakefile CHANGED
@@ -21,7 +21,8 @@ end
21
21
  desc 'Fix file permissions'
22
22
  task :fix_perms do
23
23
  files = [
24
- 'lib/fluent/plugin/*.rb',
24
+ 'lib/fluent/plugin/out_google_cloud.rb',
25
+ 'lib/fluent/plugin/monitoring.rb',
25
26
  'lib/google/**/*.rb'
26
27
  ].flat_map do |file|
27
28
  file.include?('*') ? Dir.glob(file) : [file]
@@ -1,17 +1,17 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'fluent-plugin-google-cloud'
3
3
  gem.description = <<-eos
4
- Fluentd plugins for the Stackdriver Logging API, which will make logs
5
- viewable in the Stackdriver Logs Viewer and can optionally store them
6
- in Google Cloud Storage and/or BigQuery.
4
+ Fluentd output plugin for the Stackdriver Logging API, which will make
5
+ logs viewable in the Developer Console's log viewer and can optionally
6
+ store them in Google Cloud Storage and/or BigQuery.
7
7
  This is an official Google Ruby gem.
8
8
  eos
9
- gem.summary = 'fluentd plugins for the Stackdriver Logging API'
9
+ gem.summary = 'fluentd output plugin for the Stackdriver Logging API'
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.6.25.1'
14
- gem.authors = ['Stackdriver Agents Team']
13
+ gem.version = '0.7.0.pre.1'
14
+ gem.authors = ['Ling Huang', 'Igor Peshansky']
15
15
  gem.email = ['stackdriver-agents@google.com']
16
16
  gem.required_ruby_version = Gem::Requirement.new('>= 2.2')
17
17
 
@@ -19,13 +19,13 @@ eos
19
19
  gem.test_files = gem.files.grep(/^(test)/)
20
20
  gem.require_paths = ['lib']
21
21
 
22
- gem.add_runtime_dependency 'fluentd', '~> 0.10'
22
+ gem.add_runtime_dependency 'fluentd', '~> 1.2.5'
23
23
  gem.add_runtime_dependency 'googleapis-common-protos', '~> 1.3'
24
24
  gem.add_runtime_dependency 'google-api-client', '~> 0.17'
25
25
  gem.add_runtime_dependency 'google-cloud-logging', '~> 1.3', '>= 1.3.2'
26
26
  gem.add_runtime_dependency 'googleauth', '~> 0.6'
27
27
  gem.add_runtime_dependency 'grpc', '~> 1.0'
28
- gem.add_runtime_dependency 'json', '~> 2.1'
28
+ gem.add_runtime_dependency 'json', '~> 1.8'
29
29
  gem.add_runtime_dependency 'google-protobuf', '~> 3.6', '>= 3.6.1'
30
30
 
31
31
  gem.add_development_dependency 'mocha', '~> 1.1'
@@ -86,7 +86,7 @@ module Fluent
86
86
  resource_type: 'container',
87
87
  extra_resource_labels: %w(namespace_id pod_id container_name),
88
88
  extra_common_labels: %w(namespace_name pod_name),
89
- metadata_attributes: %w(cluster-name cluster-location),
89
+ metadata_attributes: %w(kube-env),
90
90
  stream_severity_map: {
91
91
  'stdout' => 'INFO',
92
92
  'stderr' => 'ERROR'
@@ -228,16 +228,7 @@ module Fluent
228
228
  Fluent::Plugin.register_output('google_cloud', self)
229
229
 
230
230
  PLUGIN_NAME = 'Fluentd Google Cloud Logging plugin'.freeze
231
- # Extract plugin version by finding the spec this file was loaded from.
232
- PLUGIN_VERSION = begin
233
- dependency = Gem::Dependency.new('fluent-plugin-google-cloud')
234
- all_specs, = Gem::SpecFetcher.fetcher.spec_for_dependency(dependency)
235
- matching_spec, = all_specs.grep(
236
- proc { |spec,| __FILE__.include?(spec.full_gem_path) }) do |spec,|
237
- spec.version.to_s
238
- end
239
- matching_spec
240
- end.freeze
231
+ PLUGIN_VERSION = '0.7.0.pre.1'.freeze
241
232
 
242
233
  # Name of the the Google cloud logging write scope.
243
234
  LOGGING_SCOPE = 'https://www.googleapis.com/auth/logging.write'.freeze
@@ -550,12 +541,10 @@ module Fluent
550
541
  @write_request = method(:write_request_via_rest)
551
542
  end
552
543
 
553
- if [Platform::GCE, Platform::EC2].include?(@platform)
554
- # Log an informational message containing the Logs viewer URL
555
- @log.info 'Logs viewer address: https://console.cloud.google.com/logs/',
556
- "viewer?project=#{@project_id}&resource=#{@resource.type}/",
557
- "instance_id/#{@vm_id}"
558
- end
544
+ # Log an informational message containing the Logs viewer URL
545
+ @log.info 'Logs viewer address: https://console.cloud.google.com/logs/',
546
+ "viewer?project=#{@project_id}&resource=#{@resource.type}/",
547
+ "instance_id/#{@vm_id}"
559
548
  end
560
549
 
561
550
  def start
@@ -586,17 +575,16 @@ module Fluent
586
575
 
587
576
  is_json = false
588
577
  if @detect_json
589
- # Save the following fields if available, then clear them out to
578
+ # Save the timestamp and severity if available, then clear it out to
590
579
  # allow for determining whether we should parse the log or message
591
580
  # field.
592
- preserved_keys = [
593
- 'time', 'severity', @trace_key, @span_id_key, @insert_id_key
594
- ]
581
+ timestamp = record.delete('time')
582
+ severity = record.delete('severity')
595
583
 
596
584
  # If the log is json, we want to export it as a structured log
597
585
  # unless there is additional metadata that would be lost.
598
586
  record_json = nil
599
- if (record.keys - preserved_keys).length == 1
587
+ if record.length == 1
600
588
  %w(log message msg).each do |field|
601
589
  if record.key?(field)
602
590
  record_json = parse_json_or_nil(record[field])
@@ -604,15 +592,13 @@ module Fluent
604
592
  end
605
593
  end
606
594
  unless record_json.nil?
607
- # Propagate these if necessary. Note that we don't want to
608
- # override these keys in the JSON we've just parsed.
609
- preserved_keys.each do |key|
610
- record_json[key] ||= record[key] if record.key?(key)
611
- end
612
-
613
595
  record = record_json
614
596
  is_json = true
615
597
  end
598
+ # Restore timestamp and severity if necessary. Note that we don't
599
+ # want to override these keys in the JSON we've just parsed.
600
+ record['time'] ||= timestamp if timestamp
601
+ record['severity'] ||= severity if severity
616
602
  end
617
603
 
618
604
  ts_secs, ts_nanos = compute_timestamp(
@@ -626,10 +612,13 @@ module Fluent
626
612
  ts_secs,
627
613
  ts_nanos)
628
614
 
629
- trace = record.delete(@trace_key)
630
- entry.trace = trace if trace
615
+ # Get fully-qualified trace id for LogEntry "trace" field.
616
+ fq_trace_id = record.delete(@trace_key)
617
+ entry.trace = fq_trace_id if fq_trace_id
618
+
631
619
  span_id = record.delete(@span_id_key)
632
620
  entry.span_id = span_id if span_id
621
+
633
622
  insert_id = record.delete(@insert_id_key)
634
623
  entry.insert_id = insert_id if insert_id
635
624
 
@@ -1029,10 +1018,8 @@ module Fluent
1029
1018
  # All metadata parameters must now be set.
1030
1019
  missing = []
1031
1020
  missing << 'project_id' unless @project_id
1032
- if @platform != Platform::OTHER
1033
- missing << 'zone' unless @zone
1034
- missing << 'vm_id' unless @vm_id
1035
- end
1021
+ missing << 'zone' unless @zone
1022
+ missing << 'vm_id' unless @vm_id
1036
1023
  return if missing.empty?
1037
1024
  raise Fluent::ConfigError,
1038
1025
  "Unable to obtain metadata parameters: #{missing.join(' ')}"
@@ -1148,11 +1135,12 @@ module Fluent
1148
1135
 
1149
1136
  # GKE container.
1150
1137
  when GKE_CONSTANTS[:resource_type]
1138
+ raw_kube_env = fetch_gce_metadata('instance/attributes/kube-env')
1139
+ kube_env = YAML.load(raw_kube_env)
1151
1140
  return {
1152
1141
  'instance_id' => @vm_id,
1153
1142
  'zone' => @zone,
1154
- 'cluster_name' =>
1155
- fetch_gce_metadata('instance/attributes/cluster-name')
1143
+ 'cluster_name' => cluster_name_from_kube_env(kube_env)
1156
1144
  }
1157
1145
 
1158
1146
  # Cloud Dataproc.
@@ -1534,6 +1522,15 @@ module Fluent
1534
1522
  end
1535
1523
  end
1536
1524
 
1525
+ def cluster_name_from_kube_env(kube_env)
1526
+ return kube_env['CLUSTER_NAME'] if kube_env.key?('CLUSTER_NAME')
1527
+ instance_prefix = kube_env['INSTANCE_PREFIX']
1528
+ gke_name_match = /^gke-(.+)-[0-9a-f]{8}$/.match(instance_prefix)
1529
+ return gke_name_match.captures[0] if gke_name_match &&
1530
+ !gke_name_match.captures.empty?
1531
+ instance_prefix
1532
+ end
1533
+
1537
1534
  def time_or_nil(ts_secs, ts_nanos)
1538
1535
  Time.at((Integer ts_secs), (Integer ts_nanos) / 1_000.0)
1539
1536
  rescue ArgumentError, TypeError
@@ -81,27 +81,26 @@ module BaseTest
81
81
  assert_equal CUSTOM_VM_ID, d.instance.vm_id
82
82
  end
83
83
 
84
- def test_configure_metadata_missing_parts_on_other_platforms
84
+ def test_configure_invalid_metadata_missing_parts
85
85
  setup_no_metadata_service_stubs
86
86
  Fluent::GoogleCloudOutput::CredentialsInfo.stubs(:project_id).returns(nil)
87
- [[CONFIG_MISSING_METADATA_PROJECT_ID, ['project_id'], false],
88
- [CONFIG_MISSING_METADATA_ZONE, [], true],
89
- [CONFIG_MISSING_METADATA_VM_ID, [], true],
90
- [CONFIG_MISSING_METADATA_ALL, ['project_id'], false]
91
- ].each_with_index do |(config, missing_parts, is_valid_config), index|
87
+ { CONFIG_MISSING_METADATA_PROJECT_ID => ['project_id'],
88
+ CONFIG_MISSING_METADATA_ZONE => ['zone'],
89
+ CONFIG_MISSING_METADATA_VM_ID => ['vm_id'],
90
+ CONFIG_MISSING_METADATA_ALL => %w(project_id zone vm_id)
91
+ }.each_with_index do |(config, parts), index|
92
+ exception_count = 0
92
93
  begin
93
94
  create_driver(config)
94
- assert_true is_valid_config, "Invalid config at index #{index} should "\
95
- 'have raised an error.'
96
95
  rescue Fluent::ConfigError => error
97
- assert_false is_valid_config, "Valid config at index #{index} should "\
98
- "not have raised an error #{error}."
99
96
  assert error.message.include?('Unable to obtain metadata parameters:'),
100
97
  "Index #{index} failed."
101
- missing_parts.each do |part|
98
+ parts.each do |part|
102
99
  assert error.message.include?(part), "Index #{index} failed."
103
100
  end
101
+ exception_count += 1
104
102
  end
103
+ assert_equal 1, exception_count, "Index #{index} failed."
105
104
  end
106
105
  end
107
106
 
@@ -180,7 +179,7 @@ module BaseTest
180
179
  setup_gce_metadata_stubs
181
180
  # This would cause the resource type to be container.googleapis.com if not
182
181
  # for the detect_subservice=false config.
183
- setup_k8s_metadata_stubs
182
+ setup_container_metadata_stubs
184
183
  d = create_driver(NO_DETECT_SUBSERVICE_CONFIG)
185
184
  d.run
186
185
  assert_equal COMPUTE_CONSTANTS[:resource_type], d.instance.resource.type
@@ -468,7 +467,7 @@ module BaseTest
468
467
 
469
468
  def test_structured_payload_json_log_default_container_not_parsed
470
469
  setup_gce_metadata_stubs
471
- setup_k8s_metadata_stubs
470
+ setup_container_metadata_stubs
472
471
  json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
473
472
  '"data": 5000, "some_null_field": null}'
474
473
  setup_logging_stubs do
@@ -485,7 +484,7 @@ module BaseTest
485
484
 
486
485
  def test_structured_payload_json_log_detect_json_container_not_parsed
487
486
  setup_gce_metadata_stubs
488
- setup_k8s_metadata_stubs
487
+ setup_container_metadata_stubs
489
488
  json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
490
489
  '"data": 5000, "some_null_field": null}'
491
490
  setup_logging_stubs do
@@ -500,7 +499,7 @@ module BaseTest
500
499
 
501
500
  def test_structured_payload_json_log_detect_json_container_parsed
502
501
  setup_gce_metadata_stubs
503
- setup_k8s_metadata_stubs
502
+ setup_container_metadata_stubs
504
503
  json_string = '{"msg": "test log entry 0", "tag2": "test", ' \
505
504
  '"data": 5000, "some_null_field": null}'
506
505
  setup_logging_stubs do
@@ -539,7 +538,7 @@ module BaseTest
539
538
  # match, thus the original tag is used as the log name.
540
539
  def test_handle_empty_container_name
541
540
  setup_gce_metadata_stubs
542
- setup_k8s_metadata_stubs
541
+ setup_container_metadata_stubs
543
542
  container_name = ''
544
543
  # This tag will not match the kubernetes regex because it requires a
545
544
  # non-empty container name.
@@ -561,7 +560,7 @@ module BaseTest
561
560
  # 'require_valid_tags' is true.
562
561
  def test_reject_non_utf8_container_name_with_require_valid_tags_true
563
562
  setup_gce_metadata_stubs
564
- setup_k8s_metadata_stubs
563
+ setup_container_metadata_stubs
565
564
  non_utf8_tags = INVALID_TAGS.select do |tag, _|
566
565
  tag.is_a?(String) && !tag.empty?
567
566
  end
@@ -601,7 +600,7 @@ module BaseTest
601
600
  # Verify that tags extracted from container names are properly encoded.
602
601
  def test_encode_tags_from_container_name_with_require_valid_tags_true
603
602
  setup_gce_metadata_stubs
604
- setup_k8s_metadata_stubs
603
+ setup_container_metadata_stubs
605
604
  VALID_TAGS.each do |tag, encoded_tag|
606
605
  setup_logging_stubs do
607
606
  @logs_sent = []
@@ -640,7 +639,7 @@ module BaseTest
640
639
  # sanitized.
641
640
  def test_sanitize_tags_from_container_name_with_require_valid_tags_false
642
641
  setup_gce_metadata_stubs
643
- setup_k8s_metadata_stubs
642
+ setup_container_metadata_stubs
644
643
  # Log names are derived from container names for containers. And container
645
644
  # names are extracted from the tag based on a regex match pattern. As a
646
645
  # prerequisite, the tag should already be a string, thus we only test
@@ -969,7 +968,7 @@ module BaseTest
969
968
 
970
969
  def test_one_container_log_from_tag_stderr
971
970
  setup_gce_metadata_stubs
972
- setup_k8s_metadata_stubs
971
+ setup_container_metadata_stubs
973
972
  setup_logging_stubs do
974
973
  d = create_driver(APPLICATION_DEFAULT_CONFIG, CONTAINER_TAG)
975
974
  d.emit(container_log_entry(log_entry(0), 'stderr'))
@@ -980,15 +979,15 @@ module BaseTest
980
979
  ) { |_, oldval, newval| oldval.merge(newval) }
981
980
  verify_log_entries(1, expected_params) do |entry, i|
982
981
  verify_default_log_entry_text(entry['textPayload'], i, entry)
983
- assert_equal K8S_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
984
- assert_equal K8S_NANOS, entry['timestamp']['nanos'], entry
982
+ assert_equal CONTAINER_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
983
+ assert_equal CONTAINER_NANOS, entry['timestamp']['nanos'], entry
985
984
  assert_equal 'ERROR', entry['severity'], entry
986
985
  end
987
986
  end
988
987
 
989
988
  def test_json_container_log_metadata_from_plugin
990
989
  setup_gce_metadata_stubs
991
- setup_k8s_metadata_stubs
990
+ setup_container_metadata_stubs
992
991
  setup_logging_stubs do
993
992
  d = create_driver(DETECT_JSON_CONFIG, CONTAINER_TAG)
994
993
  d.emit(container_log_entry_with_metadata('{"msg": "test log entry 0", ' \
@@ -1003,15 +1002,15 @@ module BaseTest
1003
1002
  assert_equal 'test log entry 0', get_string(fields['msg']), entry
1004
1003
  assert_equal 'test', get_string(fields['tag2']), entry
1005
1004
  assert_equal 5000, get_number(fields['data']), entry
1006
- assert_equal K8S_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
1007
- assert_equal K8S_NANOS, entry['timestamp']['nanos'], entry
1005
+ assert_equal CONTAINER_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
1006
+ assert_equal CONTAINER_NANOS, entry['timestamp']['nanos'], entry
1008
1007
  assert_equal 'WARNING', entry['severity'], entry
1009
1008
  end
1010
1009
  end
1011
1010
 
1012
1011
  def test_json_container_log_metadata_from_tag
1013
1012
  setup_gce_metadata_stubs
1014
- setup_k8s_metadata_stubs
1013
+ setup_container_metadata_stubs
1015
1014
  setup_logging_stubs do
1016
1015
  d = create_driver(DETECT_JSON_CONFIG, CONTAINER_TAG)
1017
1016
  d.emit(container_log_entry('{"msg": "test log entry 0", ' \
@@ -1026,8 +1025,8 @@ module BaseTest
1026
1025
  assert_equal 'test log entry 0', get_string(fields['msg']), entry
1027
1026
  assert_equal 'test', get_string(fields['tag2']), entry
1028
1027
  assert_equal 5000, get_number(fields['data']), entry
1029
- assert_equal K8S_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
1030
- assert_equal K8S_NANOS, entry['timestamp']['nanos'], entry
1028
+ assert_equal CONTAINER_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
1029
+ assert_equal CONTAINER_NANOS, entry['timestamp']['nanos'], entry
1031
1030
  assert_equal 'WARNING', entry['severity'], entry
1032
1031
  end
1033
1032
  end
@@ -1222,32 +1221,18 @@ module BaseTest
1222
1221
 
1223
1222
  def test_log_entry_trace_field
1224
1223
  verify_field_key('trace', DEFAULT_TRACE_KEY, 'custom_trace_key',
1225
- CONFIG_CUSTOM_TRACE_KEY_SPECIFIED, TRACE)
1224
+ CONFIG_CUSTOM_TRACE_KEY_SPECIFIED,
1225
+ 'projects/proj1/traces/1234567890abcdef1234567890abcdef')
1226
1226
  end
1227
1227
 
1228
1228
  def test_log_entry_span_id_field
1229
1229
  verify_field_key('spanId', DEFAULT_SPAN_ID_KEY, 'custom_span_id_key',
1230
- CONFIG_CUSTOM_SPAN_ID_KEY_SPECIFIED, SPAN_ID)
1230
+ CONFIG_CUSTOM_SPAN_ID_KEY_SPECIFIED, '000000000000004a')
1231
1231
  end
1232
1232
 
1233
1233
  def test_log_entry_insert_id_field
1234
1234
  verify_field_key('insertId', DEFAULT_INSERT_ID_KEY, 'custom_insert_id_key',
1235
- CONFIG_CUSTOM_INSERT_ID_KEY_SPECIFIED, INSERT_ID)
1236
- end
1237
-
1238
- def test_cascading_json_detection_with_log_entry_trace_field
1239
- verify_cascading_json_detection_with_log_entry_fields(
1240
- 'trace', DEFAULT_TRACE_KEY, TRACE, TRACE2)
1241
- end
1242
-
1243
- def test_cascading_json_detection_with_log_entry_span_id_field
1244
- verify_cascading_json_detection_with_log_entry_fields(
1245
- 'spanId', DEFAULT_SPAN_ID_KEY, SPAN_ID, SPAN_ID2)
1246
- end
1247
-
1248
- def test_cascading_json_detection_with_log_entry_insert_id_field
1249
- verify_cascading_json_detection_with_log_entry_fields(
1250
- 'insertId', DEFAULT_INSERT_ID_KEY, INSERT_ID, INSERT_ID2)
1235
+ CONFIG_CUSTOM_INSERT_ID_KEY_SPECIFIED, 'fah7yr7iw64tg857y')
1251
1236
  end
1252
1237
 
1253
1238
  # Metadata Agent related tests.
@@ -1340,24 +1325,25 @@ module BaseTest
1340
1325
  end
1341
1326
  end
1342
1327
 
1343
- # Test k8s_container monitored resource including the fallback when Metadata
1344
- # Agent restarts.
1345
- def test_k8s_container_monitored_resource_fallback
1328
+ # Test k8s monitored resource including the fallback when Metadata Agent
1329
+ # restarts.
1330
+ def test_k8s_monitored_resource_fallback
1346
1331
  [
1332
+ # k8s_container.
1347
1333
  # When enable_metadata_agent is false.
1348
1334
  {
1349
1335
  config: APPLICATION_DEFAULT_CONFIG,
1350
1336
  setup_metadata_agent_stub: false,
1351
1337
  setup_k8s_stub: false,
1352
1338
  log_entry: k8s_container_log_entry(log_entry(0)),
1353
- expected_params: K8S_CONTAINER_PARAMS_FROM_FALLBACK
1339
+ expected_params: COMPUTE_PARAMS
1354
1340
  },
1355
1341
  {
1356
1342
  config: APPLICATION_DEFAULT_CONFIG,
1357
1343
  setup_metadata_agent_stub: true,
1358
1344
  setup_k8s_stub: false,
1359
1345
  log_entry: k8s_container_log_entry(log_entry(0)),
1360
- expected_params: K8S_CONTAINER_PARAMS_FROM_FALLBACK
1346
+ expected_params: COMPUTE_PARAMS
1361
1347
  },
1362
1348
  {
1363
1349
  config: APPLICATION_DEFAULT_CONFIG,
@@ -1379,7 +1365,7 @@ module BaseTest
1379
1365
  setup_metadata_agent_stub: false,
1380
1366
  setup_k8s_stub: false,
1381
1367
  log_entry: k8s_container_log_entry(log_entry(0)),
1382
- expected_params: K8S_CONTAINER_PARAMS_FROM_FALLBACK
1368
+ expected_params: COMPUTE_PARAMS
1383
1369
  },
1384
1370
  {
1385
1371
  config: ENABLE_METADATA_AGENT_CONFIG,
@@ -1415,30 +1401,7 @@ module BaseTest
1415
1401
  setup_k8s_stub: true,
1416
1402
  log_entry: k8s_container_log_entry(log_entry(0)),
1417
1403
  expected_params: K8S_CONTAINER_PARAMS
1418
- }
1419
- ].each do |test_params|
1420
- new_stub_context do
1421
- setup_gce_metadata_stubs
1422
- setup_metadata_agent_stubs(test_params[:setup_metadata_agent_stub])
1423
- setup_k8s_metadata_stubs(test_params[:setup_k8s_stub])
1424
- setup_logging_stubs do
1425
- d = create_driver(test_params[:config], CONTAINER_TAG)
1426
- d.emit(test_params[:log_entry])
1427
- d.run
1428
- end
1429
- verify_log_entries(1, test_params[:expected_params],
1430
- 'jsonPayload') do |entry|
1431
- fields = get_fields(entry['jsonPayload'])
1432
- assert_equal 2, fields.size, entry
1433
- assert_equal 'test log entry 0', get_string(fields['log']), entry
1434
- assert_equal K8S_STREAM, get_string(fields['stream']), entry
1435
- end
1436
- end
1437
- end
1438
- end
1439
-
1440
- def test_k8s_container_monitored_resource_invalid_local_resource_id
1441
- [
1404
+ },
1442
1405
  # When local_resource_id is not present or does not match k8s regexes.
1443
1406
  {
1444
1407
  config: ENABLE_METADATA_AGENT_CONFIG,
@@ -1446,7 +1409,7 @@ module BaseTest
1446
1409
  setup_k8s_stub: true,
1447
1410
  log_entry: k8s_container_log_entry(
1448
1411
  log_entry(0)).reject { |k, _| k == LOCAL_RESOURCE_ID_KEY },
1449
- expected_params: CONTAINER_FROM_TAG_PARAMS
1412
+ expected_params: COMPUTE_PARAMS
1450
1413
  },
1451
1414
  {
1452
1415
  config: ENABLE_METADATA_AGENT_CONFIG,
@@ -1455,29 +1418,11 @@ module BaseTest
1455
1418
  log_entry: k8s_container_log_entry(
1456
1419
  log_entry(0),
1457
1420
  local_resource_id: RANDOM_LOCAL_RESOURCE_ID),
1458
- expected_params: CONTAINER_FROM_TAG_PARAMS
1459
- }
1460
- ].each do |test_params|
1461
- new_stub_context do
1462
- setup_gce_metadata_stubs
1463
- setup_metadata_agent_stubs(test_params[:setup_metadata_agent_stub])
1464
- setup_k8s_metadata_stubs(test_params[:setup_k8s_stub])
1465
- setup_logging_stubs do
1466
- d = create_driver(test_params[:config], CONTAINER_TAG)
1467
- d.emit(test_params[:log_entry])
1468
- d.run
1469
- end
1470
- verify_log_entries(1, test_params[:expected_params]) do |entry|
1471
- assert_equal 'test log entry 0', entry['textPayload'], entry
1472
- end
1473
- end
1474
- end
1475
- end
1476
-
1477
- # Test k8s_node monitored resource including the fallback when Metadata Agent
1478
- # restarts.
1479
- def test_k8s_node_monitored_resource_fallback
1480
- [
1421
+ # When 'kube-env' is present, "compute.googleapis.com/resource_name" is
1422
+ # not added.
1423
+ expected_params: COMPUTE_PARAMS
1424
+ },
1425
+ # Specific cases for k8s_node.
1481
1426
  {
1482
1427
  config: APPLICATION_DEFAULT_CONFIG,
1483
1428
  setup_metadata_agent_stub: true,
@@ -1516,8 +1461,16 @@ module BaseTest
1516
1461
  ].each do |test_params|
1517
1462
  new_stub_context do
1518
1463
  setup_gce_metadata_stubs
1519
- setup_metadata_agent_stubs(test_params[:setup_metadata_agent_stub])
1520
- setup_k8s_metadata_stubs(test_params[:setup_k8s_stub])
1464
+ if test_params[:setup_metadata_agent_stub]
1465
+ setup_metadata_agent_stubs
1466
+ else
1467
+ setup_no_metadata_agent_stubs
1468
+ end
1469
+ if test_params[:setup_k8s_stub]
1470
+ setup_k8s_metadata_stubs
1471
+ else
1472
+ setup_no_k8s_metadata_stubs
1473
+ end
1521
1474
  setup_logging_stubs do
1522
1475
  d = create_driver(test_params[:config])
1523
1476
  d.emit(test_params[:log_entry])
@@ -1594,7 +1547,7 @@ module BaseTest
1594
1547
  [1, 2, 3, 5, 11, 50].each do |n|
1595
1548
  new_stub_context do
1596
1549
  setup_gce_metadata_stubs
1597
- setup_k8s_metadata_stubs
1550
+ setup_container_metadata_stubs
1598
1551
  setup_metadata_agent_stubs
1599
1552
  setup_logging_stubs do
1600
1553
  d = create_driver(ENABLE_METADATA_AGENT_CONFIG)
@@ -1606,7 +1559,7 @@ module BaseTest
1606
1559
  verify_log_entries(n, CONTAINER_FROM_APPLICATION_PARAMS)
1607
1560
  assert_requested_metadata_agent_stub(
1608
1561
  "#{CONTAINER_LOCAL_RESOURCE_ID_PREFIX}.#{CONTAINER_NAMESPACE_ID}" \
1609
- ".#{K8S_POD_NAME}.#{K8S_CONTAINER_NAME}")
1562
+ ".#{CONTAINER_POD_NAME}.#{CONTAINER_CONTAINER_NAME}")
1610
1563
  end
1611
1564
  end
1612
1565
  end
@@ -1686,34 +1639,44 @@ module BaseTest
1686
1639
  MANAGED_VM_BACKEND_VERSION)
1687
1640
  end
1688
1641
 
1689
- def setup_k8s_metadata_stubs(should_respond = true)
1690
- if should_respond
1691
- stub_metadata_request(
1692
- 'instance/attributes/',
1693
- "attribute1\ncluster-location\ncluster-name\nlast_attribute")
1694
- stub_metadata_request('instance/attributes/cluster-location',
1695
- K8S_LOCATION2)
1696
- stub_metadata_request('instance/attributes/cluster-name',
1697
- K8S_CLUSTER_NAME)
1698
- else
1699
- ['cluster-location', 'cluster-name'].each do |metadata_name|
1700
- stub_request(:get, %r{.*instance/attributes/#{metadata_name}.*})
1701
- .to_return(status: 404,
1702
- body: 'The requested URL /computeMetadata/v1/instance/' \
1703
- "attributes/#{metadata_name} was not found on this" \
1704
- ' server.')
1705
- end
1642
+ def setup_container_metadata_stubs
1643
+ stub_metadata_request(
1644
+ 'instance/attributes/',
1645
+ "attribute1\nkube-env\nlast_attribute")
1646
+ stub_metadata_request('instance/attributes/kube-env',
1647
+ "ENABLE_NODE_LOGGING: \"true\"\n"\
1648
+ 'INSTANCE_PREFIX: '\
1649
+ "gke-#{CONTAINER_CLUSTER_NAME}-740fdafa\n"\
1650
+ 'KUBE_BEARER_TOKEN: AoQiMuwkNP2BMT0S')
1651
+ end
1652
+
1653
+ def setup_k8s_metadata_stubs
1654
+ stub_metadata_request(
1655
+ 'instance/attributes/',
1656
+ "attribute1\ncluster-name\ncluster-location\nlast_attribute")
1657
+ stub_metadata_request('instance/attributes/cluster-location', K8S_LOCATION2)
1658
+ stub_metadata_request('instance/attributes/cluster-name', K8S_CLUSTER_NAME)
1659
+ end
1660
+
1661
+ def setup_no_k8s_metadata_stubs
1662
+ ['cluster-location', 'cluster-name'].each do |metadata_name|
1663
+ stub_request(:get, %r{.*instance/attributes/#{metadata_name}.*})
1664
+ .to_return(status: 404,
1665
+ body: 'The requested URL /computeMetadata/v1/instance/' \
1666
+ "attributes/#{metadata_name} was not found on this" \
1667
+ ' server.')
1706
1668
  end
1707
1669
  end
1708
1670
 
1709
1671
  def setup_cloudfunctions_metadata_stubs
1710
1672
  stub_metadata_request(
1711
1673
  'instance/attributes/',
1712
- "attribute1\ncluster-location\ncluster-name\ngcf_region\nlast_attribute")
1713
- stub_metadata_request('instance/attributes/cluster-location',
1714
- K8S_LOCATION2)
1715
- stub_metadata_request('instance/attributes/cluster-name',
1716
- K8S_CLUSTER_NAME)
1674
+ "attribute1\nkube-env\ngcf_region\nlast_attribute")
1675
+ stub_metadata_request('instance/attributes/kube-env',
1676
+ "ENABLE_NODE_LOGGING: \"true\"\n"\
1677
+ 'INSTANCE_PREFIX: '\
1678
+ "gke-#{CLOUDFUNCTIONS_CLUSTER_NAME}-740fdafa\n"\
1679
+ 'KUBE_BEARER_TOKEN: AoQiMuwkNP2BMT0S')
1717
1680
  stub_metadata_request('instance/attributes/gcf_region',
1718
1681
  CLOUDFUNCTIONS_REGION)
1719
1682
  end
@@ -1748,20 +1711,19 @@ module BaseTest
1748
1711
  WebMock.reset!
1749
1712
  end
1750
1713
 
1751
- def setup_metadata_agent_stubs(should_respond = true)
1752
- if should_respond
1753
- MONITORED_RESOURCE_STUBS.each do |local_resource_id, resource|
1754
- stub_request(:get, metadata_request_url(local_resource_id))
1755
- .to_return(status: 200, body: resource)
1756
- end
1757
- stub_request(:get, metadata_request_url(RANDOM_LOCAL_RESOURCE_ID))
1758
- .to_return(status: 404, body: '')
1759
- else
1760
- # Simulate an environment with no metadata agent endpoint present.
1761
- stub_request(:get,
1762
- %r{#{DEFAULT_METADATA_AGENT_URL}\/monitoredResource/.*})
1763
- .to_raise(Errno::EHOSTUNREACH)
1714
+ def setup_metadata_agent_stubs
1715
+ MONITORED_RESOURCE_STUBS.each do |local_resource_id, resource|
1716
+ stub_request(:get, metadata_request_url(local_resource_id))
1717
+ .to_return(status: 200, body: resource)
1764
1718
  end
1719
+ stub_request(:get, metadata_request_url(RANDOM_LOCAL_RESOURCE_ID))
1720
+ .to_return(status: 404, body: '')
1721
+ end
1722
+
1723
+ def setup_no_metadata_agent_stubs
1724
+ # Simulate an environment with no metadata agent endpoint present.
1725
+ stub_request(:get, %r{#{DEFAULT_METADATA_AGENT_URL}\/monitoredResource/.*})
1726
+ .to_raise(Errno::EHOSTUNREACH)
1765
1727
  end
1766
1728
 
1767
1729
  def assert_requested_metadata_agent_stub(local_resource_id)
@@ -1771,20 +1733,21 @@ module BaseTest
1771
1733
  # GKE Container.
1772
1734
 
1773
1735
  def container_tag_with_container_name(container_name)
1774
- "kubernetes.#{K8S_POD_NAME}_#{K8S_NAMESPACE_NAME}_#{container_name}"
1736
+ "kubernetes.#{CONTAINER_POD_NAME}_#{CONTAINER_NAMESPACE_NAME}_" \
1737
+ "#{container_name}"
1775
1738
  end
1776
1739
 
1777
1740
  def container_log_entry_with_metadata(
1778
- log, container_name = K8S_CONTAINER_NAME)
1741
+ log, container_name = CONTAINER_CONTAINER_NAME)
1779
1742
  {
1780
1743
  log: log,
1781
- stream: K8S_STREAM,
1782
- time: K8S_TIMESTAMP,
1744
+ stream: CONTAINER_STREAM,
1745
+ time: CONTAINER_TIMESTAMP,
1783
1746
  kubernetes: {
1784
1747
  namespace_id: CONTAINER_NAMESPACE_ID,
1785
- namespace_name: K8S_NAMESPACE_NAME,
1748
+ namespace_name: CONTAINER_NAMESPACE_NAME,
1786
1749
  pod_id: CONTAINER_POD_ID,
1787
- pod_name: K8S_POD_NAME,
1750
+ pod_name: CONTAINER_POD_NAME,
1788
1751
  container_name: container_name,
1789
1752
  labels: {
1790
1753
  CONTAINER_LABEL_KEY => CONTAINER_LABEL_VALUE
@@ -1793,11 +1756,11 @@ module BaseTest
1793
1756
  }
1794
1757
  end
1795
1758
 
1796
- def container_log_entry(log, stream = K8S_STREAM)
1759
+ def container_log_entry(log, stream = CONTAINER_STREAM)
1797
1760
  {
1798
1761
  log: log,
1799
1762
  stream: stream,
1800
- time: K8S_TIMESTAMP
1763
+ time: CONTAINER_TIMESTAMP
1801
1764
  }
1802
1765
  end
1803
1766
 
@@ -1806,7 +1769,7 @@ module BaseTest
1806
1769
  log: log,
1807
1770
  LOCAL_RESOURCE_ID_KEY =>
1808
1771
  "#{CONTAINER_LOCAL_RESOURCE_ID_PREFIX}.#{CONTAINER_NAMESPACE_ID}" \
1809
- ".#{K8S_POD_NAME}.#{K8S_CONTAINER_NAME}"
1772
+ ".#{CONTAINER_POD_NAME}.#{CONTAINER_CONTAINER_NAME}"
1810
1773
  }
1811
1774
  end
1812
1775
 
@@ -1897,13 +1860,6 @@ module BaseTest
1897
1860
  }
1898
1861
  end
1899
1862
 
1900
- def structured_log_entry
1901
- {
1902
- 'name' => 'test name',
1903
- 'code' => 'test code'
1904
- }
1905
- end
1906
-
1907
1863
  def log_entry(i)
1908
1864
  "test log entry #{i}"
1909
1865
  end
@@ -1972,7 +1928,7 @@ module BaseTest
1972
1928
 
1973
1929
  def verify_container_logs(log_entry_factory, expected_params)
1974
1930
  setup_gce_metadata_stubs
1975
- setup_k8s_metadata_stubs
1931
+ setup_container_metadata_stubs
1976
1932
  [1, 2, 3, 5, 11, 50].each do |n|
1977
1933
  @logs_sent = []
1978
1934
  setup_logging_stubs do
@@ -1982,8 +1938,9 @@ module BaseTest
1982
1938
  end
1983
1939
  verify_log_entries(n, expected_params) do |entry, i|
1984
1940
  verify_default_log_entry_text(entry['textPayload'], i, entry)
1985
- assert_equal K8S_SECONDS_EPOCH, entry['timestamp']['seconds'], entry
1986
- assert_equal K8S_NANOS, entry['timestamp']['nanos'], entry
1941
+ assert_equal CONTAINER_SECONDS_EPOCH, entry['timestamp']['seconds'],
1942
+ entry
1943
+ assert_equal CONTAINER_NANOS, entry['timestamp']['nanos'], entry
1987
1944
  assert_equal CONTAINER_SEVERITY, entry['severity'], entry
1988
1945
  end
1989
1946
  end
@@ -2052,71 +2009,6 @@ module BaseTest
2052
2009
  end
2053
2010
  end
2054
2011
 
2055
- # Cascading JSON detection is only triggered when the record has one field
2056
- # left with name "log", "message" or "msg". This test verifies additional
2057
- # LogEntry fields like spanId and traceId do not disable that by accident.
2058
- def verify_cascading_json_detection_with_log_entry_fields(
2059
- log_entry_field, default_key, root_level_value, nested_level_value)
2060
- setup_gce_metadata_stubs
2061
-
2062
- # {
2063
- # "logging.googleapis.com/XXX' => 'sample value'
2064
- # "msg": {
2065
- # "name": "test name",
2066
- # "code": "test code"
2067
- # }
2068
- # }
2069
- log_entry_with_root_level_field = {
2070
- default_key => root_level_value,
2071
- 'msg' => structured_log_entry.to_json
2072
- }
2073
- # {
2074
- # "msg": {
2075
- # "logging.googleapis.com/XXX' => 'another value',
2076
- # "name": "test name",
2077
- # "code": "test code"
2078
- # }
2079
- # }
2080
- log_entry_with_nested_level_field = {
2081
- 'msg' => {
2082
- default_key => nested_level_value
2083
- }.merge(structured_log_entry).to_json
2084
- }
2085
- # {
2086
- # "logging.googleapis.com/XXX' => 'sample value'
2087
- # "msg": {
2088
- # "logging.googleapis.com/XXX' => 'another value',
2089
- # "name": "test name",
2090
- # "code": "test code"
2091
- # }
2092
- # }
2093
- log_entry_with_both_level_fields = log_entry_with_nested_level_field.merge(
2094
- default_key => root_level_value)
2095
-
2096
- {
2097
- log_entry_with_root_level_field => root_level_value,
2098
- log_entry_with_nested_level_field => nested_level_value,
2099
- log_entry_with_both_level_fields => nested_level_value
2100
- }.each_with_index do |(input_log_entry, expected_value), index|
2101
- setup_logging_stubs do
2102
- @logs_sent = []
2103
- d = create_driver(DETECT_JSON_CONFIG)
2104
- d.emit(input_log_entry)
2105
- d.run
2106
- end
2107
- verify_log_entries(1, COMPUTE_PARAMS, 'jsonPayload') do |entry|
2108
- assert_equal expected_value, entry[log_entry_field],
2109
- "Index #{index} failed. #{expected_value} is expected" \
2110
- " for #{log_entry_field} field."
2111
- payload_fields = get_fields(entry['jsonPayload'])
2112
- assert_equal structured_log_entry.size, payload_fields.size
2113
- payload_fields.each do |key, value|
2114
- assert_equal structured_log_entry[key], get_string(value)
2115
- end
2116
- end
2117
- end
2118
- end
2119
-
2120
2012
  def verify_field_key(log_entry_field, default_key, custom_key,
2121
2013
  custom_key_config, sample_value)
2122
2014
  setup_gce_metadata_stubs