opencensus-stackdriver 0.1.2 → 0.4.0

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
  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