opencensus-stackdriver 0.1.0.pre1

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.
@@ -0,0 +1,21 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ require "yard"
4
+
5
+ require "rubocop/rake_task"
6
+ RuboCop::RakeTask.new
7
+
8
+ Rake::TestTask.new :test do |t|
9
+ t.libs << "test"
10
+ t.libs << "lib"
11
+ t.test_files = FileList["test/**/*_test.rb"]
12
+ t.warning = false
13
+ end
14
+
15
+ YARD::Rake::YardocTask.new do |t|
16
+ t.files = ['lib/**/*.rb'] # optional
17
+ t.options = ['--output-dir', 'docs/api'] # optional
18
+ t.stats_options = ['--list-undoc'] # optional
19
+ end
20
+
21
+ task :default => [:test, :rubocop, :yard]
@@ -0,0 +1,15 @@
1
+ # Copyright 2018 OpenCensus Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "opencensus/stackdriver"
@@ -0,0 +1,25 @@
1
+ # Copyright 2018 OpenCensus Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "opencensus"
16
+
17
+ module OpenCensus
18
+ ## Information about the Stackdriver exporter plugin
19
+ module Stackdriver
20
+ end
21
+ end
22
+
23
+ require "opencensus/stackdriver/version"
24
+ require "opencensus/trace/exporters/stackdriver"
25
+ require "opencensus/trace/exporters/stackdriver/converter"
@@ -0,0 +1,20 @@
1
+ # Copyright 2018 OpenCensus Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ module OpenCensus
16
+ module Stackdriver
17
+ ## Current OpenCensus Stackdriver plugin version
18
+ VERSION = "0.1.0.pre1".freeze
19
+ end
20
+ end
@@ -0,0 +1,259 @@
1
+ # Copyright 2018 OpenCensus Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ gem "google-cloud-trace"
16
+ gem "concurrent-ruby"
17
+
18
+ require "concurrent"
19
+ require "google/cloud/trace"
20
+ require "google/cloud/trace/v2"
21
+
22
+ module OpenCensus
23
+ module Trace
24
+ module Exporters
25
+ ##
26
+ # The Stackdriver exporter for OpenCensus Trace exports captured spans
27
+ # to a Google Stackdriver project. It calls the Stackdriver Trace API in
28
+ # a background thread pool.
29
+ #
30
+ class Stackdriver
31
+ ##
32
+ # Create a Stackdriver exporter.
33
+ #
34
+ # @param [String] project_id The project identifier for the Stackdriver
35
+ # Trace service you are connecting to. If you are running on Google
36
+ # Cloud hosting (e.g. Compute Engine, Kubernetes Engine, or App
37
+ # Engine), this parameter is optional and will default to the
38
+ # hosting project. Otherwise, it is required.
39
+ # @param [String, Hash, Google::Auth::Credentials] credentials The
40
+ # Stackdriver API credentials, which can be a path to a keyfile as
41
+ # a String, the contents of a keyfile as a Hash, or a
42
+ # Google::Auth::Credentials object. If you are running on Google
43
+ # Cloud hosting (e.g. Compute Engine, Kubernetes Engine, or App
44
+ # Engine), this parameter is optional and will default to the
45
+ # credentials provided by the hosting project. Otherwise, it is
46
+ # required.
47
+ # @param [String, Array<String>] scope The OAuth 2.0 scopes controlling
48
+ # the set of resources and operations the API client can access.
49
+ # Optional. Most applications can leave this set to the default.
50
+ # @param [Integer] timeout The default timeout for API requests, in
51
+ # seconds. Optional.
52
+ # @param [Hash] client_config An optional set of additional
53
+ # configuration values for the API connection.
54
+ # @param [Integer] max_queue The maximum number of API requests that
55
+ # can be queued for background operation. If the queue exceeds this
56
+ # value, additional requests will be run in the calling thread
57
+ # rather than in the background. Set to 0 to allow the queue to
58
+ # grow indefinitely. Default is 1000.
59
+ # @param [Integer] max_threads The maximum number of threads that can
60
+ # be spun up to handle API requests. Default is 1. If set to 0,
61
+ # backgrounding will be disabled and all requests will run in the
62
+ # calling thread.
63
+ # @param [Integer] auto_terminate_time The time in seconds allotted to
64
+ # complete any pending background requests when Ruby is exiting.
65
+ #
66
+ def initialize \
67
+ project_id: nil,
68
+ credentials: nil,
69
+ scope: nil,
70
+ timeout: nil,
71
+ client_config: nil,
72
+ max_queue: 1000,
73
+ max_threads: 1,
74
+ auto_terminate_time: 10,
75
+ mock_client: nil
76
+ @project_id = final_project_id project_id
77
+
78
+ @executor = create_executor max_threads, max_queue
79
+ if auto_terminate_time
80
+ terminate_at_exit! @executor, auto_terminate_time
81
+ end
82
+
83
+ if mock_client
84
+ @client_promise =
85
+ Concurrent::Promise.fulfill mock_client, executor: @executor
86
+ 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
+ @client_promise = create_client_promise \
92
+ @executor, credentials, scope, client_config, timeout
93
+ end
94
+ end
95
+
96
+ ##
97
+ # The project ID
98
+ # @return [String]
99
+ #
100
+ attr_reader :project_id
101
+
102
+ ##
103
+ # Export spans to Stackdriver asynchronously.
104
+ #
105
+ # @param [Array<OpenCensus::Trace::Span>] spans The captured spans to
106
+ # export to Stackdriver
107
+ #
108
+ def export spans
109
+ raise "Exporter is no longer running" unless @executor.running?
110
+
111
+ @client_promise.execute
112
+ export_promise = @client_promise.then do |client|
113
+ export_as_batch(client, spans)
114
+ end
115
+ export_promise.on_error do |reason|
116
+ warn "Unable to export to Stackdriver because: #{reason}"
117
+ end
118
+
119
+ true
120
+ end
121
+
122
+ ##
123
+ # Returns true if this exporter is running and will accept further
124
+ # export requests. Returns false once the exporter begins shutting down.
125
+ #
126
+ # @return [boolean]
127
+ #
128
+ def running?
129
+ @executor.running?
130
+ end
131
+
132
+ ##
133
+ # Returns true if this exporter has finished shutting down and all
134
+ # pending spans have been sent.
135
+ #
136
+ # @return [boolean]
137
+ #
138
+ def shutdown?
139
+ @executor.shutdown?
140
+ end
141
+
142
+ ##
143
+ # Returns true if this exporter has begun shutting down and is no
144
+ # longer accepting export requests, but is still running queued
145
+ # requests in the background.
146
+ #
147
+ # @return [boolean]
148
+ #
149
+ def shuttingdown?
150
+ @executor.shuttingdown?
151
+ end
152
+
153
+ ##
154
+ # Begin shutting down the exporter gracefully. After this operation is
155
+ # performed, the exporter will no longer accept export requests, but
156
+ # will finish any pending requests in the background.
157
+ #
158
+ def shutdown
159
+ @executor.shutdown
160
+ self
161
+ end
162
+
163
+ ##
164
+ # Begin shutting down the exporter forcefully. After this operation is
165
+ # performed, the exporter will no longer accept export requests, and
166
+ # will finish any currently running export requests, but will cancel
167
+ # all requests that are still pending in the queue.
168
+ #
169
+ def kill
170
+ @executor.kill
171
+ self
172
+ end
173
+
174
+ ##
175
+ # Wait for the exporter to finish shutting down.
176
+ #
177
+ # @param [Integer, nil] timeout A timeout in seconds, or nil for no
178
+ # timeout.
179
+ # @return [boolean] true if the exporter is shut down, or false if the
180
+ # wait timed out.
181
+ #
182
+ def wait_for_termination timeout = nil
183
+ @executor.wait_for_termination timeout
184
+ end
185
+
186
+ private
187
+
188
+ # Create the executor
189
+ def create_executor max_threads, max_queue
190
+ if max_threads >= 1
191
+ Concurrent::ThreadPoolExecutor.new \
192
+ min_length: 1, max_length: max_threads,
193
+ max_queue: max_queue, fallback_policy: :caller_runs,
194
+ auto_terminate: false
195
+ else
196
+ Concurrent::ImmediateExecutor.new
197
+ end
198
+ end
199
+
200
+ # Create the client promise.
201
+ # We create the client lazily so grpc doesn't get initialized until
202
+ # we actually need it. This is important because if it is intialized
203
+ # too early, before a fork, it can go into a bad state.
204
+ def create_client_promise executor, credentials, scopes, client_config,
205
+ timeout
206
+ Concurrent::Promise.new executor: executor do
207
+ Google::Cloud::Trace::V2.new(
208
+ credentials: credentials,
209
+ scopes: scopes,
210
+ client_config: client_config,
211
+ timeout: timeout,
212
+ lib_name: "opencensus",
213
+ lib_version: OpenCensus::Stackdriver::VERSION
214
+ )
215
+ end
216
+ end
217
+
218
+ # Set up an at_exit hook that shuts the exporter down.
219
+ def terminate_at_exit! executor, timeout
220
+ at_exit do
221
+ executor.shutdown
222
+ unless executor.wait_for_termination timeout
223
+ executor.kill
224
+ executor.wait_for_termination timeout
225
+ end
226
+ end
227
+ end
228
+
229
+ # Fall back to default project ID
230
+ def final_project_id project_id
231
+ project_id ||
232
+ Google::Cloud.configure.trace.project_id ||
233
+ Google::Cloud.configure.project_id ||
234
+ Google::Cloud.env.project_id
235
+ end
236
+
237
+ # Fall back to default credentials, and wrap in a creds object
238
+ def final_credentials credentials, scope
239
+ credentials ||=
240
+ Google::Cloud.configure.trace.credentials ||
241
+ Google::Cloud.configure.credentials ||
242
+ Google::Cloud::Trace::Credentials.default(scope: scope)
243
+ unless credentials.is_a? Google::Auth::Credentials
244
+ credentials =
245
+ Google::Cloud::Trace::Credentials.new credentials, scope: scope
246
+ end
247
+ credentials
248
+ end
249
+
250
+ # Export a list of spans in a single batch write, in the current thread
251
+ def export_as_batch client, spans
252
+ converter = Converter.new project_id
253
+ span_protos = Array(spans).map { |span| converter.convert_span span }
254
+ client.batch_write_spans "projects/#{project_id}", span_protos
255
+ end
256
+ end
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,356 @@
1
+ # Copyright 2018 OpenCensus Authors
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "google/devtools/cloudtrace/v2/trace_pb"
16
+ require "google/protobuf/well_known_types"
17
+
18
+ module OpenCensus
19
+ module Trace
20
+ module Exporters
21
+ class Stackdriver
22
+ ##
23
+ # An object that converts OpenCensus span data objects to Stackdriver
24
+ # Trace V2 protos.
25
+ #
26
+ # You should use one converter instance to convert the spans for a
27
+ # single export request, because the converter will keep track of and
28
+ # omit duplicate stack traces. Use a new converter instance for the
29
+ # next request.
30
+ #
31
+ # @private
32
+ #
33
+ class Converter
34
+ ##
35
+ # @private
36
+ # Alias for the V2 Cloudtrace protos namespace
37
+ #
38
+ TraceProtos = Google::Devtools::Cloudtrace::V2
39
+
40
+ ##
41
+ # Create a converter
42
+ #
43
+ # @param [String] project_id Google project ID
44
+ #
45
+ def initialize project_id
46
+ @project_id = project_id
47
+ @stack_trace_hash_ids = {}
48
+ end
49
+
50
+ # rubocop:disable Metrics/AbcSize
51
+
52
+ ##
53
+ # Convert a span object.
54
+ #
55
+ # @param [OpenCensus::Trace::Span] obj OpenCensus span object
56
+ # @return [Google::Devtools::Cloudtrace::V2::Span] The generated
57
+ # proto
58
+ #
59
+ def convert_span obj
60
+ TraceProtos::Span.new \
61
+ name: make_resource_name(@project_id, obj.trace_id, obj.span_id),
62
+ span_id: obj.span_id,
63
+ parent_span_id: obj.parent_span_id || "",
64
+ display_name: convert_truncatable_string(obj.name),
65
+ start_time: convert_time(obj.start_time),
66
+ end_time: convert_time(obj.end_time),
67
+ attributes:
68
+ convert_attributes(obj.attributes,
69
+ obj.dropped_attributes_count),
70
+ stack_trace:
71
+ convert_stack_trace(obj.stack_trace, obj.dropped_frames_count,
72
+ obj.stack_trace_hash_id),
73
+ time_events:
74
+ convert_time_events(obj.time_events,
75
+ obj.dropped_annotations_count,
76
+ obj.dropped_message_events_count),
77
+ links: convert_links(obj.links, obj.dropped_links_count),
78
+ status: convert_optional_status(obj.status),
79
+ same_process_as_parent_span:
80
+ convert_optional_bool(obj.same_process_as_parent_span),
81
+ child_span_count: convert_optional_int32(obj.child_span_count)
82
+ end
83
+
84
+ # rubocop:enable Metrics/AbcSize
85
+
86
+ ##
87
+ # Make a span resource name.
88
+ #
89
+ # @param [String] project_id The project ID
90
+ # @param [String] trace_id The project ID
91
+ # @param [String] span_id The project ID
92
+ # @return [String] The resource na,e
93
+ #
94
+ def make_resource_name project_id, trace_id, span_id
95
+ "projects/#{project_id}/traces/#{trace_id}/spans/#{span_id}"
96
+ end
97
+
98
+ ##
99
+ # Create a truncatable string proto.
100
+ #
101
+ # @param [String] str The string
102
+ # @param [Integer] truncated_byte_count The number of bytes omitted.
103
+ # Defaults to 0.
104
+ # @return [Google::Devtools::Cloudtrace::V2::TruncatableString] The
105
+ # generated proto
106
+ #
107
+ def make_truncatable_string str, truncated_byte_count = 0
108
+ TraceProtos::TruncatableString.new \
109
+ value: str,
110
+ truncated_byte_count: truncated_byte_count
111
+ end
112
+
113
+ ##
114
+ # Convert a truncatable string object.
115
+ #
116
+ # @param [OpenCensus::Trace::TruncatableString] obj OpenCensus
117
+ # truncatable string object
118
+ # @return [Google::Devtools::Cloudtrace::V2::TruncatableString] The
119
+ # generated proto
120
+ #
121
+ def convert_truncatable_string obj
122
+ make_truncatable_string obj.value, obj.truncated_byte_count
123
+ end
124
+
125
+ ##
126
+ # Convert a time object.
127
+ #
128
+ # @param [Time] time Ruby Time object
129
+ # @return [Google::Protobuf::Timestamp] The generated proto
130
+ #
131
+ def convert_time time
132
+ proto = Google::Protobuf::Timestamp.new
133
+ proto.from_time(time)
134
+ proto
135
+ end
136
+
137
+ ##
138
+ # Convert a value that can be used for an attribute.
139
+ #
140
+ # @param [OpenCensus::Trace::TruncatableString, Integer, boolean]
141
+ # obj Object to convert
142
+ # @return [Google::Devtools::Cloudtrace::V2::AttributeValue] The
143
+ # generated proto
144
+ #
145
+ def convert_attribute_value obj
146
+ case obj
147
+ when OpenCensus::Trace::TruncatableString
148
+ TraceProtos::AttributeValue.new \
149
+ string_value: convert_truncatable_string(obj)
150
+ when Integer
151
+ TraceProtos::AttributeValue.new int_value: obj
152
+ when true, false
153
+ TraceProtos::AttributeValue.new bool_value: obj
154
+ end
155
+ end
156
+
157
+ ##
158
+ # Convert an attributes hash
159
+ #
160
+ # @param [Hash] attributes The map of attribute values to convert
161
+ # @param [Integer] dropped_attributes_count Number of dropped
162
+ # @return [Google::Devtools::Cloudtrace::V2::Attributes] The
163
+ # generated proto
164
+ #
165
+ def convert_attributes attributes, dropped_attributes_count
166
+ attribute_map = {}
167
+ attributes.each do |k, v|
168
+ attribute_map[k] = convert_attribute_value v
169
+ end
170
+ TraceProtos::Span::Attributes.new \
171
+ attribute_map: attribute_map,
172
+ dropped_attributes_count: dropped_attributes_count
173
+ end
174
+
175
+ ##
176
+ # Convert a single stack frame as a Thread::Backtrace::Location
177
+ #
178
+ # @param [Thread::Backtrace::Location] frame The backtrace element to
179
+ # convert
180
+ # @return [Google::Devtools::Cloudtrace::V2::StackTrace::StackFrame]
181
+ # The generated proto
182
+ #
183
+ def convert_stack_frame frame
184
+ TraceProtos::StackTrace::StackFrame.new \
185
+ function_name: make_truncatable_string(frame.label),
186
+ file_name: make_truncatable_string(frame.path),
187
+ line_number: frame.lineno
188
+ end
189
+
190
+ ##
191
+ # Convert a full backtrace.
192
+ #
193
+ # @param [Array<Thread::Backtrace::Location>] backtrace The backtrace
194
+ # element array to convert
195
+ # @param [Integer] dropped_frames_count Frames that were dropped
196
+ # @param [Integer] stack_trace_hash_id Hash of the data
197
+ # @return [Google::Devtools::Cloudtrace::V2::StackTrace] The
198
+ # generated proto
199
+ #
200
+ def convert_stack_trace backtrace, dropped_frames_count,
201
+ stack_trace_hash_id
202
+ if @stack_trace_hash_ids[stack_trace_hash_id]
203
+ return TraceProtos::StackTrace.new \
204
+ stack_trace_hash_id: stack_trace_hash_id
205
+ end
206
+ @stack_trace_hash_ids[stack_trace_hash_id] = true
207
+ frame_protos = backtrace.map { |frame| convert_stack_frame(frame) }
208
+ frames_proto = TraceProtos::StackTrace::StackFrames.new \
209
+ frame: frame_protos,
210
+ dropped_frames_count: dropped_frames_count
211
+ TraceProtos::StackTrace.new \
212
+ stack_frames: frames_proto,
213
+ stack_trace_hash_id: stack_trace_hash_id
214
+ end
215
+
216
+ ##
217
+ # Convert an annotation object
218
+ #
219
+ # @param [OpenCensus::Trace::Annotation] annotation The annotation
220
+ # object to convert
221
+ # @return
222
+ # [Google::Devtools::Cloudtrace::V2::Span::TimeEvent::Annotation]
223
+ # The generated proto
224
+ #
225
+ def convert_annotation annotation
226
+ annotation_proto = TraceProtos::Span::TimeEvent::Annotation.new \
227
+ description: convert_truncatable_string(annotation.description),
228
+ attributes:
229
+ convert_attributes(annotation.attributes,
230
+ annotation.dropped_attributes_count)
231
+ TraceProtos::Span::TimeEvent.new \
232
+ time: convert_time(annotation.time),
233
+ annotation: annotation_proto
234
+ end
235
+
236
+ ##
237
+ # Convert a message event object
238
+ #
239
+ # @param [OpenCensus::Trace::MessageEvent] message_event The message
240
+ # event object to convert
241
+ # @return
242
+ # [Google::Devtools::Cloudtrace::V2::Span::TimeEvent::MessageEvent]
243
+ # The generated proto
244
+ #
245
+ def convert_message_event message_event
246
+ message_event_proto =
247
+ TraceProtos::Span::TimeEvent::MessageEvent.new \
248
+ type: message_event.type,
249
+ id: message_event.id,
250
+ uncompressed_size_bytes: message_event.uncompressed_size,
251
+ compressed_size_bytes: message_event.compressed_size
252
+ Google::Devtools::Cloudtrace::V2::Span::TimeEvent.new \
253
+ time: convert_time(message_event.time),
254
+ message_event: message_event_proto
255
+ end
256
+
257
+ ##
258
+ # Convert a list of time event objects
259
+ #
260
+ # @param [Array<OpenCensus::Trace::TimeEvent>] time_events The time
261
+ # event objects to convert
262
+ # @param [Integer] dropped_annotations_count Number of dropped
263
+ # annotations
264
+ # @param [Integer] dropped_message_events_count Number of dropped
265
+ # message events
266
+ # @return [Google::Devtools::Cloudtrace::V2::Span::TimeEvents] The
267
+ # generated proto
268
+ #
269
+ def convert_time_events time_events, dropped_annotations_count,
270
+ dropped_message_events_count
271
+ time_event_protos = time_events.map do |time_event|
272
+ case time_event
273
+ when OpenCensus::Trace::Annotation
274
+ convert_annotation time_event
275
+ when OpenCensus::Trace::MessageEvent
276
+ convert_message_event time_event
277
+ else
278
+ nil
279
+ end
280
+ end.compact
281
+ TraceProtos::Span::TimeEvents.new \
282
+ time_event: time_event_protos,
283
+ dropped_annotations_count: dropped_annotations_count,
284
+ dropped_message_events_count: dropped_message_events_count
285
+ end
286
+
287
+ ##
288
+ # Convert a link object
289
+ #
290
+ # @param [OpenCensus::Trace::Link] link The link object to convert
291
+ # @return [Google::Devtools::Cloudtrace::V2::Span::Link] The
292
+ # generated proto
293
+ #
294
+ def convert_link link
295
+ TraceProtos::Span::Link.new \
296
+ trace_id: link.trace_id,
297
+ span_id: link.span_id,
298
+ type: link.type,
299
+ attributes:
300
+ convert_attributes(link.attributes,
301
+ link.dropped_attributes_count)
302
+ end
303
+
304
+ ##
305
+ # Convert a list of link objects
306
+ #
307
+ # @param [Array<OpenCensus::Trace::Link>] links The link objects to
308
+ # convert
309
+ # @param [Integer] dropped_links_count Number of dropped links
310
+ # @return [Google::Devtools::Cloudtrace::V2::Span::Links] The
311
+ # generated proto
312
+ #
313
+ def convert_links links, dropped_links_count
314
+ TraceProtos::Span::Links.new \
315
+ link: links.map { |link| convert_link link },
316
+ dropped_links_count: dropped_links_count
317
+ end
318
+
319
+ ##
320
+ # Convert a nullable status object
321
+ #
322
+ # @param [OpenCensus::Trace::Status, nil] status The status object to
323
+ # convert, or nil if absent
324
+ # @return [Google::Rpc::Status, nil] The generated proto, or nil
325
+ #
326
+ def convert_optional_status status
327
+ return nil if status.nil?
328
+ Google::Rpc::Status.new code: status.code, message: status.message
329
+ end
330
+
331
+ ##
332
+ # Convert a nullable boolean object
333
+ #
334
+ # @param [boolean, nil] value The value to convert, or nil if absent
335
+ # @return [Google::Protobuf::BoolValue, nil] Generated proto, or nil
336
+ #
337
+ def convert_optional_bool value
338
+ return nil if value.nil?
339
+ Google::Protobuf::BoolValue.new value: value
340
+ end
341
+
342
+ ##
343
+ # Convert a nullable int32 object
344
+ #
345
+ # @param [Integer, nil] value The value to convert, or nil if absent
346
+ # @return [Google::Protobuf::Int32Value, nil] Generated proto, or nil
347
+ #
348
+ def convert_optional_int32 value
349
+ return nil if value.nil?
350
+ Google::Protobuf::Int32Value.new value: value
351
+ end
352
+ end
353
+ end
354
+ end
355
+ end
356
+ end