opentelemetry-api 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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