Class: Labkit::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/labkit/context.rb

Overview

A context can be used to provide structured information on what resources GitLab is working on within a service.

Values can be provided by passing a hash. If one of the values is a Proc the proc will only be called when the value is actually needed.

Multiple contexts can be nested, the nested context will inherit the values from the closest outer one. All contexts will have the same correlation id.

Usage:

Labkit::Context.with_context(user: 'username', root_namespace: -> { get_root_namespace } do |context|
  logger.info(context.to_h)
end

Constant Summary collapse

LOG_KEY =
"meta"
CORRELATION_ID_KEY =
"correlation_id"
RAW_KEYS =
[CORRELATION_ID_KEY].freeze
HEADER_PREFIX =
"X-Gitlab-"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(values = {}) ⇒ Context

Returns a new instance of Context.



85
86
87
88
89
# File 'lib/labkit/context.rb', line 85

def initialize(values = {})
  @data = {}

  assign_attributes(values)
end

Class Method Details

.correlation_idObject



54
55
56
# File 'lib/labkit/context.rb', line 54

def correlation_id
  contexts.last&.correlation_id
end

.currentObject



58
59
60
# File 'lib/labkit/context.rb', line 58

def current
  contexts.last
end

.header_name(name) ⇒ Object



74
75
76
# File 'lib/labkit/context.rb', line 74

def header_name(name)
  HEADER_PREFIX + log_key(name).titlecase(keep_id_suffix: true).gsub(/\W/, "-")
end

.known_log_keysObject



70
71
72
# File 'lib/labkit/context.rb', line 70

def known_log_keys
  @known_log_keys ||= (KNOWN_KEYS.map(&method(:log_key)) + RAW_KEYS).freeze
end

.log_key(key) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/labkit/context.rb', line 62

def log_key(key)
  key = key.to_s
  return key if RAW_KEYS.include?(key)
  return key if key.starts_with?("#{LOG_KEY}.")

  "#{LOG_KEY}.#{key}"
end

.pop(context) ⇒ Object



50
51
52
# File 'lib/labkit/context.rb', line 50

def pop(context)
  contexts.pop while contexts.include?(context)
end

.push(new_attributes = {}) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/labkit/context.rb', line 42

def push(new_attributes = {})
  new_context = current&.merge(new_attributes) || new(new_attributes)

  contexts.push(new_context)

  new_context
end

.with_context(attributes = {}) ⇒ Object



32
33
34
35
36
37
38
39
40
# File 'lib/labkit/context.rb', line 32

def with_context(attributes = {})
  context = push(attributes)

  begin
    yield(context)
  ensure
    pop(context)
  end
end

Instance Method Details

#correlation_idObject



102
103
104
# File 'lib/labkit/context.rb', line 102

def correlation_id
  data[CORRELATION_ID_KEY]
end

#get_attribute(attribute) ⇒ Object



112
113
114
115
116
# File 'lib/labkit/context.rb', line 112

def get_attribute(attribute)
  raw = call_or_value(data[log_key(attribute)])

  call_or_value(raw)
end

#merge(new_attributes) ⇒ Object



91
92
93
94
95
96
# File 'lib/labkit/context.rb', line 91

def merge(new_attributes)
  new_context = self.class.new(data.dup)
  new_context.assign_attributes(new_attributes)

  new_context
end

#to_hObject



98
99
100
# File 'lib/labkit/context.rb', line 98

def to_h
  expand_data
end

#to_headersObject



106
107
108
109
110
# File 'lib/labkit/context.rb', line 106

def to_headers
  to_h.except(CORRELATION_ID_KEY).transform_keys do |key|
    self.class.header_name(key)
  end
end