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 =

The meta log key is used to effectively aggregate the attributes that we should be associating with the logs that we emit. These fields will get propagated across all services which will allow us to correlate logs across these different services.

"meta"
RAW_KEYS =
[Fields::CORRELATION_ID].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(values = {}) ⇒ Context

Returns a new instance of Context.



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

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

  assign_attributes(values)
end

Class Method Details

.correlation_idObject



61
62
63
# File 'lib/labkit/context.rb', line 61

def correlation_id
  contexts.last&.correlation_id
end

.currentObject



65
66
67
# File 'lib/labkit/context.rb', line 65

def current
  contexts.last
end

.log_key(key) ⇒ Object



69
70
71
72
73
74
75
# File 'lib/labkit/context.rb', line 69

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



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

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

.push(new_attributes = {}) ⇒ Object



49
50
51
52
53
54
55
# File 'lib/labkit/context.rb', line 49

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

  contexts.push(new_context)

  new_context
end

.with_context(attributes = {}) ⇒ Object



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

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

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

Instance Method Details

#correlation_idObject



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

def correlation_id
  data[Fields::CORRELATION_ID]
end

#get_attribute(attribute) ⇒ Object



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

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

  call_or_value(raw)
end

#merge(new_attributes) ⇒ Object



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

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

  new_context
end

#to_hObject



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

def to_h
  expand_data
end