test/plugin/base_test.rb in fluent-plugin-google-cloud-0.7.28 vs test/plugin/base_test.rb in fluent-plugin-google-cloud-0.7.29
- old
+ new
@@ -941,81 +941,210 @@
assert_prometheus_metric_value(:stackdriver_ingested_entries_count,
log_entry_count, :aggregate)
end
end
- def test_timestamps
+ def test_compute_timestamp
setup_gce_metadata_stubs
- current_time = Time.now
+ d = create_driver(APPLICATION_DEFAULT_CONFIG)
+
+ compute_timestamp = lambda do |driver, record, time|
+ driver.instance.send(:compute_timestamp, record, time)
+ end
+
+ current_time = Time.new(2019, 12, 29, 10, 23, 35, '-08:00')
+ one_day_later = current_time.to_datetime.next_day.to_time
+ just_under_one_day_later = one_day_later - 1
next_year = Time.mktime(current_time.year + 1)
one_second_before_next_year = next_year - 1
- adjusted_to_last_year =
- one_second_before_next_year.to_datetime.prev_year.to_time
one_second_into_next_year = next_year + 1
- one_day_into_next_year = next_year.to_date.next_day.to_time
+ one_day_into_next_year = next_year.to_datetime.next_day.to_time
+
+ [
+ Time.at(123_456.789),
+ Time.at(0),
+ current_time,
+ just_under_one_day_later,
+ one_second_before_next_year,
+ next_year,
+ one_second_into_next_year,
+ one_day_into_next_year
+ ].each do |ts|
+ # Use record collection time.
+ ts_secs, ts_nanos, actual_ts = compute_timestamp[d, {
+ 'message' => ''
+ }, ts.to_f]
+ assert_timestamp_matches ts, ts_secs, ts_nanos, actual_ts.iso8601
+
+ # Use the (deprecated) timeNanos key.
+ ts_secs, ts_nanos, actual_ts = compute_timestamp[d, {
+ 'message' => '',
+ 'timeNanos' => ts.tv_sec * 1_000_000_000 + ts.tv_nsec
+ }, 1.0]
+ assert_timestamp_matches ts, ts_secs, ts_nanos, actual_ts.iso8601
+
+ # Use the structured timestamp key.
+ ts_secs, ts_nanos, actual_ts = compute_timestamp[d, {
+ 'message' => '',
+ 'timestamp' => { 'seconds' => ts.tv_sec, 'nanos' => ts.tv_nsec }
+ }, 1.0]
+ assert_timestamp_matches ts, ts_secs, ts_nanos, actual_ts.iso8601
+
+ # Use the timestampSeconds/timestampNanos keys.
+ ts_secs, ts_nanos, actual_ts = compute_timestamp[d, {
+ 'message' => '',
+ 'timestampSeconds' => ts.tv_sec,
+ 'timestampNanos' => ts.tv_nsec
+ }, 1.0]
+ assert_timestamp_matches ts, ts_secs, ts_nanos, actual_ts.iso8601
+
+ # Use the string timestampSeconds/timestampNanos keys.
+ ts_secs, ts_nanos, actual_ts = compute_timestamp[d, {
+ 'message' => '',
+ 'timestampSeconds' => ts.tv_sec.to_s,
+ 'timestampNanos' => ts.tv_nsec.to_s
+ }, 1.0]
+ assert_timestamp_matches ts, ts_secs, ts_nanos, actual_ts.iso8601
+ end
+ end
+
+ def test_adjust_timestamp
+ setup_gce_metadata_stubs
+ d = create_driver(APPLICATION_DEFAULT_CONFIG)
+
+ adjust_timestamp_if_invalid = lambda do |driver, timestamp, current_time|
+ driver.instance.send(:adjust_timestamp_if_invalid, timestamp,
+ current_time)
+ end
+
+ december_29 = Time.new(2019, 12, 29, 10, 23, 35, '-08:00')
+ december_31 = Time.new(2019, 12, 31, 10, 23, 35, '-08:00')
+ january_1 = Time.new(2020, 1, 1, 10, 23, 35, '-08:00')
+
{
- APPLICATION_DEFAULT_CONFIG => {
- Time.at(123_456.789) => Time.at(123_456.789),
- Time.at(0) => Time.at(0),
- current_time => current_time,
- one_second_before_next_year => adjusted_to_last_year,
- next_year => Time.at(0),
- one_second_into_next_year => Time.at(0),
- one_day_into_next_year => Time.at(0)
- },
- NO_ADJUST_TIMESTAMPS_CONFIG => {
- Time.at(123_456.789) => Time.at(123_456.789),
- Time.at(0) => Time.at(0),
- current_time => current_time,
- one_second_before_next_year => one_second_before_next_year,
- next_year => next_year,
- one_second_into_next_year => one_second_into_next_year,
- one_day_into_next_year => one_day_into_next_year
- }
- }.each do |config, timestamps|
+ # December 29, 2019 (normal operation).
+ december_29 => begin
+ one_day_later = Time.new(2019, 12, 30, 10, 23, 35, '-08:00')
+ one_day_a_year_earlier = Time.new(2018, 12, 30, 10, 23, 35, '-08:00')
+ just_under_one_day_later = Time.new(2019, 12, 30, 10, 23, 34, '-08:00')
+ next_year = Time.new(2020, 1, 1, 0, 0, 0, '-08:00')
+ one_second_before_next_year =
+ Time.new(2019, 12, 31, 11, 59, 59, '-08:00')
+ one_second_before_this_year =
+ Time.new(2018, 12, 31, 11, 59, 59, '-08:00')
+ one_second_into_next_year = Time.new(2020, 1, 1, 0, 0, 1, '-08:00')
+ one_day_into_next_year = Time.new(2020, 1, 2, 0, 0, 0, '-08:00')
+ {
+ Time.at(123_456.789) => Time.at(123_456.789),
+ Time.at(0) => Time.at(0),
+ december_29 => december_29,
+ one_day_later => one_day_a_year_earlier,
+ just_under_one_day_later => just_under_one_day_later,
+ one_second_before_next_year => one_second_before_this_year,
+ next_year => Time.at(0),
+ one_second_into_next_year => Time.at(0),
+ one_day_into_next_year => Time.at(0)
+ }
+ end,
+ # January 1, 2020 (normal operation).
+ january_1 => begin
+ one_day_later = Time.new(2020, 1, 2, 10, 23, 35, '-08:00')
+ one_day_a_year_earlier = Time.new(2019, 1, 2, 10, 23, 35, '-08:00')
+ just_under_one_day_later = Time.new(2020, 1, 2, 10, 23, 34, '-08:00')
+ next_year = Time.new(2021, 1, 1, 0, 0, 0, '-08:00')
+ one_second_before_next_year =
+ Time.new(2020, 12, 31, 11, 59, 59, '-08:00')
+ one_second_before_this_year =
+ Time.new(2019, 12, 31, 11, 59, 59, '-08:00')
+ one_second_into_next_year = Time.new(2021, 1, 1, 0, 0, 1, '-08:00')
+ one_day_into_next_year = Time.new(2021, 1, 2, 0, 0, 0, '-08:00')
+ {
+ Time.at(123_456.789) => Time.at(123_456.789),
+ Time.at(0) => Time.at(0),
+ january_1 => january_1,
+ one_day_later => one_day_a_year_earlier,
+ just_under_one_day_later => just_under_one_day_later,
+ one_second_before_next_year => one_second_before_this_year,
+ next_year => Time.at(0),
+ one_second_into_next_year => Time.at(0),
+ one_day_into_next_year => Time.at(0)
+ }
+ end,
+ # December 31, 2019 (next day overlaps new year).
+ december_31 => begin
+ one_day_later = Time.new(2020, 1, 1, 10, 23, 35, '-08:00')
+ just_under_one_day_later = Time.new(2020, 1, 1, 10, 23, 34, '-08:00')
+ next_year = Time.new(2020, 1, 1, 0, 0, 0, '-08:00')
+ one_second_before_next_year =
+ Time.new(2019, 12, 31, 11, 59, 59, '-08:00')
+ one_second_into_next_year = Time.new(2020, 1, 1, 0, 0, 1, '-08:00')
+ one_day_into_next_year = Time.new(2020, 1, 2, 0, 0, 0, '-08:00')
+ {
+ Time.at(123_456.789) => Time.at(123_456.789),
+ Time.at(0) => Time.at(0),
+ december_31 => december_31,
+ one_day_later => Time.at(0), # Falls into the next year.
+ just_under_one_day_later => just_under_one_day_later,
+ one_second_before_next_year => one_second_before_next_year,
+ next_year => next_year,
+ one_second_into_next_year => one_second_into_next_year,
+ one_day_into_next_year => Time.at(0)
+ }
+ end
+ }.each do |current_time, timestamps|
timestamps.each do |ts, expected_ts|
- emit_index = 0
- setup_logging_stubs do
- @logs_sent = []
- d = create_driver(config)
- # Test the "native" fluentd timestamp as well as our nanosecond tags.
- d.emit({ 'message' => log_entry(emit_index) }, ts.to_f)
- emit_index += 1
- d.emit('message' => log_entry(emit_index),
- 'timeNanos' => ts.tv_sec * 1_000_000_000 + ts.tv_nsec)
- emit_index += 1
- d.emit('message' => log_entry(emit_index),
- 'timestamp' => { 'seconds' => ts.tv_sec,
- 'nanos' => ts.tv_nsec })
- emit_index += 1
- d.emit('message' => log_entry(emit_index),
- 'timestampSeconds' => ts.tv_sec,
- 'timestampNanos' => ts.tv_nsec)
- emit_index += 1
- d.emit('message' => log_entry(emit_index),
- 'timestampSeconds' => ts.tv_sec.to_s,
- 'timestampNanos' => ts.tv_nsec.to_s)
- emit_index += 1
- d.run
- verify_log_entries(emit_index, COMPUTE_PARAMS) do |entry, i|
- verify_default_log_entry_text(entry['textPayload'], i, entry)
- actual_timestamp = timestamp_parse(entry['timestamp'])
- assert_equal actual_timestamp['seconds'], expected_ts.tv_sec, entry
- # Fluentd v0.14 onwards supports nanosecond timestamp values.
- # Added in 600 ns delta to avoid flaky tests introduced
- # due to rounding error in double-precision floating-point numbers
- # (to account for the missing 9 bits of precision ~ 512 ns).
- # See http://wikipedia.org/wiki/Double-precision_floating-point_format.
- assert_in_delta expected_ts.tv_nsec, actual_timestamp['nanos'],
- 600, entry
- end
+ ts_secs, ts_nanos = adjust_timestamp_if_invalid[d, ts, current_time]
+ adjusted_ts = Time.at(ts_secs, ts_nanos / 1_000.0)
+ assert_timestamp_matches expected_ts, ts_secs, ts_nanos,
+ adjusted_ts.iso8601
+ end
+ end
+ end
+
+ def test_log_timestamps
+ setup_gce_metadata_stubs
+ current_time = Time.now
+ {
+ # Verify that timestamps make it through.
+ Time.at(123_456.789) => Time.at(123_456.789),
+ Time.at(0) => Time.at(0),
+ current_time => current_time
+ }.each do |ts, expected_ts|
+ emit_index = 0
+ setup_logging_stubs do
+ @logs_sent = []
+ d = create_driver(APPLICATION_DEFAULT_CONFIG)
+ # Test the "native" fluentd timestamp as well as our nanosecond tags.
+ d.emit({ 'message' => log_entry(emit_index) }, ts.to_f)
+ emit_index += 1
+ d.emit('message' => log_entry(emit_index),
+ 'timeNanos' => ts.tv_sec * 1_000_000_000 + ts.tv_nsec)
+ emit_index += 1
+ d.emit('message' => log_entry(emit_index),
+ 'timestamp' => { 'seconds' => ts.tv_sec,
+ 'nanos' => ts.tv_nsec })
+ emit_index += 1
+ d.emit('message' => log_entry(emit_index),
+ 'timestampSeconds' => ts.tv_sec,
+ 'timestampNanos' => ts.tv_nsec)
+ emit_index += 1
+ d.emit('message' => log_entry(emit_index),
+ 'timestampSeconds' => ts.tv_sec.to_s,
+ 'timestampNanos' => ts.tv_nsec.to_s)
+ emit_index += 1
+ d.run
+ verify_log_entries(emit_index, COMPUTE_PARAMS) do |entry, i|
+ verify_default_log_entry_text(entry['textPayload'], i, entry)
+ actual_timestamp = timestamp_parse(entry['timestamp'])
+ assert_timestamp_matches expected_ts, actual_timestamp['seconds'],
+ actual_timestamp['nanos'], entry
end
end
end
end
- def test_malformed_timestamp
+ def test_malformed_timestamp_field
setup_gce_metadata_stubs
setup_logging_stubs do
d = create_driver
# if timestamp is not a hash it is passed through to the json payload.
d.emit('message' => log_entry(0), 'timestamp' => 'not-a-hash')
@@ -2745,9 +2874,20 @@
#
# An optional block can be passed in if we need to assert something other than
# a plain equal. e.g. assert_in_delta.
def assert_equal_with_default(_field, _expected_value, _default_value, _entry)
_undefined
+ end
+
+ # Compare the timestamp seconds and nanoseconds with the expected timestamp.
+ def assert_timestamp_matches(expected_ts, ts_secs, ts_nanos, entry)
+ assert_equal expected_ts.tv_sec, ts_secs, entry
+ # Fluentd v0.14 onwards supports nanosecond timestamp values.
+ # Added in 600 ns delta to avoid flaky tests introduced
+ # due to rounding error in double-precision floating-point numbers
+ # (to account for the missing 9 bits of precision ~ 512 ns).
+ # See http://wikipedia.org/wiki/Double-precision_floating-point_format.
+ assert_in_delta expected_ts.tv_nsec, ts_nanos, 600, entry
end
def assert_prometheus_metric_value(metric_name, expected_value, labels = {})
metric = Prometheus::Client.registry.get(metric_name)
assert_not_nil(metric)