fluent-plugin-google-cloud 0.6.25.1 → 0.7.0.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 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