Class: LogBrew::TelemetryContext

Inherits:
Object
  • Object
show all
Defined in:
lib/logbrew/telemetry_context.rb

Overview

Immutable schema-v1 resource, trace, session, subject, and tag context.

Constant Summary collapse

SCHEMA_VERSION =
1
ROOT_FIELDS =
%w[schemaVersion resource trace session subject tags].freeze
TRACE_FIELDS =
%w[traceId spanId parentSpanId sampled].freeze
SESSION_FIELDS =
%w[id previousId].freeze
SUBJECT_FIELDS =
%w[id kind].freeze

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.createObject



15
16
17
# File 'lib/logbrew/telemetry_context.rb', line 15

def self.create
  TelemetryContextBuilder.new
end

.from_hash(value = nil, **keywords) ⇒ Object



19
20
21
22
23
24
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/telemetry_context.rb', line 19

def self.from_hash(value = nil, **keywords)
  if value.nil?
    value = keywords
  elsif !keywords.empty?
    raise TelemetryContextValue.invalid("telemetry context must be one object")
  end
  object = TelemetryContextValue.object(value, "telemetry context")
  TelemetryContextValue.reject_unknown_fields(object, ROOT_FIELDS, "telemetry context")
  unless object["schemaVersion"] == SCHEMA_VERSION
    raise TelemetryContextValue.invalid("telemetry context schemaVersion must be 1")
  end

  normalized = { "schemaVersion" => SCHEMA_VERSION }
  if object.key?("resource")
    normalized["resource"] = TelemetryResource.from_hash(object.fetch("resource")).to_h
  end
  normalized["trace"] = normalize_trace(object.fetch("trace")) if object.key?("trace")
  normalized["session"] = normalize_session(object.fetch("session")) if object.key?("session")
  normalized["subject"] = normalize_subject(object.fetch("subject")) if object.key?("subject")
  normalized["tags"] = normalize_tags(object.fetch("tags")) if object.key?("tags")
  if normalized.length == 1
    raise TelemetryContextValue.invalid(
      "telemetry context must include resource, trace, session, subject, or tags"
    )
  end

  new(normalized)
end

.merge(base, override) ⇒ Object

Resource fields and tags merge by field. Trace, session, and subject are replaced.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/logbrew/telemetry_context.rb', line 49

def self.merge(base, override)
  require_context_or_nil(base, "base telemetry context")
  require_context_or_nil(override, "override telemetry context")
  return nil if base.nil? && override.nil?
  return from_hash(override.to_h) if base.nil?
  return from_hash(base.to_h) if override.nil?

  base_value = base.to_h
  override_value = override.to_h
  merged = { "schemaVersion" => SCHEMA_VERSION }

  base_resource = resource_from_value(base_value["resource"])
  override_resource = resource_from_value(override_value["resource"])
  resource = TelemetryResource.merge(base_resource, override_resource)
  merged["resource"] = resource.to_h unless resource.nil?

  %w[trace session subject].each do |section|
    value = override_value[section] || base_value[section]
    merged[section] = value unless value.nil?
  end

  base_tags = base_value["tags"] || {}
  override_tags = override_value["tags"] || {}
  unless base_tags.empty? && override_tags.empty?
    tags = base_tags.merge(override_tags)
    TelemetryContextValue.require_tag_count(tags.length)
    merged["tags"] = tags.keys.sort.each_with_object({}) { |key, sorted| sorted[key] = tags.fetch(key) }
  end

  from_hash(merged)
end

.runtime_defaultsObject

Conservative Ruby runtime, OS-family/release, and architecture identity.



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/logbrew/telemetry_context.rb', line 93

def self.runtime_defaults
  runtime_name = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
  resource = TelemetryResource.create.with_runtime(name: runtime_name, version: RUBY_VERSION)
  uname = safe_uname
  operating_system = normalize_os_name(
    safe_runtime_value(uname && uname[:sysname]) ||
      safe_runtime_value(RbConfig::CONFIG["host_os"])
  )
  operating_system_version = safe_runtime_value(uname && uname[:release])
  architecture = safe_runtime_value(uname && uname[:machine]) ||
                 safe_runtime_value(RbConfig::CONFIG["host_cpu"])
  unless operating_system.nil?
    resource.with_operating_system(name: operating_system, version: operating_system_version)
  end
  resource.with_device(architecture: architecture) unless architecture.nil?
  create.with_resource(resource.build).build
end

.with_trace(context, trace) ⇒ Object

Add exact active trace correlation over any existing context.



82
83
84
85
86
87
88
89
90
# File 'lib/logbrew/telemetry_context.rb', line 82

def self.with_trace(context, trace)
  require_context_or_nil(context, "telemetry context")
  unless defined?(LogBrew::TraceContext) && trace.is_a?(LogBrew::TraceContext)
    raise TelemetryContextValue.invalid("trace must be a LogBrew::TraceContext")
  end

  trace_context = create.with_trace(trace).build
  merge(context, trace_context)
end

Instance Method Details

#to_hObject



111
112
113
# File 'lib/logbrew/telemetry_context.rb', line 111

def to_h
  TelemetryContextValue.deep_copy(@value)
end