55# SPDX-License-Identifier: Apache-2.0
66
77require 'opentelemetry/common'
8+ require 'opentelemetry/exporter/otlp/common'
89require 'opentelemetry/sdk'
910require 'net/http'
1011require 'zlib'
@@ -105,26 +106,6 @@ def shutdown(timeout: nil)
105106
106107 private
107108
108- # Builds span flags based on whether the parent span context is remote.
109- # This follows the OTLP specification for span flags.
110- def build_span_flags ( parent_span_is_remote , base_flags )
111- # Extract integer value from TraceFlags object if needed
112- # Derive the low 8-bit W3C trace flags using the public API.
113- base_flags_int =
114- if base_flags . sampled?
115- 1
116- else
117- 0
118- end
119-
120- has_remote_mask = Opentelemetry ::Proto ::Trace ::V1 ::SpanFlags ::SPAN_FLAGS_CONTEXT_HAS_IS_REMOTE_MASK
121- is_remote_mask = Opentelemetry ::Proto ::Trace ::V1 ::SpanFlags ::SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK
122-
123- flags = base_flags_int | has_remote_mask
124- flags |= is_remote_mask if parent_span_is_remote
125- flags
126- end
127-
128109 def http_connection ( uri , ssl_verify_mode , certificate_file , client_certificate_file , client_key_file )
129110 http = Net ::HTTP . new ( uri . hostname , uri . port )
130111 http . use_ssl = uri . scheme == 'https'
@@ -293,32 +274,9 @@ def backoff?(retry_count:, reason:, retry_after: nil) # rubocop:disable Metrics/
293274 true
294275 end
295276
296- def encode ( span_data ) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
277+ def encode ( span_data )
297278 start = Process . clock_gettime ( Process ::CLOCK_MONOTONIC )
298- Opentelemetry ::Proto ::Collector ::Trace ::V1 ::ExportTraceServiceRequest . encode (
299- Opentelemetry ::Proto ::Collector ::Trace ::V1 ::ExportTraceServiceRequest . new (
300- resource_spans : span_data
301- . group_by ( &:resource )
302- . map do |resource , span_datas |
303- Opentelemetry ::Proto ::Trace ::V1 ::ResourceSpans . new (
304- resource : Opentelemetry ::Proto ::Resource ::V1 ::Resource . new (
305- attributes : resource . attribute_enumerator . map { |key , value | as_otlp_key_value ( key , value ) }
306- ) ,
307- scope_spans : span_datas
308- . group_by ( &:instrumentation_scope )
309- . map do |il , sds |
310- Opentelemetry ::Proto ::Trace ::V1 ::ScopeSpans . new (
311- scope : Opentelemetry ::Proto ::Common ::V1 ::InstrumentationScope . new (
312- name : il . name ,
313- version : il . version
314- ) ,
315- spans : sds . map { |sd | as_otlp_span ( sd ) }
316- )
317- end
318- )
319- end
320- )
321- )
279+ OpenTelemetry ::Exporter ::OTLP ::Common . as_encoded_etsr ( span_data )
322280 rescue StandardError => e
323281 OpenTelemetry . handle_error ( exception : e , message : 'unexpected error in OTLP::Exporter#encode' )
324282 nil
@@ -329,93 +287,6 @@ def encode(span_data) # rubocop:disable Metrics/MethodLength, Metrics/Cyclomatic
329287 value : duration_ms )
330288 end
331289
332- def as_otlp_span ( span_data ) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
333- Opentelemetry ::Proto ::Trace ::V1 ::Span . new (
334- trace_id : span_data . trace_id ,
335- span_id : span_data . span_id ,
336- trace_state : span_data . tracestate . to_s ,
337- parent_span_id : span_data . parent_span_id == OpenTelemetry ::Trace ::INVALID_SPAN_ID ? nil : span_data . parent_span_id ,
338- name : span_data . name ,
339- kind : as_otlp_span_kind ( span_data . kind ) ,
340- start_time_unix_nano : span_data . start_timestamp ,
341- end_time_unix_nano : span_data . end_timestamp ,
342- attributes : span_data . attributes &.map { |k , v | as_otlp_key_value ( k , v ) } ,
343- dropped_attributes_count : span_data . total_recorded_attributes - span_data . attributes &.size . to_i ,
344- events : span_data . events &.map do |event |
345- Opentelemetry ::Proto ::Trace ::V1 ::Span ::Event . new (
346- time_unix_nano : event . timestamp ,
347- name : event . name ,
348- attributes : event . attributes &.map { |k , v | as_otlp_key_value ( k , v ) }
349- # TODO: track dropped_attributes_count in Span#append_event
350- )
351- end ,
352- dropped_events_count : span_data . total_recorded_events - span_data . events &.size . to_i ,
353- links : span_data . links &.map do |link |
354- Opentelemetry ::Proto ::Trace ::V1 ::Span ::Link . new (
355- trace_id : link . span_context . trace_id ,
356- span_id : link . span_context . span_id ,
357- trace_state : link . span_context . tracestate . to_s ,
358- attributes : link . attributes &.map { |k , v | as_otlp_key_value ( k , v ) } ,
359- # TODO: track dropped_attributes_count in Span#trim_links
360- flags : build_span_flags ( link . span_context . remote? , link . span_context . trace_flags )
361- )
362- end ,
363- dropped_links_count : span_data . total_recorded_links - span_data . links &.size . to_i ,
364- status : span_data . status &.then do |status |
365- Opentelemetry ::Proto ::Trace ::V1 ::Status . new (
366- code : as_otlp_status_code ( status . code ) ,
367- message : status . description
368- )
369- end ,
370- flags : build_span_flags ( span_data . parent_span_is_remote , span_data . trace_flags )
371- )
372- end
373-
374- def as_otlp_status_code ( code )
375- case code
376- when OpenTelemetry ::Trace ::Status ::OK then Opentelemetry ::Proto ::Trace ::V1 ::Status ::StatusCode ::STATUS_CODE_OK
377- when OpenTelemetry ::Trace ::Status ::ERROR then Opentelemetry ::Proto ::Trace ::V1 ::Status ::StatusCode ::STATUS_CODE_ERROR
378- else Opentelemetry ::Proto ::Trace ::V1 ::Status ::StatusCode ::STATUS_CODE_UNSET
379- end
380- end
381-
382- def as_otlp_span_kind ( kind )
383- case kind
384- when :internal then Opentelemetry ::Proto ::Trace ::V1 ::Span ::SpanKind ::SPAN_KIND_INTERNAL
385- when :server then Opentelemetry ::Proto ::Trace ::V1 ::Span ::SpanKind ::SPAN_KIND_SERVER
386- when :client then Opentelemetry ::Proto ::Trace ::V1 ::Span ::SpanKind ::SPAN_KIND_CLIENT
387- when :producer then Opentelemetry ::Proto ::Trace ::V1 ::Span ::SpanKind ::SPAN_KIND_PRODUCER
388- when :consumer then Opentelemetry ::Proto ::Trace ::V1 ::Span ::SpanKind ::SPAN_KIND_CONSUMER
389- else Opentelemetry ::Proto ::Trace ::V1 ::Span ::SpanKind ::SPAN_KIND_UNSPECIFIED
390- end
391- end
392-
393- def as_otlp_key_value ( key , value )
394- Opentelemetry ::Proto ::Common ::V1 ::KeyValue . new ( key : key , value : as_otlp_any_value ( value ) )
395- rescue Encoding ::UndefinedConversionError => e
396- encoded_value = value . encode ( 'UTF-8' , invalid : :replace , undef : :replace , replace : '�' )
397- OpenTelemetry . handle_error ( exception : e , message : "encoding error for key #{ key } and value #{ encoded_value } " )
398- Opentelemetry ::Proto ::Common ::V1 ::KeyValue . new ( key : key , value : as_otlp_any_value ( 'Encoding Error' ) )
399- end
400-
401- def as_otlp_any_value ( value )
402- result = Opentelemetry ::Proto ::Common ::V1 ::AnyValue . new
403- case value
404- when String
405- result . string_value = value
406- when Integer
407- result . int_value = value
408- when Float
409- result . double_value = value
410- when true , false
411- result . bool_value = value
412- when Array
413- values = value . map { |element | as_otlp_any_value ( element ) }
414- result . array_value = Opentelemetry ::Proto ::Common ::V1 ::ArrayValue . new ( values : values )
415- end
416- result
417- end
418-
419290 def prepare_endpoint ( endpoint )
420291 endpoint ||= ENV . fetch ( 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT' , nil )
421292 if endpoint . nil?
0 commit comments