opentelemetry-api 0.2.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.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1 -0
  3. data/LICENSE +201 -0
  4. data/lib/opentelemetry.rb +43 -0
  5. data/lib/opentelemetry/context.rb +31 -0
  6. data/lib/opentelemetry/distributed_context.rb +19 -0
  7. data/lib/opentelemetry/distributed_context/distributed_context.rb +24 -0
  8. data/lib/opentelemetry/distributed_context/entry.rb +66 -0
  9. data/lib/opentelemetry/distributed_context/manager.rb +12 -0
  10. data/lib/opentelemetry/distributed_context/propagation.rb +19 -0
  11. data/lib/opentelemetry/distributed_context/propagation/binary_format.rb +26 -0
  12. data/lib/opentelemetry/distributed_context/propagation/text_format.rb +76 -0
  13. data/lib/opentelemetry/distributed_context/propagation/trace_parent.rb +124 -0
  14. data/lib/opentelemetry/error.rb +9 -0
  15. data/lib/opentelemetry/internal.rb +22 -0
  16. data/lib/opentelemetry/metrics.rb +16 -0
  17. data/lib/opentelemetry/metrics/handles.rb +54 -0
  18. data/lib/opentelemetry/metrics/instruments.rb +156 -0
  19. data/lib/opentelemetry/metrics/meter.rb +109 -0
  20. data/lib/opentelemetry/metrics/meter_factory.rb +22 -0
  21. data/lib/opentelemetry/trace.rb +53 -0
  22. data/lib/opentelemetry/trace/event.rb +45 -0
  23. data/lib/opentelemetry/trace/link.rb +45 -0
  24. data/lib/opentelemetry/trace/sampling_hint.rb +22 -0
  25. data/lib/opentelemetry/trace/span.rb +137 -0
  26. data/lib/opentelemetry/trace/span_context.rb +56 -0
  27. data/lib/opentelemetry/trace/span_kind.rb +35 -0
  28. data/lib/opentelemetry/trace/status.rb +109 -0
  29. data/lib/opentelemetry/trace/trace_flags.rb +50 -0
  30. data/lib/opentelemetry/trace/tracer.rb +69 -0
  31. data/lib/opentelemetry/trace/tracer_factory.rb +45 -0
  32. data/lib/opentelemetry/version.rb +10 -0
  33. metadata +200 -0
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+ module OpenTelemetry
7
+ module DistributedContext
8
+ module Propagation
9
+ # TextFormat is a formatter that injects and extracts a value as text into carriers that travel in-band across
10
+ # process boundaries.
11
+ # Encoding is expected to conform to the HTTP Header Field semantics. Values are often encoded as RPC/HTTP request
12
+ # headers.
13
+ #
14
+ # The carrier of propagated data on both the client (injector) and server (extractor) side is usually an http request.
15
+ # Propagation is usually implemented via library-specific request interceptors, where the client-side injects values
16
+ # and the server-side extracts them.
17
+ class TextFormat
18
+ DEFAULT_GETTER = ->(carrier, key) { carrier[key] }
19
+ DEFAULT_SETTER = ->(carrier, key, value) { carrier[key] = value }
20
+ private_constant(:DEFAULT_GETTER, :DEFAULT_SETTER)
21
+
22
+ # Returns an array with the trace context header keys used by this formatter
23
+ attr_reader :fields
24
+
25
+ # Returns a new TextFormat that injects and extracts using the specified trace context
26
+ # header keys
27
+ #
28
+ # @param [String] traceparent_header_key The traceparent header key used in the carrier
29
+ # @param [String] tracestate_header_key The tracestate header key used in the carrier
30
+ # @return [TextFormatter]
31
+ def initialize(traceparent_header_key:, tracestate_header_key:)
32
+ @traceparent_header_key = traceparent_header_key
33
+ @tracestate_header_key = tracestate_header_key
34
+ @fields = [traceparent_header_key, tracestate_header_key].freeze
35
+ end
36
+
37
+ # Return a remote {Trace::SpanContext} extracted from the supplied carrier. Expects the
38
+ # the supplied carrier to have keys in rack normalized format (HTTP_#{UPPERCASE_KEY}).
39
+ # Invalid headers will result in a new, valid, non-remote {Trace::SpanContext}.
40
+ #
41
+ # @param [Carrier] carrier The carrier to get the header from.
42
+ # @param [optional Callable] getter An optional callable that takes a carrier and a key and
43
+ # returns the value associated with the key. If omitted the default getter will be used
44
+ # which expects the carrier to respond to [] and []=.
45
+ # @yield [Carrier, String] if an optional getter is provided, extract will yield the carrier
46
+ # and the header key to the getter.
47
+ # @return [SpanContext] the span context from the header, or a new one if parsing fails.
48
+ def extract(carrier, &getter)
49
+ getter ||= DEFAULT_GETTER
50
+ header = getter.call(carrier, @traceparent_header_key)
51
+ tp = TraceParent.from_string(header)
52
+
53
+ tracestate = getter.call(carrier, @tracestate_header_key)
54
+
55
+ Trace::SpanContext.new(trace_id: tp.trace_id, span_id: tp.span_id, trace_flags: tp.flags, tracestate: tracestate, remote: true)
56
+ rescue OpenTelemetry::Error
57
+ Trace::SpanContext.new
58
+ end
59
+
60
+ # Set the span context on the supplied carrier.
61
+ #
62
+ # @param [SpanContext] context The active {Trace::SpanContext}.
63
+ # @param [optional Callable] setter An optional callable that takes a carrier and a key and
64
+ # a value and assigns the key-value pair in the carrier. If omitted the default setter
65
+ # will be used which expects the carrier to respond to [] and []=.
66
+ # @yield [Carrier, String, String] if an optional setter is provided, inject will yield
67
+ # carrier, header key, header value to the setter.
68
+ def inject(context, carrier, &setter)
69
+ setter ||= DEFAULT_SETTER
70
+ setter.call(carrier, @traceparent_header_key, TraceParent.from_context(context).to_s)
71
+ setter.call(carrier, @tracestate_header_key, context.tracestate) unless context.tracestate.nil?
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+ module OpenTelemetry
7
+ module DistributedContext
8
+ module Propagation
9
+ # A TraceParent is an implementation of the W3C trace context specification
10
+ # https://www.w3.org/TR/trace-context/
11
+ # {Trace::SpanContext}
12
+ class TraceParent
13
+ InvalidFormatError = Class.new(Error)
14
+ InvalidVersionError = Class.new(Error)
15
+ InvalidTraceIDError = Class.new(Error)
16
+ InvalidSpanIDError = Class.new(Error)
17
+
18
+ TRACE_PARENT_HEADER = 'traceparent'
19
+ SUPPORTED_VERSION = 0
20
+ private_constant :SUPPORTED_VERSION
21
+ MAX_VERSION = 254
22
+ private_constant :MAX_VERSION
23
+
24
+ REGEXP = /^(?<version>[A-Fa-f0-9]{2})-(?<trace_id>[A-Fa-f0-9]{32})-(?<span_id>[A-Fa-f0-9]{16})-(?<flags>[A-Fa-f0-9]{2})(?<ignored>-.*)?$/.freeze
25
+ private_constant :REGEXP
26
+
27
+ class << self
28
+ # Creates a new {TraceParent} from a supplied {Trace::SpanContext}
29
+ # @param [SpanContext] ctx The context
30
+ # @return [TraceParent] a trace parent
31
+ def from_context(ctx)
32
+ new(trace_id: ctx.trace_id, span_id: ctx.span_id, flags: ctx.trace_flags)
33
+ end
34
+
35
+ # Deserializes the {TraceParent} from the string representation
36
+ # @param [String] string The serialized trace parent
37
+ # @return [TraceParent] a trace_parent
38
+ # @raise [InvalidFormatError] on an invalid format
39
+ # @raise [InvalidVerionError] on an invalid version
40
+ # @raise [InvalidTraceIDError] on an invalid trace_id
41
+ # @raise [InvalidSpanIDError] on an invalid span_id
42
+ def from_string(string)
43
+ matches = match_input(string)
44
+
45
+ version = parse_version(matches[:version])
46
+ raise InvalidFormatError if version > SUPPORTED_VERSION && string.length < 55
47
+
48
+ trace_id = parse_trace_id(matches[:trace_id])
49
+ span_id = parse_span_id(matches[:span_id])
50
+ flags = parse_flags(matches[:flags])
51
+
52
+ new(trace_id: trace_id, span_id: span_id, flags: flags)
53
+ end
54
+
55
+ private
56
+
57
+ def match_input(string)
58
+ matches = REGEXP.match(string)
59
+ raise InvalidFormatError, 'regexp match failed' if !matches || matches.length < 6
60
+
61
+ matches
62
+ end
63
+
64
+ def parse_version(string)
65
+ v = string.to_i(16)
66
+ raise InvalidFormatError, string unless v
67
+ raise InvalidVersionError, v if v > MAX_VERSION
68
+
69
+ v
70
+ end
71
+
72
+ def parse_trace_id(string)
73
+ raise InvalidTraceIDError, string if string == OpenTelemetry::Trace::INVALID_TRACE_ID
74
+
75
+ string.downcase!
76
+ string
77
+ end
78
+
79
+ def parse_span_id(string)
80
+ raise InvalidSpanIDError, string if string == OpenTelemetry::Trace::INVALID_SPAN_ID
81
+
82
+ string.downcase!
83
+ string
84
+ end
85
+
86
+ def parse_flags(string)
87
+ OpenTelemetry::Trace::TraceFlags.from_byte(string.to_i(16))
88
+ end
89
+ end
90
+
91
+ attr_reader :version, :trace_id, :span_id, :flags
92
+
93
+ private_class_method :new
94
+
95
+ # Returns the sampling choice from the trace_flags
96
+ # @return [Boolean] the sampling choice
97
+ def sampled?
98
+ flags.sampled?
99
+ end
100
+
101
+ # converts this object into a string according to the w3c spec
102
+ # @return [String] the serialized trace_parent
103
+ def to_s
104
+ "00-#{trace_id}-#{span_id}-#{flag_string}"
105
+ end
106
+
107
+ private
108
+
109
+ def flag_string
110
+ # the w3c standard only dictates the one flag for this version
111
+ # therefore we can only output the one flag.
112
+ flags.sampled? ? '01' : '00'
113
+ end
114
+
115
+ def initialize(trace_id: nil, span_id: nil, version: SUPPORTED_VERSION, flags: Trace::TraceFlags::DEFAULT)
116
+ @trace_id = trace_id
117
+ @span_id = span_id
118
+ @version = version
119
+ @flags = flags
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+ module OpenTelemetry
7
+ class Error < StandardError
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ # @api private
9
+ #
10
+ # Internal contains helpers used by the no-op API implementation.
11
+ module Internal
12
+ extend self
13
+
14
+ def printable_ascii?(string)
15
+ return false unless string.is_a?(String)
16
+
17
+ r = 32..126
18
+ string.each_codepoint { |c| return false unless r.include?(c) }
19
+ true
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ require 'opentelemetry/metrics/handles'
8
+ require 'opentelemetry/metrics/instruments'
9
+ require 'opentelemetry/metrics/meter'
10
+ require 'opentelemetry/metrics/meter_factory'
11
+
12
+ module OpenTelemetry
13
+ # The Metrics API allows reporting raw measurements as well as metrics with known aggregation and labels.
14
+ module Metrics
15
+ end
16
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module Metrics
9
+ # In situations where performance is a requirement and a metric is
10
+ # repeatedly used with the same set of labels, the developer may elect to
11
+ # use instrument {Handles} as an optimization. For handles to be a benefit,
12
+ # it requires that a specific instrument will be re-used with specific
13
+ # labels. If an instrument will be used with the same label set more than
14
+ # once, obtaining an instrument handle corresponding to the label set
15
+ # ensures the highest performance available.
16
+ #
17
+ # To obtain a handle given an instrument and label set, use the #handle
18
+ # method to return an interface that supports the #add, #set, or #record
19
+ # method of the instrument in question.
20
+ #
21
+ # Instrument handles may consume SDK resources indefinitely.
22
+ module Handles
23
+ # A float gauge handle.
24
+ class FloatGauge
25
+ def set(value); end
26
+ end
27
+
28
+ # An integer gauge handle.
29
+ class IntegerGauge
30
+ def set(value); end
31
+ end
32
+
33
+ # A float counter handle.
34
+ class FloatCounter
35
+ def add(value); end
36
+ end
37
+
38
+ # An integer counter handle.
39
+ class IntegerCounter
40
+ def add(value); end
41
+ end
42
+
43
+ # A float measure handle.
44
+ class FloatMeasure
45
+ def record(value); end
46
+ end
47
+
48
+ # An integer measure handle.
49
+ class IntegerMeasure
50
+ def record(value); end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,156 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2019 OpenTelemetry Authors
4
+ #
5
+ # SPDX-License-Identifier: Apache-2.0
6
+
7
+ module OpenTelemetry
8
+ module Metrics
9
+ # The user-facing metrics API supports producing diagnostic measurements
10
+ # using three basic kinds of instrument. "Metrics" are the thing being
11
+ # produced -- mathematical, statistical summaries of certain observable
12
+ # behavior in the program. "Instruments" are the devices used by the
13
+ # program to record observations about their behavior. Therefore, we use
14
+ # "metric instrument" to refer to a program object, allocated through the
15
+ # API, used for recording metrics. There are three distinct instruments in
16
+ # the Metrics API, commonly known as Counters, Gauges, and Measures.
17
+ module Instruments
18
+ # A float gauge instrument.
19
+ class FloatGauge
20
+ # Set the value of the gauge.
21
+ #
22
+ # @param [Float] value The value to set.
23
+ # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
24
+ # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
25
+ def set(value, labels_or_label_set = {}); end
26
+
27
+ # Obtain a handle from the instrument and label set.
28
+ #
29
+ # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
30
+ # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
31
+ # @return [Handles::FloatGauge]
32
+ def handle(labels_or_label_set = {})
33
+ Handles::FloatGauge.new
34
+ end
35
+
36
+ # Return a measurement to be recorded via {Meter#record_batch}.
37
+ #
38
+ # @param [Float] value
39
+ # @return [Object, Measurement]
40
+ def measurement(value)
41
+ NOOP_MEASUREMENT
42
+ end
43
+ end
44
+
45
+ # An integer gauge instrument.
46
+ class IntegerGauge
47
+ def set(value, labels_or_label_set = {}); end
48
+
49
+ # Obtain a handle from the instrument and label set.
50
+ #
51
+ # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
52
+ # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
53
+ # @return [Handles::IntegerGauge]
54
+ def handle(labels_or_label_set = {})
55
+ Handles::IntegerGauge.new
56
+ end
57
+
58
+ # Return a measurement to be recorded via {Meter#record_batch}.
59
+ #
60
+ # @param [Integer] value
61
+ # @return [Object, Measurement]
62
+ def measurement(value)
63
+ NOOP_MEASUREMENT
64
+ end
65
+ end
66
+
67
+ # A float counter instrument.
68
+ class FloatCounter
69
+ def add(value, labels_or_label_set = {}); end
70
+
71
+ # Obtain a handle from the instrument and label set.
72
+ #
73
+ # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
74
+ # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
75
+ # @return [Handles::FloatCounter]
76
+ def handle(labels_or_label_set = {})
77
+ Handles::FloatCounter.new
78
+ end
79
+
80
+ # Return a measurement to be recorded via {Meter#record_batch}.
81
+ #
82
+ # @param [Float] value
83
+ # @return [Object, Measurement]
84
+ def measurement(value)
85
+ NOOP_MEASUREMENT
86
+ end
87
+ end
88
+
89
+ # An integer counter instrument.
90
+ class IntegerCounter
91
+ def add(value, labels_or_label_set = {}); end
92
+
93
+ # Obtain a handle from the instrument and label set.
94
+ #
95
+ # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
96
+ # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
97
+ # @return [Handles::IntegerCounter]
98
+ def handle(labels_or_label_set = {})
99
+ Handles::IntegerCounter.new
100
+ end
101
+
102
+ # Return a measurement to be recorded via {Meter#record_batch}.
103
+ #
104
+ # @param [Integer] value
105
+ # @return [Object, Measurement]
106
+ def measurement(value)
107
+ NOOP_MEASUREMENT
108
+ end
109
+ end
110
+
111
+ # A float measure instrument.
112
+ class FloatMeasure
113
+ def record(value, labels_or_label_set = {}); end
114
+
115
+ # Obtain a handle from the instrument and label set.
116
+ #
117
+ # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
118
+ # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
119
+ # @return [Handles::FloatMeasure]
120
+ def handle(labels_or_label_set = {})
121
+ Handles::FloatMeasure.new
122
+ end
123
+
124
+ # Return a measurement to be recorded via {Meter#record_batch}.
125
+ #
126
+ # @param [Float] value
127
+ # @return [Object, Measurement]
128
+ def measurement(value)
129
+ NOOP_MEASUREMENT
130
+ end
131
+ end
132
+
133
+ # An integer measure instrument.
134
+ class IntegerMeasure
135
+ def record(value, labels_or_label_set = {}); end
136
+
137
+ # Obtain a handle from the instrument and label set.
138
+ #
139
+ # @param [optional LabelSet, Hash<String, String>] labels_or_label_set
140
+ # A {LabelSet} returned from {Meter#labels} or a Hash of Strings.
141
+ # @return [Handles::IntegerMeasure]
142
+ def handle(labels_or_label_set = {})
143
+ Handles::IntegerMeasure.new
144
+ end
145
+
146
+ # Return a measurement to be recorded via {Meter#record_batch}.
147
+ #
148
+ # @param [Integer] value
149
+ # @return [Object, Measurement]
150
+ def measurement(value)
151
+ NOOP_MEASUREMENT
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end