traces 0.2.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e8d74b7b8712105a772f7d9cde7108dc2218137570ba71f11632cd539808a740
4
- data.tar.gz: 4a63fcc5efe56b48a074a6e66587bab35395daf9a0b20864e59b4987db9530e3
3
+ metadata.gz: 389518e7025f63c5c99a5599000e12191ca8634b38f8d05ba727fe22b0fe3aa5
4
+ data.tar.gz: f8648d7990686c3abbd955f4b45869cf67c88e2b644da156e914bc2cac92087d
5
5
  SHA512:
6
- metadata.gz: f2291cae8c41890078266aaedbd14f760e94b18d76e55b2b32c792e6188770cee4565e96972711bf0cc83f6ddaacd1700d767eca56584423e7c55ee322ce295c
7
- data.tar.gz: 33b0e8f87d219f8c4122d356b2ee1188d6df6f89aea9f8583757bf1cf288c4ed393cd2bda96804c84fb7812014d545d872923cb7bfff22a8e7152f87aeb2b8aa
6
+ metadata.gz: a3d9834ff556a722bb7a82dae4c824c94888af648a70954ab2a7c720e26e622ce826262838016169388734b8f9beaa6c2b74cd0a4ea9a669295fce70ae41c61c
7
+ data.tar.gz: 4fd9a0b83fb293e04fec5ff91431ee55ac2a6fcb86609288795d4d22486cf51fdcb16ec21610487b6e99d9b5662ab30d0999360ce5aaf430408b75a56ae077b8
checksums.yaml.gz.sig CHANGED
Binary file
@@ -20,16 +20,71 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
+ require_relative '../context'
24
+
23
25
  require 'console'
26
+ require 'fiber'
27
+
28
+ class Fiber
29
+ attr_accessor :traces_backend_context
30
+ end
24
31
 
25
32
  module Traces
26
33
  module Backend
27
- private
28
-
29
- def trace(name, parent = nil, attributes: nil, &block)
30
- Console.logger.info(self, name, attributes)
34
+ # A backend which logs all spans to the console logger output.
35
+ module Console
36
+ # A span which validates tag assignment.
37
+ class Span
38
+ def initialize(context, instance, name)
39
+ @context = context
40
+ @instance = instance
41
+ @name = name
42
+ end
43
+
44
+ attr :context
45
+
46
+ # Assign some metadata to the span.
47
+ # @parameter key [String] The metadata key.
48
+ # @parameter value [Object] The metadata value. Should be coercable to a string.
49
+ def []= key, value
50
+ ::Console.logger.info(@context, @name, "#{key} = #{value}")
51
+ end
52
+ end
31
53
 
32
- yield
54
+ module Interface
55
+ # Trace the given block of code and log the execution.
56
+ # @parameter name [String] A useful name/annotation for the recorded span.
57
+ # @parameter attributes [Hash] Metadata for the recorded span.
58
+ def trace(name, attributes: {}, &block)
59
+ context = Context.nested(Fiber.current.traces_backend_context)
60
+ Fiber.current.traces_backend_context = context
61
+
62
+ ::Console.logger.info(self, name, attributes)
63
+
64
+ if block.arity.zero?
65
+ yield
66
+ else
67
+ yield Span.new(context, self, name)
68
+ end
69
+ end
70
+
71
+ # Assign a trace context to the current execution scope.
72
+ def trace_context= context
73
+ Fiber.current.traces_backend_context = context
74
+ end
75
+
76
+ # Get a trace context from the current execution scope.
77
+ # @parameter span [Span] An optional span from which to extract the context.
78
+ def trace_context(span = nil)
79
+ if span
80
+ span.context
81
+ else
82
+ Fiber.current.traces_backend_context
83
+ end
84
+ end
85
+ end
33
86
  end
87
+
88
+ Interface = Console::Interface
34
89
  end
35
90
  end
@@ -20,18 +20,76 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
- require 'console'
23
+ require_relative '../context'
24
+ require 'fiber'
25
+
26
+ class Fiber
27
+ attr_accessor :traces_backend_context
28
+ end
24
29
 
25
30
  module Traces
26
31
  module Backend
27
- private
28
-
29
- def trace(name, parent = nil, attributes: nil, &block)
30
- unless name.is_a?(String)
31
- raise ArgumentError, "Invalid name!"
32
+ # A backend which validates interface usage.
33
+ module Test
34
+ # A span which validates tag assignment.
35
+ class Span
36
+ def initialize(context)
37
+ @context = context
38
+ end
39
+
40
+ attr :context
41
+
42
+ # Assign some metadata to the span.
43
+ # @parameter key [String] The metadata key.
44
+ # @parameter value [Object] The metadata value. Should be coercable to a string.
45
+ def []= key, value
46
+ unless key.is_a?(String)
47
+ raise ArgumentError, "Invalid name!"
48
+ end
49
+
50
+ unless String(value)
51
+ raise ArgumentError, "Invalid value!"
52
+ end
53
+ end
32
54
  end
33
55
 
34
- yield
56
+ module Interface
57
+ # Trace the given block of code and validate the interface usage.
58
+ # @parameter name [String] A useful name/annotation for the recorded span.
59
+ # @parameter attributes [Hash] Metadata for the recorded span.
60
+ def trace(name, attributes: nil, &block)
61
+ unless name.is_a?(String)
62
+ raise ArgumentError, "Invalid name!"
63
+ end
64
+
65
+ context = Context.nested(Fiber.current.traces_backend_context)
66
+ Fiber.current.traces_backend_context = context
67
+
68
+ if block.arity.zero?
69
+ yield
70
+ else
71
+ span = Span.new(context)
72
+ yield span
73
+ end
74
+ end
75
+
76
+ # Assign a trace context to the current execution scope.
77
+ def trace_context= context
78
+ Fiber.current.traces_backend_context = context
79
+ end
80
+
81
+ # Get a trace context from the current execution scope.
82
+ # @parameter span [Span] An optional span from which to extract the context.
83
+ def trace_context(span = nil)
84
+ if span
85
+ span.context
86
+ else
87
+ Fiber.current.traces_backend_context
88
+ end
89
+ end
90
+ end
35
91
  end
92
+
93
+ Interface = Test::Interface
36
94
  end
37
95
  end
@@ -21,7 +21,12 @@
21
21
  # THE SOFTWARE.
22
22
 
23
23
  module Traces
24
+ # Require a specific trace backend.
24
25
  def self.require_backend(env = ENV)
26
+ if const_defined?(:Backend)
27
+ raise RuntimeError, "Backend already required!"
28
+ end
29
+
25
30
  if backend = env['TRACES_BACKEND']
26
31
  require(backend)
27
32
  end
@@ -20,15 +20,19 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
22
 
23
+ require 'securerandom'
24
+
23
25
  module Traces
24
- # A generic representation of the current span.
25
- # We follow the <https://github.com/openzipkin/b3-propagation> model.
26
+ # A generic representation of the current tracing context.
26
27
  class Context
27
- def self.parse(parent, state = nil)
28
+ # Parse a string representation of a distributed trace.
29
+ # @parameter parent [String] The parent trace context.
30
+ # @parameter state [Array(String)] Any attached trace state.
31
+ def self.parse(parent, state = nil, **options)
28
32
  version, trace_id, parent_id, flags = parent.split('-')
29
33
 
30
34
  if version == '00'
31
- flags = Integer(trace_flags, 16)
35
+ flags = Integer(flags, 16)
32
36
 
33
37
  if state.is_a?(String)
34
38
  state = state.split(',')
@@ -38,7 +42,23 @@ module Traces
38
42
  state = state.map{|item| item.split('=')}
39
43
  end
40
44
 
41
- self.new(trace_id, parent_id, flags, state)
45
+ self.new(trace_id, parent_id, flags, state, **options)
46
+ end
47
+ end
48
+
49
+ # Create a local trace context which is likley to be globally unique.
50
+ # @parameter flags [Integer] Any trace context flags.
51
+ def self.local(flags = 0, **options)
52
+ self.new(SecureRandom.hex(16), SecureRandom.hex(8), flags, **options)
53
+ end
54
+
55
+ # Nest a local trace context in an optional parent context.
56
+ # @parameter parent [Context] An optional parent context.
57
+ def self.nested(parent, flags = 0)
58
+ if parent
59
+ parent.nested(flags)
60
+ else
61
+ self.local(flags)
42
62
  end
43
63
  end
44
64
 
@@ -46,25 +66,40 @@ module Traces
46
66
 
47
67
  def initialize(trace_id, parent_id, flags, state = nil, remote: false)
48
68
  @trace_id = trace_id
49
- @parent_id = span_id
69
+ @parent_id = parent_id
50
70
  @flags = flags
51
71
  @state = state
52
72
  @remote = remote
53
73
  end
54
74
 
75
+ # Create a new nested trace context in which spans can be recorded.
76
+ def nested(flags = @flags)
77
+ Context.new(@trace_id, SecureRandom.hex(8), flags, @state, remote: @remote)
78
+ end
79
+
80
+ # The ID of the whole trace forest and is used to uniquely identify a distributed trace through a system. It is represented as a 16-byte array, for example, 4bf92f3577b34da6a3ce929d0e0e4736. All bytes as zero (00000000000000000000000000000000) is considered an invalid value.
55
81
  attr :trace_id
56
- attr :span_id
82
+
83
+ # The ID of this request as known by the caller (in some tracing systems, this is known as the span-id, where a span is the execution of a client request). It is represented as an 8-byte array, for example, 00f067aa0ba902b7. All bytes as zero (0000000000000000) is considered an invalid value.
84
+ attr :parent_id
85
+
86
+ # An 8-bit field that controls tracing flags such as sampling, trace level, etc. These flags are recommendations given by the caller rather than strict rules.
57
87
  attr :flags
88
+
89
+ # Provides additional vendor-specific trace identification information across different distributed tracing systems. Conveys information about the request’s position in multiple distributed tracing graphs.
58
90
  attr :state
59
91
 
92
+ # Denotes that the caller may have recorded trace data. When unset, the caller did not record trace data out-of-band.
60
93
  def sampled?
61
94
  @flags & SAMPLED
62
95
  end
63
96
 
97
+ # Whether this context was created from a distributed trace header.
64
98
  def remote?
65
99
  @remote
66
100
  end
67
101
 
102
+ # A string representation of the trace context (excluding trace state).
68
103
  def to_s
69
104
  "00-#{@trace_id}-#{@parent_id}-#{@flags.to_s(16)}"
70
105
  end
@@ -23,6 +23,7 @@
23
23
  require_relative 'backend'
24
24
 
25
25
  module Traces
26
+ # A module which contains tracing specific wrappers.
26
27
  module Provider
27
28
  def traces_provider
28
29
  @traces_provider ||= Module.new
@@ -30,12 +31,13 @@ module Traces
30
31
  end
31
32
 
32
33
  # Bail out if there is no backend configured.
33
- if Traces.const_defined?(:Backend)
34
+ if self.const_defined?(:Backend)
35
+ # Extend the specified class in order to emit traces.
34
36
  def self.Provider(klass, &block)
35
37
  klass.extend(Provider)
36
38
 
37
39
  provider = klass.traces_provider
38
- provider.prepend(Backend)
40
+ provider.prepend(Backend::Interface)
39
41
 
40
42
  klass.prepend(provider)
41
43
 
@@ -21,5 +21,5 @@
21
21
  # THE SOFTWARE.
22
22
 
23
23
  module Traces
24
- VERSION = "0.2.0"
24
+ VERSION = "0.4.0"
25
25
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: traces
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -36,7 +36,7 @@ cert_chain:
36
36
  RAOsIl+HOBTb252nx1kIRN5hqQx272AJCbCjKx8egcUQKffFVVCI0nye09v5CK+a
37
37
  HiLJ8VOFx6w=
38
38
  -----END CERTIFICATE-----
39
- date: 2021-10-17 00:00:00.000000000 Z
39
+ date: 2021-10-18 00:00:00.000000000 Z
40
40
  dependencies:
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
metadata.gz.sig CHANGED
Binary file