Module: LogBrew::Trace
- Defined in:
- lib/logbrew/trace.rb
Overview
Request-local trace context for app-owned logs, errors, actions, and metrics.
Class Method Summary collapse
- .activate(context) ⇒ Object
- .add_metadata(target, context = current) ⇒ Object
- .close_scope(scope_id) ⇒ Object
- .continue_or_create(traceparent) ⇒ Object
- .create(trace_id:, span_id:, trace_flags: "01", parent_span_id: nil) ⇒ Object
- .create_headers(context = current) ⇒ Object
- .create_root ⇒ Object
- .current ⇒ Object
- .from_rack_env(env) ⇒ Object
- .from_traceparent(traceparent) ⇒ Object
- .generate_span_id ⇒ Object
- .generate_trace_id ⇒ Object
- .merge_attributes(attributes, context = current) ⇒ Object
- .metadata(context = current) ⇒ Object
- .with_context(context) ⇒ Object
Class Method Details
.activate(context) ⇒ Object
34 35 36 37 38 39 40 41 42 |
# File 'lib/logbrew/trace.rb', line 34 def activate(context) unless context.is_a?(TraceContext) raise SdkError.new("validation_error", "trace context must be a LogBrew::TraceContext") end scope_id = Object.new.object_id stack << { id: scope_id, context: context } TraceScope.new(scope_id) end |
.add_metadata(target, context = current) ⇒ Object
125 126 127 128 129 130 131 132 |
# File 'lib/logbrew/trace.rb', line 125 def (target, context = current) return target unless context (context).each do |key, value| target[key] = value unless target.key?(key) || target.key?(key.to_sym) end target end |
.close_scope(scope_id) ⇒ Object
51 52 53 54 55 |
# File 'lib/logbrew/trace.rb', line 51 def close_scope(scope_id) entries = stack index = entries.rindex { |entry| entry[:id] == scope_id } entries.delete_at(index) unless index.nil? end |
.continue_or_create(traceparent) ⇒ Object
57 58 59 60 61 62 63 64 |
# File 'lib/logbrew/trace.rb', line 57 def continue_or_create(traceparent) text = traceparent.to_s.strip return create_root if text.empty? from_traceparent(text) rescue SdkError create_root end |
.create(trace_id:, span_id:, trace_flags: "01", parent_span_id: nil) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/logbrew/trace.rb', line 80 def create(trace_id:, span_id:, trace_flags: "01", parent_span_id: nil) normalized_traceparent = Traceparent.create(trace_id: trace_id, span_id: span_id, trace_flags: trace_flags) _version, normalized_trace_id, normalized_span_id, normalized_flags = normalized_traceparent.split("-") normalized_parent_span_id = nil unless parent_span_id.nil? parent_traceparent = Traceparent.create( trace_id: normalized_trace_id, span_id: parent_span_id, trace_flags: normalized_flags ) normalized_parent_span_id = parent_traceparent.split("-")[2] end TraceContext.new( trace_id: normalized_trace_id, span_id: normalized_span_id, parent_span_id: normalized_parent_span_id, trace_flags: normalized_flags, sampled: (normalized_flags.to_i(16) & 1) == 1 ) end |
.create_headers(context = current) ⇒ Object
102 103 104 105 106 107 108 109 110 |
# File 'lib/logbrew/trace.rb', line 102 def create_headers(context = current) return {} unless context Traceparent.create_headers( trace_id: context.trace_id, span_id: context.span_id, trace_flags: context.trace_flags ) end |
.create_root ⇒ Object
76 77 78 |
# File 'lib/logbrew/trace.rb', line 76 def create_root create(trace_id: generate_trace_id, span_id: generate_span_id, trace_flags: "01") end |
.current ⇒ Object
29 30 31 32 |
# File 'lib/logbrew/trace.rb', line 29 def current entry = stack.last entry && entry[:context] end |
.from_rack_env(env) ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/logbrew/trace.rb', line 151 def from_rack_env(env) existing = env_value(env, "logbrew.trace") return existing if existing.is_a?(TraceContext) traceparent = env_value(env, "HTTP_TRACEPARENT") || env_value(env, "traceparent") || env_value(env, "logbrew.traceparent") return continue_or_create(traceparent) unless traceparent.nil? || traceparent.empty? trace_id = env_value(env, "logbrew.trace_id") span_id = env_value(env, "logbrew.span_id") if trace_id && span_id begin return create( trace_id: trace_id, span_id: span_id, parent_span_id: env_value(env, "logbrew.parent_span_id"), trace_flags: env_value(env, "logbrew.trace_flags") || "01" ) rescue SdkError nil end end create_root end |
.from_traceparent(traceparent) ⇒ Object
66 67 68 69 70 71 72 73 74 |
# File 'lib/logbrew/trace.rb', line 66 def from_traceparent(traceparent) context = Traceparent.parse(traceparent) create( trace_id: context.trace_id, span_id: generate_span_id, parent_span_id: context.parent_span_id, trace_flags: context.trace_flags ) end |
.generate_span_id ⇒ Object
183 184 185 186 187 188 |
# File 'lib/logbrew/trace.rb', line 183 def generate_span_id loop do value = SecureRandom.hex(8) return value unless value.delete("0").empty? end end |
.generate_trace_id ⇒ Object
176 177 178 179 180 181 |
# File 'lib/logbrew/trace.rb', line 176 def generate_trace_id loop do value = SecureRandom.hex(16) return value unless value.delete("0").empty? end end |
.merge_attributes(attributes, context = current) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/logbrew/trace.rb', line 134 def merge_attributes(attributes, context = current) return attributes unless context && attributes.is_a?(Hash) = attributes.key?("metadata") ? attributes["metadata"] : attributes[:metadata] return attributes unless .nil? || .is_a?(Hash) copied = attributes.dup = .nil? ? {} : .dup (, context) if copied.key?(:metadata) && !copied.key?("metadata") copied[:metadata] = else copied["metadata"] = end copied end |
.metadata(context = current) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/logbrew/trace.rb', line 112 def (context = current) return {} unless context { "traceId" => context.trace_id, "spanId" => context.span_id, "traceFlags" => context.trace_flags, "traceSampled" => context.sampled }.tap do |payload| payload["parentSpanId"] = context.parent_span_id unless context.parent_span_id.nil? end end |
.with_context(context) ⇒ Object
44 45 46 47 48 49 |
# File 'lib/logbrew/trace.rb', line 44 def with_context(context) scope = activate(context) yield context ensure scope.close if scope end |