opencensus-stackdriver 0.1.2 → 0.4.0

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
  SHA256:
3
- metadata.gz: 6648ab08a2f19dcc8378487f54025f43d3f0fbbf5144582a095eb1df50d899a8
4
- data.tar.gz: b35b154b195811a9fc6a69cbdf553825f59818390a8e80dbbd9d7138767c8934
3
+ metadata.gz: 0c38340ddaa943b074e93623040737f17eacbd06d93f2adf0568fa2f4653776e
4
+ data.tar.gz: fd1589264c08774869166ff8a249e7e35e0a42e30f17048f09a60c859bc71539
5
5
  SHA512:
6
- metadata.gz: 59d6285c74a85ed961450af1a9d847c436aecd190ad7afae0c76206e0eb33fb7d30eecaa382ab8039a668d8f232a574c5bad65a6b24641d399a57b5fd973db16
7
- data.tar.gz: 4559660ff5249c3535b42f4e813c1b93adf026d07c152d855d3c86cd18768fb5d6bd6a6d3430807cc89dbd63c3eb129b4ac949524ee43ca86e3f760bf5b2b0f0
6
+ metadata.gz: f7404e1915c08587c91fcc6c25664b4419e600dbc5456639c5eff53a07811660b64e610ad45aa0e993b792ca1b5bd24b11915b385661cad9f25aefa0618a1a94
7
+ data.tar.gz: 584e5a22a969028271fcec0021baa1b24349e461029d2b41bef42cc1bbd5fb3ef3d6abbfbfd93362368b0d60dada4c6648b35484c71a3fd3306fa0015169303c
@@ -1,5 +1,32 @@
1
1
  # Release History
2
2
 
3
+ ### 0.4.0 / 2020-07-23
4
+
5
+ * Update for compatibility with changes to the google-cloud-trace and google-cloud-monitoring library structure.
6
+ * Requires Ruby 2.4 or later.
7
+
8
+ ### 0.3.2 / 2020-02-24
9
+
10
+ * Update the google-cloud-trace and google-cloud-monitoring dependencies to versions that support service address override.
11
+
12
+ ### 0.3.1 / 2020-02-06
13
+
14
+ * Support customizing the stackdriver service address
15
+
16
+ ### 0.3.0 / 2019-10-14
17
+
18
+ This release requires version 0.5 or later of the opencensus gem. It includes
19
+ experimental support for exporting OpenCensus Stats to the Stackdriver
20
+ Monitoring service. Note that Stats support is incomplete and there are known
21
+ issues.
22
+
23
+ ### 0.2.0 / 2018-10-22
24
+
25
+ This release requires version 0.4 or later of the opencensus gem.
26
+
27
+ * Map standard HTTP attributes from OpenCensus names to Stackdriver names.
28
+ * Fixed thread pool size configuration.
29
+
3
30
  ### 0.1.2 / 2018-05-22
4
31
 
5
32
  * Add agent identifier and version attribute to reported spans.
data/README.md CHANGED
@@ -8,7 +8,8 @@ that exports data to [Stackdriver](https://cloud.google.com/stackdriver/).
8
8
  OpenCensus is a platform- and provider-agnostic framework for distributed
9
9
  tracing and stats collection. For more information, see https://opencensus.io.
10
10
 
11
- This library is in an alpha stage, and the API is subject to change.
11
+ This library is in an alpha stage, and the API is subject to change. In
12
+ particular, support for the Stats API is currently incomplete and experimental.
12
13
 
13
14
  ## Quick Start
14
15
 
@@ -12,4 +12,16 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+
16
+ ##
17
+ # OpenCensus is a vendor-agnostic single distribution of libraries to provide
18
+ # metrics collection and tracing for your services. See https://opencensus.io/
19
+ # for general information on OpenCensus.
20
+ #
21
+ # The Stackdriver Trace plugin for OpenCensus is implemented in the
22
+ # {OpenCensus::Trace::Exporters::Stackdriver} class.
23
+ #
24
+ module OpenCensus
25
+ end
26
+
15
27
  require "opencensus/stackdriver"
@@ -12,10 +12,18 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+
15
16
  require "opencensus"
16
17
 
17
18
  module OpenCensus
18
- ## Information about the Stackdriver exporter plugin
19
+ ##
20
+ # The Stackdriver exporter plugin for OpenCensus exports OpenCensus trace and
21
+ # stats information to Stackdriver Trace and Monitoring services.
22
+ #
23
+ # The Stackdriver Trace plugin for OpenCensus is implemented in the
24
+ # {OpenCensus::Trace::Exporters::Stackdriver} class and
25
+ # {OpenCensus::Stats::Exporters::Stackdriver}
26
+ #
19
27
  module Stackdriver
20
28
  end
21
29
  end
@@ -23,3 +31,5 @@ end
23
31
  require "opencensus/stackdriver/version"
24
32
  require "opencensus/trace/exporters/stackdriver"
25
33
  require "opencensus/trace/exporters/stackdriver/converter"
34
+ require "opencensus/stats/exporters/stackdriver"
35
+ require "opencensus/stats/exporters/stackdriver/converter"
@@ -12,9 +12,10 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+
15
16
  module OpenCensus
16
17
  module Stackdriver
17
18
  ## Current OpenCensus Stackdriver plugin version
18
- VERSION = "0.1.2".freeze
19
+ VERSION = "0.4.0".freeze
19
20
  end
20
21
  end
@@ -0,0 +1,324 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenCensus Authors
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ gem "google-cloud-monitoring-v3"
19
+ gem "concurrent-ruby"
20
+
21
+ require "concurrent"
22
+ require "google/cloud/env"
23
+ require "google/cloud/monitoring/v3"
24
+
25
+ module OpenCensus
26
+ ##
27
+ # OpenCensus Stats provides a standard interface for distributed stats
28
+ # recording.
29
+ #
30
+ module Stats
31
+ ##
32
+ # The exporters module is a namespace for stats exporters.
33
+ #
34
+ module Exporters
35
+ ##
36
+ # The Stackdriver exporter for OpenCensus Stats exports captured stats
37
+ # to a Google Monitoring project. It calls the Monitoring API in
38
+ # a background thread pool.
39
+ #
40
+ class Stackdriver
41
+ # Default custom opencensus domain name
42
+ # @return [String]
43
+ CUSTOM_OPENCENSUS_DOMAIN = "custom.googleapis.com/opencensus".freeze
44
+
45
+ # Default metric resouce type.
46
+ # @return [String]
47
+ GLOBAL_RESOURCE_TYPE = "global".freeze
48
+
49
+ # The project ID
50
+ # @return [String]
51
+ #
52
+ attr_reader :project_id
53
+
54
+ # Metric prefix
55
+ # @return [String]
56
+ attr_reader :metric_prefix
57
+
58
+ # Metric resource type
59
+ # @return [String]
60
+ attr_reader :resource_type
61
+
62
+ # Metric resource labels
63
+ # @return [Hash<String,String>]
64
+ attr_reader :resource_labels
65
+
66
+ # Create a Stackdriver exporter.
67
+ #
68
+ # @param [String] project_id The project identifier for the Stackdriver
69
+ # Monitoring service you are connecting to. If you are running on
70
+ # Google
71
+ # Cloud hosting (e.g. Compute Engine, Kubernetes Engine, or App
72
+ # Engine), this parameter is optional and will default to the
73
+ # hosting project. Otherwise, it is required.
74
+ # @param [String, Hash, Google::Auth::Credentials] credentials The
75
+ # Stackdriver API credentials, which can be a path to a keyfile as
76
+ # a String, the contents of a keyfile as a Hash, or a
77
+ # Google::Auth::Credentials object. If you are running on Google
78
+ # Cloud hosting (e.g. Compute Engine, Kubernetes Engine, or App
79
+ # Engine), this parameter is optional and will default to the
80
+ # credentials provided by the hosting project. Otherwise, it is
81
+ # required.
82
+ # @param [String, Array<String>] scope The OAuth 2.0 scopes controlling
83
+ # the set of resources and operations the API client can access.
84
+ # Optional. Most applications can leave this set to the default.
85
+ # @param [Integer] timeout The default timeout for API requests, in
86
+ # seconds. Optional.
87
+ # @param [Hash] client_config An optional set of additional
88
+ # configuration values for the API connection.
89
+ # @param [Integer] max_queue The maximum number of API requests that
90
+ # can be queued for background operation. If the queue exceeds this
91
+ # value, additional requests will be run in the calling thread
92
+ # rather than in the background. Set to 0 to allow the queue to
93
+ # grow indefinitely. Default is 1000.
94
+ # @param [Integer] max_threads The maximum number of threads that can
95
+ # be spun up to handle API requests. Default is 1. If set to 0,
96
+ # backgrounding will be disabled and all requests will run in the
97
+ # calling thread.
98
+ # @param [Integer] auto_terminate_time The time in seconds allotted to
99
+ # complete any pending background requests when Ruby is exiting.
100
+ # @param [String] metric_prefix Prefix for stackdriver metric.
101
+ # Default value set to {CUSTOM_OPENCENSUS_DOMAIN}
102
+ # @param [String] resource_type Metric resource type.
103
+ # Default value set to {GLOBAL_RESOURCE_TYPE}
104
+ # @param [Hash<String,String>] resource_labels Metric resource labels.
105
+ # Default value set to { "project_id" => project_id }
106
+ # @param [String] gcm_service_address Override for the Google
107
+ # Cloud Monitoring service hostname, or `nil` to leave as
108
+ # the default.
109
+ #
110
+ def initialize \
111
+ project_id: nil,
112
+ credentials: nil,
113
+ scope: nil,
114
+ timeout: nil,
115
+ client_config: nil, # rubocop:disable Lint/UnusedMethodArgument
116
+ max_queue: 1000,
117
+ max_threads: 1,
118
+ auto_terminate_time: 10,
119
+ mock_client: nil,
120
+ metric_prefix: nil,
121
+ resource_type: nil,
122
+ resource_labels: nil,
123
+ gcm_service_address: nil
124
+ @project_id = project_id ||
125
+ ENV["GOOGLE_CLOUD_PROJECT"] ||
126
+ Google::Cloud.env.project_id
127
+ @metric_prefix = metric_prefix || CUSTOM_OPENCENSUS_DOMAIN
128
+ @resource_type = resource_type || GLOBAL_RESOURCE_TYPE
129
+ @resource_labels = resource_labels || {
130
+ "project_id" => @project_id
131
+ }
132
+ @executor = create_executor max_threads, max_queue
133
+
134
+ if auto_terminate_time
135
+ terminate_at_exit! @executor, auto_terminate_time
136
+ end
137
+
138
+ if mock_client
139
+ @client_promise =
140
+ Concurrent::Promise.fulfill mock_client, executor: @executor
141
+ else
142
+ @client_promise = create_client_promise \
143
+ @executor, credentials, scope, timeout, gcm_service_address
144
+ end
145
+
146
+ @converter = Converter.new @project_id
147
+ paths = Google::Cloud::Monitoring::V3::MetricService::Paths
148
+ @project_path = paths.project_path project: @project_id
149
+ end
150
+
151
+ # Export stats to Monitoring service asynchronously.
152
+ #
153
+ # @param [Array<OpenCensus::Stats::ViewData>] views_data The captured
154
+ # stats data
155
+ #
156
+ def export views_data
157
+ raise "Exporter is no longer running" unless @executor.running?
158
+
159
+ return if views_data.nil? || views_data.empty?
160
+
161
+ @client_promise.execute
162
+ export_promise = @client_promise.then do |client|
163
+ export_as_batch(client, views_data)
164
+ end
165
+ export_promise.on_error do |reason|
166
+ warn "Unable to export to Monitoring service because: #{reason}"
167
+ end
168
+
169
+ nil
170
+ end
171
+
172
+ ##
173
+ # Returns true if this exporter is running and will accept further
174
+ # export requests. Returns false once the exporter begins shutting down.
175
+ #
176
+ # @return [boolean]
177
+ #
178
+ def running?
179
+ @executor.running?
180
+ end
181
+
182
+ ##
183
+ # Returns true if this exporter has finished shutting down and all
184
+ # pending stats have been sent.
185
+ #
186
+ # @return [boolean]
187
+ #
188
+ def shutdown?
189
+ @executor.shutdown?
190
+ end
191
+
192
+ ##
193
+ # Returns true if this exporter has begun shutting down and is no
194
+ # longer accepting export requests, but is still running queued
195
+ # requests in the background.
196
+ #
197
+ # @return [boolean]
198
+ #
199
+ def shuttingdown?
200
+ @executor.shuttingdown?
201
+ end
202
+
203
+ ##
204
+ # Begin shutting down the exporter gracefully. After this operation is
205
+ # performed, the exporter will no longer accept export requests, but
206
+ # will finish any pending requests in the background.
207
+ #
208
+ def shutdown
209
+ @executor.shutdown
210
+ self
211
+ end
212
+
213
+ ##
214
+ # Begin shutting down the exporter forcefully. After this operation is
215
+ # performed, the exporter will no longer accept export requests, and
216
+ # will finish any currently running export requests, but will cancel
217
+ # all requests that are still pending in the queue.
218
+ #
219
+ def kill
220
+ @executor.kill
221
+ self
222
+ end
223
+
224
+ ##
225
+ # Wait for the exporter to finish shutting down.
226
+ #
227
+ # @param [Integer, nil] timeout A timeout in seconds, or nil for no
228
+ # timeout.
229
+ # @return [boolean] true if the exporter is shut down, or false if the
230
+ # wait timed out.
231
+ #
232
+ def wait_for_termination timeout = nil
233
+ @executor.wait_for_termination timeout
234
+ end
235
+
236
+ # Create a metric descriptor
237
+ #
238
+ # An error will be raised if there is
239
+ # already a metric descriptor created with the same name
240
+ # but it has a different aggregation or keys.
241
+ #
242
+ # @param [OpenCensus::Stats::View] view
243
+ # @return [Google::Api::MetricDescriptor]
244
+ #
245
+ def create_metric_descriptor view
246
+ metric_descriptor = @converter.convert_metric_descriptor(
247
+ view,
248
+ metric_prefix
249
+ )
250
+ paths = Google::Cloud::Monitoring::V3::MetricService::Paths
251
+ metric_name = paths.metric_descriptor_path(
252
+ project: project_id,
253
+ metric_descriptor: metric_descriptor.type
254
+ )
255
+
256
+ @client_promise.execute
257
+ descriptor_create_promise = @client_promise.then do |client|
258
+ client.create_metric_descriptor name: metric_name,
259
+ metric_descriptor: metric_descriptor
260
+ end
261
+ descriptor_create_promise.value!
262
+ end
263
+
264
+ private
265
+
266
+ # Create the executor
267
+ def create_executor max_threads, max_queue
268
+ if max_threads >= 1
269
+ Concurrent::ThreadPoolExecutor.new \
270
+ min_threads: 1, max_threads: max_threads,
271
+ max_queue: max_queue, fallback_policy: :caller_runs,
272
+ auto_terminate: false
273
+ else
274
+ Concurrent::ImmediateExecutor.new
275
+ end
276
+ end
277
+
278
+ # Create the client promise.
279
+ # We create the client lazily so grpc doesn't get initialized until
280
+ # we actually need it. This is important because if it is intialized
281
+ # too early, before a fork, it can go into a bad state.
282
+ def create_client_promise executor, credentials, scopes,
283
+ timeout, service_address
284
+ Concurrent::Promise.new executor: executor do
285
+ Google::Cloud::Monitoring::V3::MetricService::Client.new do |config|
286
+ config.credentials = credentials if credentials
287
+ config.scope = scopes if scopes
288
+ config.timeout = timeout if timeout
289
+ config.endpoint = service_address if service_address
290
+ config.lib_name = "opencensus"
291
+ config.lib_version = OpenCensus::Stackdriver::VERSION
292
+ end
293
+ end
294
+ end
295
+
296
+ # Set up an at_exit hook that shuts the exporter down.
297
+ def terminate_at_exit! executor, timeout
298
+ at_exit do
299
+ executor.shutdown
300
+ unless executor.wait_for_termination timeout
301
+ executor.kill
302
+ executor.wait_for_termination timeout
303
+ end
304
+ end
305
+ end
306
+
307
+ # Export a list of stats in the current thread
308
+ def export_as_batch client, views_data
309
+ time_series = views_data.map do |view_data|
310
+ @converter.convert_time_series(
311
+ metric_prefix,
312
+ resource_type,
313
+ resource_labels,
314
+ view_data
315
+ )
316
+ end
317
+
318
+ client.create_time_series name: @project_path,
319
+ time_series: time_series.flatten
320
+ end
321
+ end
322
+ end
323
+ end
324
+ end
@@ -0,0 +1,258 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenCensus Authors
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+
18
+ module OpenCensus
19
+ module Stats
20
+ module Exporters
21
+ class Stackdriver
22
+ ##
23
+ # An object that converts OpenCensus stats data objects to Monitoring
24
+ # service protos
25
+ #
26
+ # @private
27
+ #
28
+ class Converter
29
+ ##
30
+ # Create a converter
31
+ #
32
+ # @param [String] project_id Google project ID
33
+ #
34
+ def initialize project_id
35
+ @project_id = project_id
36
+ end
37
+
38
+ # Convert view to metric descriptor
39
+ #
40
+ # @param [OpenCensus::Stats:View] view Stats view
41
+ # @param [String] metric_prefix Metric prefix name
42
+ # @return [Google::Api::MetricDescriptor]
43
+ #
44
+ def convert_metric_descriptor view, metric_prefix
45
+ descriptor = Google::Api::MetricDescriptor.new(
46
+ type: make_metric_type(metric_prefix, view.name),
47
+ display_name: view.measure.name,
48
+ metric_kind: convert_metric_kind(view.aggregation),
49
+ value_type: convert_metric_value_type(view),
50
+ unit: view.measure.unit,
51
+ labels: convert_labels(view.columns)
52
+ )
53
+
54
+ descriptor.description = view.description if view.description
55
+ descriptor
56
+ end
57
+
58
+ # Conver to lables
59
+ #
60
+ # @param [Array<String>] names
61
+ # @return [Array<Google::Api::LabelDescriptor>]
62
+ def convert_labels names
63
+ names.map do |name|
64
+ Google::Api::LabelDescriptor.new(
65
+ key: name,
66
+ value_type: Google::Api::LabelDescriptor::ValueType::STRING
67
+ )
68
+ end
69
+ end
70
+
71
+ # Convert to metric view type.
72
+ #
73
+ # @param [OpenCensus::Stats:View] view Stats view
74
+ # @return [Symbol] Metric value type
75
+ #
76
+ def convert_metric_value_type view
77
+ case view.aggregation
78
+ when OpenCensus::Stats::Aggregation::Distribution
79
+ Google::Api::MetricDescriptor::ValueType::DISTRIBUTION
80
+ when OpenCensus::Stats::Aggregation::Count
81
+ Google::Api::MetricDescriptor::ValueType::INT64
82
+ when OpenCensus::Stats::Aggregation::Sum,
83
+ OpenCensus::Stats::Aggregation::LastValue
84
+ if view.measure.int64?
85
+ Google::Api::MetricDescriptor::ValueType::INT64
86
+ else
87
+ Google::Api::MetricDescriptor::ValueType::DOUBLE
88
+ end
89
+ end
90
+ end
91
+
92
+ # Convert to metric kind
93
+ #
94
+ # @param [OpenCensus::Stats:Aggregation::LastValue,
95
+ # OpenCensus::Stats:Aggregation::Sum,
96
+ # OpenCensus::Stats:Aggregation::Count,
97
+ # OpenCensus::Stats:Aggregation::Distribution] aggregation
98
+ # Aggregation type
99
+ # @return [Symbol] Metric kind type
100
+ #
101
+ def convert_metric_kind aggregation
102
+ last_value_class = OpenCensus::Stats::Aggregation::LastValue
103
+
104
+ if aggregation.instance_of? last_value_class
105
+ return Google::Api::MetricDescriptor::MetricKind::GAUGE
106
+ end
107
+
108
+ Google::Api::MetricDescriptor::MetricKind::CUMULATIVE
109
+ end
110
+
111
+ # Convert view data to time series list
112
+ #
113
+ # @param [String] metric_prefix Metric prefix name
114
+ # @param [String] resource_type Metric resource type
115
+ # @param [Hash<String,String>] resource_labels Metric resource labels
116
+ # @param [OpenCensus::Stats::ViewData] view_data Stats view data
117
+ # @return [Array[Google::Cloud::Monitoring::V3::TimeSeries]]
118
+ #
119
+ def convert_time_series metric_prefix, resource_type, resource_labels,
120
+ view_data
121
+ view = view_data.view
122
+
123
+ view_data.data.map do |tag_values, aggr_data|
124
+ series = Google::Cloud::Monitoring::V3::TimeSeries.new(
125
+ metric: {
126
+ type: make_metric_type(metric_prefix, view.name),
127
+ labels: Hash[view.columns.zip tag_values]
128
+ },
129
+ resource: {
130
+ type: resource_type,
131
+ labels: resource_labels
132
+ },
133
+ metric_kind: convert_metric_kind(view.aggregation),
134
+ value_type: convert_metric_value_type(view)
135
+ )
136
+
137
+ series.points << convert_point(
138
+ view_data.start_time,
139
+ aggr_data.time,
140
+ view.measure,
141
+ aggr_data
142
+ )
143
+
144
+ series
145
+ end
146
+ end
147
+
148
+ # Convert aggr data to time series point proto
149
+ #
150
+ # @param [Time] start_time Start time
151
+ # @param [Time] end_time Start time
152
+ # @param [OpenCensus::Stats:Measure] measure Measure details
153
+ # @param [OpenCensus::Stats:AggregationData] aggr_data Aggregated data
154
+ # @raise [TypeError] If invalid aggr data type.
155
+ # @return [Google::Cloud::Monitoring::V3::Point]
156
+ def convert_point start_time, end_time, measure, aggr_data
157
+ case aggr_data
158
+ when OpenCensus::Stats::AggregationData::Distribution
159
+ create_distribution_point start_time, end_time, aggr_data
160
+ when OpenCensus::Stats::AggregationData::LastValue
161
+ create_number_point(
162
+ start_time,
163
+ start_time,
164
+ aggr_data.value,
165
+ measure
166
+ )
167
+ when OpenCensus::Stats::AggregationData::Sum,
168
+ OpenCensus::Stats::AggregationData::Count
169
+ create_number_point(
170
+ start_time,
171
+ end_time,
172
+ aggr_data.value,
173
+ measure
174
+ )
175
+ else
176
+ raise TypeError, "invalid aggregation type : #{aggr_data.class}"
177
+ end
178
+ end
179
+
180
+ # Create a distribution point
181
+ # @param [Time] start_time Start time
182
+ # @param [Time] end_time Start time
183
+ # @param [OpenCensus::Stats::AggregationData::Distribution] aggr_data
184
+ # @return [Google::Cloud::Monitoring::V3::Point]
185
+ #
186
+ def create_distribution_point start_time, end_time, aggr_data
187
+ value = {
188
+ count: aggr_data.count,
189
+ mean: aggr_data.mean,
190
+ sum_of_squared_deviation: aggr_data.sum_of_squared_deviation,
191
+ bucket_options: {
192
+ explicit_buckets: {
193
+ bounds: [0].concat(aggr_data.buckets)
194
+ }
195
+ },
196
+ bucket_counts: [0].concat(aggr_data.bucket_counts)
197
+ }
198
+
199
+ Google::Cloud::Monitoring::V3::Point.new(
200
+ interval: {
201
+ start_time: convert_time(start_time),
202
+ end_time: convert_time(end_time)
203
+ },
204
+ value: {
205
+ distribution_value: value
206
+ }
207
+ )
208
+ end
209
+
210
+ # Create a number point
211
+ # @param [Time] start_time Start time
212
+ # @param [Time] end_time Start time
213
+ # @param [Integer, Float] value
214
+ # @param [OpenCensus::Stats::Measure] measure Measure defination
215
+ # @return [Google::Cloud::Monitoring::V3::Point]
216
+ #
217
+ def create_number_point start_time, end_time, value, measure
218
+ value = if measure.int64?
219
+ { int64_value: value }
220
+ else
221
+ { double_value: value }
222
+ end
223
+
224
+ Google::Cloud::Monitoring::V3::Point.new(
225
+ interval: {
226
+ start_time: convert_time(start_time),
227
+ end_time: convert_time(end_time)
228
+ },
229
+ value: value
230
+ )
231
+ end
232
+
233
+ # Convert time object to protobuf timestamp
234
+ #
235
+ # @param [Time] time Ruby Time object
236
+ # @return [Google::Protobuf::Timestamp] The generated proto
237
+ #
238
+ def convert_time time
239
+ proto = Google::Protobuf::Timestamp.new
240
+ proto.from_time(time)
241
+ proto
242
+ end
243
+
244
+ ##
245
+ # Make make metric type
246
+ #
247
+ # @param [String] metric_prefix The metric prefix
248
+ # @param [String] name The name of the mertic view
249
+ # @return [String] The metric type path
250
+ #
251
+ def make_metric_type metric_prefix, name
252
+ "#{metric_prefix}/#{name}"
253
+ end
254
+ end
255
+ end
256
+ end
257
+ end
258
+ end
@@ -12,15 +12,22 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- gem "google-cloud-trace"
15
+
16
+ gem "google-cloud-trace-v2"
16
17
  gem "concurrent-ruby"
17
18
 
18
19
  require "concurrent"
19
- require "google/cloud/trace"
20
+ require "google/cloud/env"
20
21
  require "google/cloud/trace/v2"
21
22
 
22
23
  module OpenCensus
24
+ ##
25
+ # OpenCensus Trace provides a standard interface for distributed tracing.
26
+ #
23
27
  module Trace
28
+ ##
29
+ # The exporters module is a namespace for trace exporters.
30
+ #
24
31
  module Exporters
25
32
  ##
26
33
  # The Stackdriver exporter for OpenCensus Trace exports captured spans
@@ -49,8 +56,7 @@ module OpenCensus
49
56
  # Optional. Most applications can leave this set to the default.
50
57
  # @param [Integer] timeout The default timeout for API requests, in
51
58
  # seconds. Optional.
52
- # @param [Hash] client_config An optional set of additional
53
- # configuration values for the API connection.
59
+ # @param [Hash] client_config Unused.
54
60
  # @param [Integer] max_queue The maximum number of API requests that
55
61
  # can be queued for background operation. If the queue exceeds this
56
62
  # value, additional requests will be run in the calling thread
@@ -68,13 +74,14 @@ module OpenCensus
68
74
  credentials: nil,
69
75
  scope: nil,
70
76
  timeout: nil,
71
- client_config: nil,
77
+ client_config: nil, # rubocop:disable Lint/UnusedMethodArgument
72
78
  max_queue: 1000,
73
79
  max_threads: 1,
74
80
  auto_terminate_time: 10,
75
81
  mock_client: nil
76
- @project_id = final_project_id project_id
77
-
82
+ @project_id = project_id ||
83
+ ENV["GOOGLE_CLOUD_PROJECT"] ||
84
+ Google::Cloud.env.project_id
78
85
  @executor = create_executor max_threads, max_queue
79
86
  if auto_terminate_time
80
87
  terminate_at_exit! @executor, auto_terminate_time
@@ -84,12 +91,8 @@ module OpenCensus
84
91
  @client_promise =
85
92
  Concurrent::Promise.fulfill mock_client, executor: @executor
86
93
  else
87
- credentials = final_credentials credentials, scope
88
- scope ||= Google::Cloud.configure.trace.scope
89
- timeout ||= Google::Cloud.configure.trace.timeout
90
- client_config ||= Google::Cloud.configure.trace.client_config
91
94
  @client_promise = create_client_promise \
92
- @executor, credentials, scope, client_config, timeout
95
+ @executor, credentials, scope, timeout
93
96
  end
94
97
  end
95
98
 
@@ -191,7 +194,7 @@ module OpenCensus
191
194
  def create_executor max_threads, max_queue
192
195
  if max_threads >= 1
193
196
  Concurrent::ThreadPoolExecutor.new \
194
- min_length: 1, max_length: max_threads,
197
+ min_threads: 1, max_threads: max_threads,
195
198
  max_queue: max_queue, fallback_policy: :caller_runs,
196
199
  auto_terminate: false
197
200
  else
@@ -203,17 +206,15 @@ module OpenCensus
203
206
  # We create the client lazily so grpc doesn't get initialized until
204
207
  # we actually need it. This is important because if it is intialized
205
208
  # too early, before a fork, it can go into a bad state.
206
- def create_client_promise executor, credentials, scopes, client_config,
207
- timeout
209
+ def create_client_promise executor, credentials, scopes, timeout
208
210
  Concurrent::Promise.new executor: executor do
209
- Google::Cloud::Trace::V2.new(
210
- credentials: credentials,
211
- scopes: scopes,
212
- client_config: client_config,
213
- timeout: timeout,
214
- lib_name: "opencensus",
215
- lib_version: OpenCensus::Stackdriver::VERSION
216
- )
211
+ Google::Cloud::Trace::V2::TraceService::Client.new do |config|
212
+ config.credentials = credentials if credentials
213
+ config.scope = scopes if scopes
214
+ config.timeout = timeout if timeout
215
+ config.lib_name = "opencensus"
216
+ config.lib_version = OpenCensus::Stackdriver::VERSION
217
+ end
217
218
  end
218
219
  end
219
220
 
@@ -228,32 +229,12 @@ module OpenCensus
228
229
  end
229
230
  end
230
231
 
231
- # Fall back to default project ID
232
- def final_project_id project_id
233
- project_id ||
234
- Google::Cloud.configure.trace.project_id ||
235
- Google::Cloud.configure.project_id ||
236
- Google::Cloud.env.project_id
237
- end
238
-
239
- # Fall back to default credentials, and wrap in a creds object
240
- def final_credentials credentials, scope
241
- credentials ||=
242
- Google::Cloud.configure.trace.credentials ||
243
- Google::Cloud.configure.credentials ||
244
- Google::Cloud::Trace::Credentials.default(scope: scope)
245
- unless credentials.is_a? Google::Auth::Credentials
246
- credentials =
247
- Google::Cloud::Trace::Credentials.new credentials, scope: scope
248
- end
249
- credentials
250
- end
251
-
252
232
  # Export a list of spans in a single batch write, in the current thread
253
233
  def export_as_batch client, spans
254
234
  converter = Converter.new project_id
255
235
  span_protos = Array(spans).map { |span| converter.convert_span span }
256
- client.batch_write_spans "projects/#{project_id}", span_protos
236
+ client.batch_write_spans name: "projects/#{project_id}",
237
+ spans: span_protos
257
238
  end
258
239
  end
259
240
  end
@@ -12,6 +12,7 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+
15
16
  require "google/devtools/cloudtrace/v2/trace_pb"
16
17
  require "google/protobuf/well_known_types"
17
18
 
@@ -35,7 +36,7 @@ module OpenCensus
35
36
  # @private
36
37
  # Alias for the V2 Cloudtrace protos namespace
37
38
  #
38
- TraceProtos = Google::Devtools::Cloudtrace::V2
39
+ TraceProtos = Google::Cloud::Trace::V2
39
40
 
40
41
  ##
41
42
  # @private
@@ -52,6 +53,20 @@ module OpenCensus
52
53
  "opencensus-ruby [#{::OpenCensus::VERSION}] ruby-stackdriver-" \
53
54
  "exporter [#{::OpenCensus::Stackdriver::VERSION}]"
54
55
 
56
+ ##
57
+ # @private
58
+ # Mapping for certain well-known attributes defined in
59
+ # https://github.com/census-instrumentation/opencensus-specs/blob/master/trace/HTTP.md
60
+ #
61
+ ATTRIBUTE_NAME_MAPPING = {
62
+ "http.host" => "/http/host",
63
+ "http.method" => "/http/method",
64
+ "http.path" => "/http/path",
65
+ "http.route" => "/http/route",
66
+ "http.user_agent" => "/http/user_agent",
67
+ "http.status_code" => "/http/status_code"
68
+ }.freeze
69
+
55
70
  ##
56
71
  # Create a converter
57
72
  #
@@ -68,7 +83,7 @@ module OpenCensus
68
83
  # Convert a span object.
69
84
  #
70
85
  # @param [OpenCensus::Trace::Span] obj OpenCensus span object
71
- # @return [Google::Devtools::Cloudtrace::V2::Span] The generated
86
+ # @return [Google::Cloud::Trace::V2::Span] The generated
72
87
  # proto
73
88
  #
74
89
  def convert_span obj
@@ -117,7 +132,7 @@ module OpenCensus
117
132
  # @param [String] str The string
118
133
  # @param [Integer] truncated_byte_count The number of bytes omitted.
119
134
  # Defaults to 0.
120
- # @return [Google::Devtools::Cloudtrace::V2::TruncatableString] The
135
+ # @return [Google::Cloud::Trace::V2::TruncatableString] The
121
136
  # generated proto
122
137
  #
123
138
  def make_truncatable_string str, truncated_byte_count = 0
@@ -131,7 +146,7 @@ module OpenCensus
131
146
  #
132
147
  # @param [OpenCensus::Trace::TruncatableString] obj OpenCensus
133
148
  # truncatable string object
134
- # @return [Google::Devtools::Cloudtrace::V2::TruncatableString] The
149
+ # @return [Google::Cloud::Trace::V2::TruncatableString] The
135
150
  # generated proto
136
151
  #
137
152
  def convert_truncatable_string obj
@@ -155,7 +170,7 @@ module OpenCensus
155
170
  #
156
171
  # @param [OpenCensus::Trace::TruncatableString, Integer, boolean]
157
172
  # obj Object to convert
158
- # @return [Google::Devtools::Cloudtrace::V2::AttributeValue] The
173
+ # @return [Google::Cloud::Trace::V2::AttributeValue] The
159
174
  # generated proto
160
175
  #
161
176
  def convert_attribute_value obj
@@ -170,6 +185,16 @@ module OpenCensus
170
185
  end
171
186
  end
172
187
 
188
+ ##
189
+ # Map OpenCensus attribute name to Stackdriver Trace name.
190
+ #
191
+ # @param [String] name OpenCensus attribute name
192
+ # @return [String] Corresponding Stackdriver Trace attribute.
193
+ #
194
+ def convert_attribute_name name
195
+ ATTRIBUTE_NAME_MAPPING[name] || name
196
+ end
197
+
173
198
  ##
174
199
  # Convert an attributes hash
175
200
  #
@@ -177,7 +202,7 @@ module OpenCensus
177
202
  # @param [Integer] dropped_attributes_count Number of dropped
178
203
  # @param [Boolean] include_agent_attribute Include the `g.co/agent`
179
204
  # attribute in the result. Default is false.
180
- # @return [Google::Devtools::Cloudtrace::V2::Attributes] The
205
+ # @return [Google::Cloud::Trace::V2::Attributes] The
181
206
  # generated proto
182
207
  #
183
208
  def convert_attributes attributes, dropped_attributes_count,
@@ -187,7 +212,8 @@ module OpenCensus
187
212
  attribute_map[AGENT_KEY] = convert_attribute_value AGENT_VALUE
188
213
  end
189
214
  attributes.each do |k, v|
190
- attribute_map[k] = convert_attribute_value v
215
+ attribute_map[convert_attribute_name k] =
216
+ convert_attribute_value v
191
217
  end
192
218
  TraceProtos::Span::Attributes.new \
193
219
  attribute_map: attribute_map,
@@ -199,7 +225,7 @@ module OpenCensus
199
225
  #
200
226
  # @param [Thread::Backtrace::Location] frame The backtrace element to
201
227
  # convert
202
- # @return [Google::Devtools::Cloudtrace::V2::StackTrace::StackFrame]
228
+ # @return [Google::Cloud::Trace::V2::StackTrace::StackFrame]
203
229
  # The generated proto
204
230
  #
205
231
  def convert_stack_frame frame
@@ -216,7 +242,7 @@ module OpenCensus
216
242
  # element array to convert
217
243
  # @param [Integer] dropped_frames_count Frames that were dropped
218
244
  # @param [Integer] stack_trace_hash_id Hash of the data
219
- # @return [Google::Devtools::Cloudtrace::V2::StackTrace] The
245
+ # @return [Google::Cloud::Trace::V2::StackTrace] The
220
246
  # generated proto
221
247
  #
222
248
  def convert_stack_trace backtrace, dropped_frames_count,
@@ -241,7 +267,7 @@ module OpenCensus
241
267
  # @param [OpenCensus::Trace::Annotation] annotation The annotation
242
268
  # object to convert
243
269
  # @return
244
- # [Google::Devtools::Cloudtrace::V2::Span::TimeEvent::Annotation]
270
+ # [Google::Cloud::Trace::V2::Span::TimeEvent::Annotation]
245
271
  # The generated proto
246
272
  #
247
273
  def convert_annotation annotation
@@ -261,7 +287,7 @@ module OpenCensus
261
287
  # @param [OpenCensus::Trace::MessageEvent] message_event The message
262
288
  # event object to convert
263
289
  # @return
264
- # [Google::Devtools::Cloudtrace::V2::Span::TimeEvent::MessageEvent]
290
+ # [Google::Cloud::Trace::V2::Span::TimeEvent::MessageEvent]
265
291
  # The generated proto
266
292
  #
267
293
  def convert_message_event message_event
@@ -271,7 +297,7 @@ module OpenCensus
271
297
  id: message_event.id,
272
298
  uncompressed_size_bytes: message_event.uncompressed_size,
273
299
  compressed_size_bytes: message_event.compressed_size
274
- Google::Devtools::Cloudtrace::V2::Span::TimeEvent.new \
300
+ TraceProtos::Span::TimeEvent.new \
275
301
  time: convert_time(message_event.time),
276
302
  message_event: message_event_proto
277
303
  end
@@ -285,7 +311,7 @@ module OpenCensus
285
311
  # annotations
286
312
  # @param [Integer] dropped_message_events_count Number of dropped
287
313
  # message events
288
- # @return [Google::Devtools::Cloudtrace::V2::Span::TimeEvents] The
314
+ # @return [Google::Cloud::Trace::V2::Span::TimeEvents] The
289
315
  # generated proto
290
316
  #
291
317
  def convert_time_events time_events, dropped_annotations_count,
@@ -310,7 +336,7 @@ module OpenCensus
310
336
  # Convert a link object
311
337
  #
312
338
  # @param [OpenCensus::Trace::Link] link The link object to convert
313
- # @return [Google::Devtools::Cloudtrace::V2::Span::Link] The
339
+ # @return [Google::Cloud::Trace::V2::Span::Link] The
314
340
  # generated proto
315
341
  #
316
342
  def convert_link link
@@ -329,7 +355,7 @@ module OpenCensus
329
355
  # @param [Array<OpenCensus::Trace::Link>] links The link objects to
330
356
  # convert
331
357
  # @param [Integer] dropped_links_count Number of dropped links
332
- # @return [Google::Devtools::Cloudtrace::V2::Span::Links] The
358
+ # @return [Google::Cloud::Trace::V2::Span::Links] The
333
359
  # generated proto
334
360
  #
335
361
  def convert_links links, dropped_links_count
@@ -347,6 +373,7 @@ module OpenCensus
347
373
  #
348
374
  def convert_optional_status status
349
375
  return nil if status.nil?
376
+
350
377
  Google::Rpc::Status.new code: status.code, message: status.message
351
378
  end
352
379
 
@@ -358,6 +385,7 @@ module OpenCensus
358
385
  #
359
386
  def convert_optional_bool value
360
387
  return nil if value.nil?
388
+
361
389
  Google::Protobuf::BoolValue.new value: value
362
390
  end
363
391
 
@@ -369,6 +397,7 @@ module OpenCensus
369
397
  #
370
398
  def convert_optional_int32 value
371
399
  return nil if value.nil?
400
+
372
401
  Google::Protobuf::Int32Value.new value: value
373
402
  end
374
403
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opencensus-stackdriver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-22 00:00:00.000000000 Z
11
+ date: 2020-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -25,47 +25,75 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: google-cloud-trace
28
+ name: google-cloud-env
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.31'
33
+ version: '1.3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.31'
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: google-cloud-monitoring-v3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: google-cloud-trace-v2
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.1'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: opencensus
43
71
  requirement: !ruby/object:Gem::Requirement
44
72
  requirements:
45
73
  - - "~>"
46
74
  - !ruby/object:Gem::Version
47
- version: '0.3'
75
+ version: '0.5'
48
76
  type: :runtime
49
77
  prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
80
  - - "~>"
53
81
  - !ruby/object:Gem::Version
54
- version: '0.3'
82
+ version: '0.5'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: bundler
57
85
  requirement: !ruby/object:Gem::Requirement
58
86
  requirements:
59
- - - "~>"
87
+ - - ">="
60
88
  - !ruby/object:Gem::Version
61
- version: '1.16'
89
+ version: '1.17'
62
90
  type: :development
63
91
  prerelease: false
64
92
  version_requirements: !ruby/object:Gem::Requirement
65
93
  requirements:
66
- - - "~>"
94
+ - - ">="
67
95
  - !ruby/object:Gem::Version
68
- version: '1.16'
96
+ version: '1.17'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: faraday
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +114,14 @@ dependencies:
86
114
  requirements:
87
115
  - - "~>"
88
116
  - !ruby/object:Gem::Version
89
- version: '5.0'
117
+ version: '5.14'
90
118
  type: :development
91
119
  prerelease: false
92
120
  version_requirements: !ruby/object:Gem::Requirement
93
121
  requirements:
94
122
  - - "~>"
95
123
  - !ruby/object:Gem::Version
96
- version: '5.0'
124
+ version: '5.14'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: minitest-focus
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -142,14 +170,14 @@ dependencies:
142
170
  requirements:
143
171
  - - "~>"
144
172
  - !ruby/object:Gem::Version
145
- version: '0.52'
173
+ version: 0.59.2
146
174
  type: :development
147
175
  prerelease: false
148
176
  version_requirements: !ruby/object:Gem::Requirement
149
177
  requirements:
150
178
  - - "~>"
151
179
  - !ruby/object:Gem::Version
152
- version: '0.52'
180
+ version: 0.59.2
153
181
  - !ruby/object:Gem::Dependency
154
182
  name: yard
155
183
  requirement: !ruby/object:Gem::Requirement
@@ -195,6 +223,8 @@ files:
195
223
  - lib/opencensus-stackdriver.rb
196
224
  - lib/opencensus/stackdriver.rb
197
225
  - lib/opencensus/stackdriver/version.rb
226
+ - lib/opencensus/stats/exporters/stackdriver.rb
227
+ - lib/opencensus/stats/exporters/stackdriver/converter.rb
198
228
  - lib/opencensus/trace/exporters/stackdriver.rb
199
229
  - lib/opencensus/trace/exporters/stackdriver/converter.rb
200
230
  homepage: https://github.com/census-instrumentation/ruby-stackdriver-exporter
@@ -209,15 +239,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
209
239
  requirements:
210
240
  - - ">="
211
241
  - !ruby/object:Gem::Version
212
- version: 2.2.0
242
+ version: 2.4.0
213
243
  required_rubygems_version: !ruby/object:Gem::Requirement
214
244
  requirements:
215
245
  - - ">="
216
246
  - !ruby/object:Gem::Version
217
247
  version: '0'
218
248
  requirements: []
219
- rubyforge_project:
220
- rubygems_version: 2.7.6
249
+ rubygems_version: 3.0.3
221
250
  signing_key:
222
251
  specification_version: 4
223
252
  summary: Stackdriver exporter for OpenCensus