Class: Instana::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/instana/config.rb

Constant Summary collapse

LEGACY_TRACING_KEY =
'com.instana.tracing'.freeze
TRACING_KEY =
'tracing'.freeze

Instance Method Summary collapse

Constructor Details

#initialize(logger: ::Instana.logger, agent_host: ENV.fetch('INSTANA_AGENT_HOST', nil), agent_port: ENV.fetch('INSTANA_AGENT_PORT', nil)) ⇒ Config

rubocop:disable Metrics/MethodLength



12
13
14
15
16
17
18
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
47
48
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/instana/config.rb', line 12

def initialize(logger: ::Instana.logger, agent_host: ENV.fetch('INSTANA_AGENT_HOST', nil), agent_port: ENV.fetch('INSTANA_AGENT_PORT', nil)) # rubocop:disable Metrics/MethodLength
  @config = {}
  if agent_host
    logger.debug "Using custom agent host location specified in INSTANA_AGENT_HOST (#{agent_host})"
    @config[:agent_host] = agent_host
  else
    @config[:agent_host] = '127.0.0.1'
  end
  if agent_port
    logger.debug "Using custom agent port specified in INSTANA_AGENT_PORT (#{agent_port})"
    @config[:agent_port] = agent_port
  else
    @config[:agent_port] = 42699
  end

  # Enable/disable metrics globally or individually (default: all enabled)
  @config[:metrics] = { :enabled => true }
  @config[:metrics][:gc]     = { :enabled => true }
  @config[:metrics][:memory] = { :enabled => true }
  @config[:metrics][:thread] = { :enabled => true }

  # Enable/disable tracing (default: enabled)
  @config[:tracing] = { :enabled => true }

  # Enable/disable tracing exit spans as root spans
  @config[:allow_exit_as_root] = ENV.fetch('INSTANA_ALLOW_EXIT_AS_ROOT', nil) == '1'

  # Enable/Disable logging
  @config[:logging] = { :enabled => true }

  # Collector interval
  @config[:collector] = { :enabled => true, :interval => 1 }

  # EUM Related
  @config[:eum_api_key] = nil
  @config[:eum_baggage] = {}

  # In Ruby, backtrace collection is very expensive so it's
  # (unfortunately) disabled by default.  If you still want
  # backtraces, it can be enabled with this config option.
  # @config[:back_trace][:stack_trace_level] = all
  # @config[:back_trace] = { stack_trace_level: nil }
  read_span_stack_config

  # OTLP exporter configuration (default: disabled)
  @config[:otlp] = {
    enabled: false,
    endpoint: 'http://localhost:4318/v1/traces',
    timeout: 10_000,
    compression: nil,
    headers: {},
    certificate: nil,
    client_key: nil,
    client_certificate: nil,
    config_source: 'default'
  }
  read_otlp_config

  # By default, collected SQL will be sanitized to remove potentially sensitive bind params such as:
  #   > SELECT  "blocks".* FROM "blocks"  WHERE "blocks"."name" = "Mr. Smith"
  #
  # ...would be sanitized to be:
  #   > SELECT  "blocks".* FROM "blocks"  WHERE "blocks"."name" = ?
  #
  # This sanitization step can be disabled by setting the following value to false.
  # ::Instana.config[:sanitize_sql] = false
  @config[:sanitize_sql] = true

  # W3C Trace Context Support
  @config[:w3c_trace_correlation] = ENV.fetch('INSTANA_DISABLE_W3C_TRACE_CORRELATION', nil).nil?

  @config[:post_fork_proc] = proc { ::Instana.agent.spawn_background_thread }

  @config[:action_controller]  = { :enabled => true }
  @config[:action_view]        = { :enabled => true }
  @config[:active_record]      = { :enabled => true }
  @config[:bunny]              = { :enabled => true }
  @config[:dalli]              = { :enabled => true }
  @config[:excon]              = { :enabled => true }
  @config[:grpc]               = { :enabled => true }
  @config[:graphql]            = { :enabled => true }
  @config[:nethttp]            = { :enabled => true }
  @config[:redis]              = { :enabled => true }
  @config[:'resque-client']    = { :enabled => true, :propagate => true }
  @config[:'resque-worker']    = { :enabled => true, :'setup-fork' => true }
  @config[:'rest-client']      = { :enabled => true }
  @config[:sequel]             = { :enabled => true }
  @config[:'sidekiq-client']   = { :enabled => true }
  @config[:'sidekiq-worker']   = { :enabled => true }
end

Instance Method Details

#[](key) ⇒ Object



103
104
105
# File 'lib/instana/config.rb', line 103

def [](key)
  @config[key.to_sym]
end

#[]=(key, value) ⇒ Object



107
108
109
# File 'lib/instana/config.rb', line 107

def []=(key, value)
  @config[key.to_sym] = value
end

#apply_default_stack_trace_configObject

Apply default stack trace configuration



208
209
210
211
212
213
214
215
# File 'lib/instana/config.rb', line 208

def apply_default_stack_trace_config
  @config[:back_trace] = {
    stack_trace_level: 'error',
    stack_trace_length: 30,
    config_source: 'default'
  }
  @config[:back_trace_technologies] = {}
end

#get_stack_trace_config(technology) ⇒ Hash

Get stack trace configuration for a specific technology Falls back to global configuration if technology-specific config is not found

Parameters:

  • technology (Symbol)

    The technology name (e.g., :excon, :kafka, :activerecord)

Returns:

  • (Hash)

    Configuration hash with :stack_trace_level and :stack_trace_length



230
231
232
233
234
235
236
237
238
# File 'lib/instana/config.rb', line 230

def get_stack_trace_config(technology)
  tech_config = @config[:back_trace_technologies]&.[](technology)
  global_config = @config[:back_trace] || {}

  {
    stack_trace_level: tech_config&.[](:stack_trace_level) || global_config[:stack_trace_level] || 'error',
    stack_trace_length: tech_config&.[](:stack_trace_length) || global_config[:stack_trace_length] || 30
  }
end

#read_config_from_agent(discovery) ⇒ Object

Read configuration from agent discovery response This is called after agent discovery is complete

Parameters:

  • discovery (Hash)

    The discovery response from the agent



136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/instana/config.rb', line 136

def read_config_from_agent(discovery)
  return unless discovery.is_a?(Hash) && discovery['tracing']

  tracing_config = discovery['tracing']

  # Read stack trace configuration from agent if not already set from YAML or env
  read_span_stack_config_from_agent(tracing_config) if should_read_from_agent?(:back_trace)
  # Read OTLP configuration from agent if not already set from YAML or env
  read_otlp_config_from_agent(tracing_config) if should_read_from_agent?(:otlp)
  # Read span filtering configuration from agent
  ::Instana.span_filtering_config&.read_config_from_agent(discovery)
rescue => e
  ::Instana.logger.warn("Failed to read configuration from agent: #{e.message}")
end

#read_otlp_config_from_agent(tracing_config) ⇒ Object

Read OTLP configuration from agent discovery

Parameters:

  • tracing_config (Hash)

    The tracing configuration from discovery



242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/instana/config.rb', line 242

def read_otlp_config_from_agent(tracing_config)
  otlp_config = tracing_config['otlp']
  return unless otlp_config.is_a?(Hash)

  @config[:otlp][:enabled]            = truthy?(otlp_config['enabled'])         unless otlp_config['enabled'].nil?
  @config[:otlp][:endpoint]           = otlp_config['endpoint']                 if otlp_config['endpoint']
  @config[:otlp][:timeout]            = otlp_config['timeout'].to_i             if otlp_config['timeout']
  @config[:otlp][:compression]        = otlp_config['compression']              if otlp_config['compression']
  @config[:otlp][:headers]            = otlp_config['headers']                  if otlp_config['headers'].is_a?(Hash)
  @config[:otlp][:certificate]        = otlp_config['certificate']              if otlp_config['certificate']
  @config[:otlp][:client_key]         = otlp_config['client_key']               if otlp_config['client_key']
  @config[:otlp][:client_certificate] = otlp_config['client_certificate']       if otlp_config['client_certificate']
  @config[:otlp][:config_source]      = 'agent'
end

#read_span_stack_configObject

Read stack trace configuration from environment variables, YAML file, or use defaults Priority: Environment variables > YAML file > Agent discovery > Defaults



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/instana/config.rb', line 113

def read_span_stack_config
  # Try environment variables first
  if ENV.fetch('INSTANA_STACK_TRACE', nil) || ENV.fetch('INSTANA_STACK_TRACE_LENGTH', nil)
    read_span_stack_config_from_env
    @config[:back_trace_technologies] = {}
    return
  end

  # Try YAML file
  yaml_config = read_span_stack_config_from_yaml
  if yaml_config
    @config[:back_trace] = yaml_config[:global]
    @config[:back_trace_technologies] = yaml_config[:technologies] || {}
    return
  end

  # Use defaults
  apply_default_stack_trace_config
end

#read_span_stack_config_from_agent(tracing_config) ⇒ Object

Read stack trace configuration from agent discovery

Parameters:

  • tracing_config (Hash)

    The tracing configuration from discovery



153
154
155
156
157
158
159
160
161
# File 'lib/instana/config.rb', line 153

def read_span_stack_config_from_agent(tracing_config)
  return unless tracing_config['global']

  global_config = parse_global_stack_trace_config(tracing_config['global'], 'agent')
  @config[:back_trace] = global_config if global_config

  # Read technology-specific configurations
  @config[:back_trace_technologies] = parse_technology_configs(tracing_config)
end

#read_span_stack_config_from_envObject

Read stack trace configuration from environment variables



199
200
201
202
203
204
205
# File 'lib/instana/config.rb', line 199

def read_span_stack_config_from_env
  @config[:back_trace] = {
    stack_trace_level: ENV.fetch('INSTANA_STACK_TRACE', 'error'),
    stack_trace_length: ENV.fetch('INSTANA_STACK_TRACE_LENGTH', 30).to_i,
    config_source: 'env'
  }
end

#read_span_stack_config_from_yamlObject

Read stack trace configuration from YAML file Returns hash with :global and :technologies keys or nil if not found



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/instana/config.rb', line 165

def read_span_stack_config_from_yaml
  config_path = ENV.fetch('INSTANA_CONFIG_PATH', nil)
  return nil unless config_path && File.exist?(config_path)

  begin
    yaml_content = YAML.safe_load(File.read(config_path))

    # Support both "tracing" and "com.instana.tracing" as top-level keys
    if yaml_content[LEGACY_TRACING_KEY]
      ::Instana.logger.warn("Please use \"#{TRACING_KEY}\" instead of \"#{LEGACY_TRACING_KEY}\"")
    end
    tracing_config = yaml_content[TRACING_KEY] || yaml_content[LEGACY_TRACING_KEY]
    return nil unless tracing_config

    result = {}

    # Look for global stack trace configuration
    if tracing_config['global']
      global_config = parse_global_stack_trace_config(tracing_config['global'], 'yaml')
      result[:global] = global_config if global_config
    end

    # Look for technology-specific configurations
    technologies = parse_technology_configs(tracing_config)
    result[:technologies] = technologies unless technologies.empty?

    result.empty? ? nil : result
  rescue => e
    ::Instana.logger.warn("Failed to load stack trace configuration from YAML: #{e.message}")
    nil
  end
end

#should_read_from_agent?(config_key) ⇒ Boolean

Check if we should read configuration from agent Returns true if config was not set from YAML or environment variables

Returns:

  • (Boolean)


219
220
221
222
223
224
# File 'lib/instana/config.rb', line 219

def should_read_from_agent?(config_key)
  return true unless @config[config_key]

  source = @config[config_key][:config_source]
  source.nil? || source == 'default'
end