opentelemetry-api 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1 -0
- data/LICENSE +201 -0
- data/lib/opentelemetry.rb +43 -0
- data/lib/opentelemetry/context.rb +31 -0
- data/lib/opentelemetry/distributed_context.rb +19 -0
- data/lib/opentelemetry/distributed_context/distributed_context.rb +24 -0
- data/lib/opentelemetry/distributed_context/entry.rb +66 -0
- data/lib/opentelemetry/distributed_context/manager.rb +12 -0
- data/lib/opentelemetry/distributed_context/propagation.rb +19 -0
- data/lib/opentelemetry/distributed_context/propagation/binary_format.rb +26 -0
- data/lib/opentelemetry/distributed_context/propagation/text_format.rb +76 -0
- data/lib/opentelemetry/distributed_context/propagation/trace_parent.rb +124 -0
- data/lib/opentelemetry/error.rb +9 -0
- data/lib/opentelemetry/internal.rb +22 -0
- data/lib/opentelemetry/metrics.rb +16 -0
- data/lib/opentelemetry/metrics/handles.rb +54 -0
- data/lib/opentelemetry/metrics/instruments.rb +156 -0
- data/lib/opentelemetry/metrics/meter.rb +109 -0
- data/lib/opentelemetry/metrics/meter_factory.rb +22 -0
- data/lib/opentelemetry/trace.rb +53 -0
- data/lib/opentelemetry/trace/event.rb +45 -0
- data/lib/opentelemetry/trace/link.rb +45 -0
- data/lib/opentelemetry/trace/sampling_hint.rb +22 -0
- data/lib/opentelemetry/trace/span.rb +137 -0
- data/lib/opentelemetry/trace/span_context.rb +56 -0
- data/lib/opentelemetry/trace/span_kind.rb +35 -0
- data/lib/opentelemetry/trace/status.rb +109 -0
- data/lib/opentelemetry/trace/trace_flags.rb +50 -0
- data/lib/opentelemetry/trace/tracer.rb +69 -0
- data/lib/opentelemetry/trace/tracer_factory.rb +45 -0
- data/lib/opentelemetry/version.rb +10 -0
- 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,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
|