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.



88
89
90
91
92
# File 'lib/labkit/context.rb', line 88

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

  assign_attributes(values)
end

Class Method Details

.clearObject



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

def clear
  Thread.current[:labkit_contexts] = nil
end

.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



73
74
75
76
77
78
79
# File 'lib/labkit/context.rb', line 73

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



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

def correlation_id
  data[Fields::CORRELATION_ID]
end

#get_attribute(attribute) ⇒ Object



109
110
111
112
113
# File 'lib/labkit/context.rb', line 109

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

  call_or_value(raw)
end

#merge(new_attributes) ⇒ Object



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

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

  new_context
end

#to_hObject



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

def to_h
  expand_data
end