Module: LogBrew::OperationTracing
- Defined in:
- lib/logbrew/operation_tracing.rb
Overview
Explicit dependency spans for app-owned database, cache, and queue work.
Class Method Summary collapse
- .add_option(metadata, key, value) ⇒ Object
- .cache_operation(client, name, **options, &block) ⇒ Object
- .capture_operation(client, kind, name, options) ⇒ Object
- .capture_span(client, kind, name, context, started_at, options, error) ⇒ Object
- .child_context ⇒ Object
- .database_operation(client, name, **options, &block) ⇒ Object
- .duration_ms(started_at, options) ⇒ Object
- .event_id(kind, context, options) ⇒ Object
- .monotonic_time ⇒ Object
- .queue_operation(client, name, **options, &block) ⇒ Object
- .read_option(options, key) ⇒ Object
- .sanitized_metadata(metadata) ⇒ Object
- .span_events(error) ⇒ Object
- .span_metadata(kind, options, error) ⇒ Object
- .timestamp(options) ⇒ Object
- .unsafe_metadata_key?(key) ⇒ Boolean
Class Method Details
.add_option(metadata, key, value) ⇒ Object
128 129 130 |
# File 'lib/logbrew/operation_tracing.rb', line 128 def add_option(, key, value) [key] = value if CaptureHelpers.(value) && !(value.is_a?(String) && value.strip.empty?) end |
.cache_operation(client, name, **options, &block) ⇒ Object
17 18 19 |
# File 'lib/logbrew/operation_tracing.rb', line 17 def cache_operation(client, name, **, &block) capture_operation(client, "cache", name, , &block) end |
.capture_operation(client, kind, name, options) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/logbrew/operation_tracing.rb', line 25 def capture_operation(client, kind, name, ) raise SdkError.new("validation_error", "#{kind} operation block is required") unless block_given? Validation.require_non_empty("#{kind} operation name", name) started_at = monotonic_time context = child_context error = nil result = nil Trace.with_context(context) do begin result = yield context rescue StandardError => captured error = captured end end capture_span(client, kind, name, context, started_at, , error) raise error if error result end |
.capture_span(client, kind, name, context, started_at, options, error) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/logbrew/operation_tracing.rb', line 48 def capture_span(client, kind, name, context, started_at, , error) Trace.with_context(context) do client.span( event_id(kind, context, ), (), { name: "#{kind}.operation:#{name}", traceId: context.trace_id, spanId: context.span_id, parentSpanId: context.parent_span_id, status: error ? "error" : "ok", durationMs: duration_ms(started_at, ), metadata: (kind, , error), events: span_events(error) } ) end rescue StandardError => capture_error on_error = read_option(, :on_error) begin on_error.call(capture_error) if on_error.respond_to?(:call) rescue StandardError nil end end |
.child_context ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/logbrew/operation_tracing.rb', line 74 def child_context parent = Trace.current return Trace.create_root unless parent Trace.create( trace_id: parent.trace_id, span_id: Trace.generate_span_id, parent_span_id: parent.span_id, trace_flags: parent.trace_flags ) end |
.database_operation(client, name, **options, &block) ⇒ Object
13 14 15 |
# File 'lib/logbrew/operation_tracing.rb', line 13 def database_operation(client, name, **, &block) capture_operation(client, "database", name, , &block) end |
.duration_ms(started_at, options) ⇒ Object
147 148 149 150 151 152 |
# File 'lib/logbrew/operation_tracing.rb', line 147 def duration_ms(started_at, ) configured = read_option(, :duration_ms) return configured unless configured.nil? ((monotonic_time - started_at) * 1000.0).round(3) end |
.event_id(kind, context, options) ⇒ Object
136 137 138 |
# File 'lib/logbrew/operation_tracing.rb', line 136 def event_id(kind, context, ) read_option(, :event_id) || "ruby_#{kind}_span_#{context.span_id}" end |
.monotonic_time ⇒ Object
154 155 156 |
# File 'lib/logbrew/operation_tracing.rb', line 154 def monotonic_time Process.clock_gettime(Process::CLOCK_MONOTONIC) end |
.queue_operation(client, name, **options, &block) ⇒ Object
21 22 23 |
# File 'lib/logbrew/operation_tracing.rb', line 21 def queue_operation(client, name, **, &block) capture_operation(client, "queue", name, , &block) end |
.read_option(options, key) ⇒ Object
132 133 134 |
# File 'lib/logbrew/operation_tracing.rb', line 132 def read_option(, key) .key?(key) ? [key] : [key.to_s] end |
.sanitized_metadata(metadata) ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/logbrew/operation_tracing.rb', line 110 def () return {} if .nil? raise SdkError.new("validation_error", "operation metadata must be an object") unless .is_a?(Hash) .each_with_object({}) do |(key, value), copied| normalized_key = key.to_s next if normalized_key.strip.empty? next if (normalized_key) next unless CaptureHelpers.(value) copied[normalized_key] = value end end |
.span_events(error) ⇒ Object
96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/logbrew/operation_tracing.rb', line 96 def span_events(error) return nil unless error [ { name: "exception", metadata: { exceptionType: error.class.name, exceptionEscaped: true } } ] end |
.span_metadata(kind, options, error) ⇒ Object
86 87 88 89 90 91 92 93 94 |
# File 'lib/logbrew/operation_tracing.rb', line 86 def (kind, , error) (read_option(, :metadata)).tap do || ["source"] = read_option(, :source) || "#{kind}.operation" add_option(, "#{kind}.system", read_option(, :system)) add_option(, "#{kind}.operation", read_option(, :operation)) add_option(, "#{kind}.target", read_option(, :target)) ["exceptionType"] = error.class.name if error end end |
.timestamp(options) ⇒ Object
140 141 142 143 144 145 |
# File 'lib/logbrew/operation_tracing.rb', line 140 def () value = read_option(, :timestamp) return value unless value.nil? Time.now.utc.iso8601 end |
.unsafe_metadata_key?(key) ⇒ Boolean
124 125 126 |
# File 'lib/logbrew/operation_tracing.rb', line 124 def (key) key.match?(UNSAFE_METADATA) end |