Module: Logister::ContextHelpers

Defined in:
lib/logister/context_helpers.rb

Constant Summary collapse

FILTERED_VALUE =
"[FILTERED]".freeze

Class Method Summary collapse

Class Method Details

.anonymize_ip(ip) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/logister/context_helpers.rb', line 88

def anonymize_ip(ip)
  return nil if ip.to_s.strip.empty?
  return ip.to_s unless configuration_value(:anonymize_ip, false)

  parsed = IPAddr.new(ip.to_s)
  if parsed.ipv4?
    segments = ip.to_s.split(".")
    return ip.to_s if segments.size != 4

    "#{segments[0]}.#{segments[1]}.#{segments[2]}.0"
  else
    "#{parsed.mask(64).to_s}/64"
  end
rescue StandardError
  ip.to_s
end

.blank_value?(value) ⇒ Boolean

Returns:

  • (Boolean)


161
162
163
# File 'lib/logister/context_helpers.rb', line 161

def blank_value?(value)
  value.nil? || (value.respond_to?(:empty?) && value.empty?)
end

.compact_deep(value) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/logister/context_helpers.rb', line 145

def compact_deep(value)
  case value
  when Hash
    value.each_with_object({}) do |(key, nested), acc|
      compacted = compact_deep(nested)
      next if blank_value?(compacted)

      acc[key] = compacted
    end
  when Array
    value.map { |item| compact_deep(item) }.reject { |item| blank_value?(item) }
  else
    value
  end
end

.deployment_contextObject



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/logister/context_helpers.rb', line 22

def deployment_context
  config = Logister.configuration if Logister.respond_to?(:configuration)
  environment = config&.respond_to?(:environment) ? config.environment.to_s.presence : nil
  service = config&.respond_to?(:service) ? config.service.to_s.presence : nil
  release = config&.respond_to?(:release) ? config.release.to_s.presence : nil

  {
    deployment: {
      environment: environment || ENV["RAILS_ENV"].to_s.presence || ENV["RACK_ENV"].to_s.presence || "development",
      service: service || ENV["LOGISTER_SERVICE"].to_s.presence || "ruby-app",
      release: release || ENV["LOGISTER_RELEASE"].to_s.presence,
      region: ENV["FLY_REGION"].to_s.presence || ENV["RAILS_REGION"].to_s.presence || ENV["AWS_REGION"].to_s.presence,
      hostname: Socket.gethostname.to_s.presence,
      processPid: Process.pid
    }.compact
  }
end

.filtered_job_arguments(job) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/logister/context_helpers.rb', line 119

def filtered_job_arguments(job)
  arguments = Array(job.arguments)
  return arguments if arguments.empty?

  filter = ActiveSupport::ParameterFilter.new(
    Array(Rails.application.config.filter_parameters)
  )
  arguments.map { |argument| filter_argument(argument, filter) }
rescue StandardError
  arguments
end

.hash_value(value) ⇒ Object



139
140
141
142
143
# File 'lib/logister/context_helpers.rb', line 139

def hash_value(value)
  return nil if value.to_s.strip.empty?

  Digest::SHA256.hexdigest(value.to_s.strip.downcase)
end

.resolve_dependency_context(request:, env:) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/logister/context_helpers.rb', line 75

def resolve_dependency_context(request:, env:)
  resolver = configuration_value(:dependency_resolver)
  return {} unless resolver.respond_to?(:call)

  raw = call_resolver(resolver, request: request, env: env)
  list = normalize_dependency_list(raw)
  return {} if list.empty?

  { dependencyCalls: list }
rescue StandardError
  {}
end

.resolve_feature_flags(request:, env:, user:) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/logister/context_helpers.rb', line 62

def resolve_feature_flags(request:, env:, user:)
  resolver = configuration_value(:feature_flags_resolver)
  return {} unless resolver.respond_to?(:call)

  raw = call_resolver(resolver, request: request, env: env, user: user)
  flags = normalize_flags_hash(raw)
  return {} if flags.empty?

  { featureFlags: flags }
rescue StandardError
  {}
end

.runtime_contextObject



11
12
13
14
15
16
17
18
19
20
# File 'lib/logister/context_helpers.rb', line 11

def runtime_context
  {
    runtime: {
      rubyVersion: RUBY_VERSION,
      railsVersion: defined?(Rails) ? Rails.version : nil,
      rackVersion: defined?(Rack) ? Rack.release : nil,
      platform: RUBY_PLATFORM
    }.compact
  }
end

.safe_call(object, method_name) ⇒ Object



131
132
133
134
135
136
137
# File 'lib/logister/context_helpers.rb', line 131

def safe_call(object, method_name)
  return nil unless object.respond_to?(method_name)

  object.public_send(method_name)
rescue StandardError
  nil
end

.trace_context(headers:, env:) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/logister/context_helpers.rb', line 40

def trace_context(headers:, env:)
  traceparent = header_value(headers, "Traceparent")
  b3_trace_id = header_value(headers, "X-B3-Traceid")
  b3_span_id = header_value(headers, "X-B3-Spanid")
  datadog_trace_id = header_value(headers, "X-Datadog-Trace-Id")
  datadog_parent_id = header_value(headers, "X-Datadog-Parent-Id")
  amzn_trace_id = header_value(headers, "X-Amzn-Trace-Id")

  parsed_trace_id, parsed_span_id, parsed_sampled = parse_traceparent(traceparent)

  {
    trace: {
      traceId: parsed_trace_id || b3_trace_id || datadog_trace_id,
      spanId: parsed_span_id || b3_span_id || datadog_parent_id,
      sampled: parsed_sampled,
      traceparent: traceparent,
      requestId: env["action_dispatch.request_id"].to_s.presence,
      amznTraceId: amzn_trace_id
    }.compact
  }
end

.user_context_for(user) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/logister/context_helpers.rb', line 105

def user_context_for(user)
  return {} unless user

  {
    user: {
      id: safe_call(user, :id).to_s.presence,
      class: user.class.name.to_s.presence,
      email_hash: hashed_email(user),
      role: safe_call(user, :role).to_s.presence,
      account_id: safe_call(user, :account_id).to_s.presence || safe_call(user, :tenant_id).to_s.presence
    }.compact
  }
end