File: test_timeseries.rb

package info (click to toggle)
ruby-fog-google 1.19.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,568 kB
  • sloc: ruby: 16,775; makefile: 3
file content (238 lines) | stat: -rw-r--r-- 7,408 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
require "helpers/integration_test_helper"

class TestMetricDescriptors < FogIntegrationTest
  # This module has a decent amount of retry wrappers as the Stackdriver API
  # can be quite slow with metric propagation (sometimes 80+ seconds) and client
  # returning errors, e.g. Google::Apis::ClientError: badRequest if the metric
  # hasn't yet been created instead of a 404.

  TEST_METRIC_PREFIX = "custom.googleapis.com/fog-google-test/timeseries".freeze
  LABEL_DESCRIPTORS = [
    {
      :key => "test_string_label",
      :value_type => "STRING",
      :description => "test string label"
    },
    {
      :key => "test_bool_label",
      :value_type => "BOOL",
      :description => "test boolean label"
    },
    {
      :key => "test_int_label",
      :value_type => "INT64",
      :description => "test integer label"
    }
  ].freeze

  def setup
    @client = Fog::Google::Monitoring.new
    # Ensure any resources we create with test prefixes are removed

    Minitest.after_run do
      _delete_test_resources
    end
  end

  def test_timeseries_collection
    metric_type = "#{TEST_METRIC_PREFIX}/test_requests"
    _some_custom_metric_descriptor(metric_type)

    start_time = Time.now
    labels = {
      :test_string_label => "foo",
      :test_bool_label => "false",
      :test_int_label => "1"
    }

    expected = _some_timeseries(start_time, metric_type, labels)
    resp = @client.create_timeseries(:timeseries => [expected])
    assert_empty(resp.to_h)

    # Wait for metric to be created
    retry_on(Google::Apis::ClientError) do
      @client.list_timeseries(
          :filter => "metric.type = \"#{metric_type}\"",
          :interval => {
            # Subtracting one second because timeSeries.list API
            # doesn't return points that are exactly the same time
            # as the interval for some reason.
            :start_time => (start_time - 1).to_datetime.rfc3339,
            :end_time => Time.now.to_datetime.rfc3339
          }
      ).time_series
    end

    series = retry_on(Google::Apis::ClientError) do
      @client.timeseries_collection.all(
        :filter => "metric.type = \"#{metric_type}\"",
        :interval => {
          # Subtracting one second because timeSeries.list API
          # doesn't return points that are exactly the same time
          # as the interval for some reason.
          :start_time => (start_time - 1).to_datetime.rfc3339,
          :end_time => Time.now.to_datetime.rfc3339
        }
      )
    end

    assert_equal(1, series.size)
    actual = series.first
    assert_equal(expected[:metric], actual.metric)
    assert_equal(expected[:metric_kind], actual.metric_kind)

    assert_equal(expected[:resource], actual.resource)
    assert_equal(expected[:value_type], actual.value_type)
    assert_equal(1, actual.points.size)
    assert_equal(expected[:points].first[:value], actual.points.first[:value])
  end

  def test_multiple_timeseries
    metric_type = "#{TEST_METRIC_PREFIX}/test_multiple"
    _some_custom_metric_descriptor(metric_type)

    start_time = Time.now
    metric_labels = [
      {
        :test_string_label => "first",
        :test_bool_label => "true",
        :test_int_label => "1"
      },
      {
        :test_string_label => "second",
        :test_bool_label => "false",
        :test_int_label => "2"
      }
    ]

    timeseries = metric_labels.map do |labels|
      _some_timeseries(start_time, metric_type, labels)
    end

    retry_on(Google::Apis::ServerError) do
      @client.create_timeseries(:timeseries => timeseries)
    end
    interval = {
      # Subtracting one second because timeSeries.list API
      # doesn't return points that are exactly the same time
      # as the interval for some reason.
      :start_time => (start_time - 1).to_datetime.rfc3339,
      :end_time => Time.now.to_datetime.rfc3339
    }


    # Wait for metric to be created
    # Retriable is used instead of wait_for due to API client returning Google::Apis::ClientError: badRequest if the
    # metric hasn't yet been created
    retry_on(Google::Apis::ClientError) do
      @client.list_timeseries(
        :filter => "metric.type = \"#{metric_type}\"",
        :interval => interval
      ).time_series
    end

    # Test page size
    resp = retry_on(Google::Apis::ClientError) do
      @client.list_timeseries(
        :filter => "metric.type = \"#{metric_type}\"",
        :interval => interval,
        :page_size => 1
      )
    end

    refute_nil(resp.time_series, "expected timeseries to not be nil")
    assert_equal(resp.time_series.size, 1,
                 "expected timeseries count to be equal to page size 1")

    next_resp = @client.list_timeseries(
      :filter => "metric.type = \"#{metric_type}\"",
      :interval => interval,
      :page_size => 1,
      :page_token => resp.next_page_token
    )
    assert_equal(next_resp.time_series.size, 1,
                 "expected timeseries count to be equal to page size 1")
    labels = resp.time_series.first.metric.labels
    labels_next = next_resp.time_series.first.metric.labels
    refute_equal(labels, labels_next,
           "expected different timeseries when using page_token")

    # Test filter
    series = retry_on(Google::Apis::ClientError) do
      @client.timeseries_collection.all(
        :filter => %[
          metric.type = "#{metric_type}" AND
          metric.label.test_string_label = "first"
        ],
        :interval => interval
      )
    end
    assert_equal(series.size, 1,
                 "expected returned timeseries to be filtered to 1 value")
    assert_equal("true", series.first.metric[:labels][:test_bool_label])
    assert_equal("1", series.first.metric[:labels][:test_int_label])
  end

  def _delete_test_resources
    list_resp = @client.monitoring.list_project_metric_descriptors(
      "projects/#{@client.project}",
      filter: "metric.type = starts_with(\"#{TEST_METRIC_PREFIX}\")"
    )
    unless list_resp.metric_descriptors.nil?
      list_resp.metric_descriptors.each do |md|
        @client.monitoring.delete_project_metric_descriptor(md.name)
      end
    end
  rescue
    # Do nothing
  end

  def _some_custom_metric_descriptor(metric_type)
    # Create custom metric to write test timeseries for.
    @client.create_metric_descriptor(
      :labels => LABEL_DESCRIPTORS,
      :metric_type => metric_type,
      :unit => "1",
      :value_type => "INT64",
      :description => "A custom metric descriptor for fog-google timeseries test.",
      :display_name => "fog-google-test/#{metric_type}",
      :metric_kind => "GAUGE"
    )

    # Wait for metric descriptor to be created
    Fog.wait_for(180, 2) do
      begin
        @client.get_metric_descriptor(metric_type)
        true
      rescue
        false
      end
    end
  end

  def _some_timeseries(start_time, metric_type, labels)
    {
      :metric => {
        :type => metric_type,
        :labels => labels
      },
      :resource => {
        :type => "global",
        :labels => { :project_id => @client.project }
      },
      :metric_kind => "GAUGE",
      :value_type => "INT64",
      :points => [
        {
          :interval => {
            :end_time => start_time.to_datetime.rfc3339,
            :start_time => start_time.to_datetime.rfc3339
          },
          :value => {
            :int64_value => rand(10)
          }
        }
      ]
    }
  end
end