Class: ScoutApm::Sampling

Inherits:
Object
  • Object
show all
Defined in:
lib/scout_apm/sampling.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ Sampling

Returns a new instance of Sampling.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/scout_apm/sampling.rb', line 5

def initialize(config)
  @global_sample_rate = config.value('sample_rate')
  # web endpoints matched prefix by regex
  # jobs matched explicitly by name

  # for now still support old config key ('ignore') for backwards compatibility
  @ignore_endpoints = config.value('ignore').present? ? config.value('ignore') : config.value('ignore_endpoints')
  @sample_endpoints = individual_sample_to_hash(config.value('sample_endpoints'))
  @endpoint_sample_rate = config.value('endpoint_sample_rate')

  @ignore_jobs = config.value('ignore_jobs')
  @sample_jobs = individual_sample_to_hash(config.value('sample_jobs'))
  @job_sample_rate = config.value('job_sample_rate')

  logger.info("Sampling initialized with config: global_sample_rate: #{@global_sample_rate}, endpoint_sample_rate: #{@endpoint_sample_rate}, sample_endpoints: #{@sample_endpoints}, ignore_endpoints: #{@ignore_endpoints}, job_sample_rate: #@job_sample_rate}, sample_jobs: #{@sample_jobs}, ignore_jobs: #{@ignore_jobs}")
end

Instance Attribute Details

#global_sample_rateObject (readonly)

Returns the value of attribute global_sample_rate.



3
4
5
# File 'lib/scout_apm/sampling.rb', line 3

def global_sample_rate
  @global_sample_rate
end

#ignore_jobsObject (readonly)

Returns the value of attribute ignore_jobs.



3
4
5
# File 'lib/scout_apm/sampling.rb', line 3

def ignore_jobs
  @ignore_jobs
end

#ignore_uri_regexObject (readonly)

Returns the value of attribute ignore_uri_regex.



3
4
5
# File 'lib/scout_apm/sampling.rb', line 3

def ignore_uri_regex
  @ignore_uri_regex
end

#sample_endpointsObject (readonly)

Returns the value of attribute sample_endpoints.



3
4
5
# File 'lib/scout_apm/sampling.rb', line 3

def sample_endpoints
  @sample_endpoints
end

#sample_jobsObject (readonly)

Returns the value of attribute sample_jobs.



3
4
5
# File 'lib/scout_apm/sampling.rb', line 3

def sample_jobs
  @sample_jobs
end

#sample_uri_regexObject (readonly)

Returns the value of attribute sample_uri_regex.



3
4
5
# File 'lib/scout_apm/sampling.rb', line 3

def sample_uri_regex
  @sample_uri_regex
end

Instance Method Details

#drop_request?(transaction) ⇒ Boolean

Returns:

  • (Boolean)


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
# File 'lib/scout_apm/sampling.rb', line 22

def drop_request?(transaction)
  # Individual endpoint/job sampling takes precedence over ignoring.
  # Individual endpoint/job sample rate always takes precedence over general endpoint/job rate.
  # General endpoint/job rate always takes precedence over global sample rate
  if transaction.job?
    job_name = transaction.layer_finder.job.name
    rate = job_sample_rate(job_name)
    return sample?(rate) unless rate.nil?
    return true if ignore_job?(job_name)
    return sample?(@job_sample_rate) unless @job_sample_rate.nil?
  elsif transaction.web?
    uri = transaction.annotations[:uri]
    rate = web_sample_rate(uri)
    return sample?(rate) unless rate.nil?
    return true if ignore_uri?(uri)
    return sample?(@endpoint_sample_rate) unless @endpoint_sample_rate.nil?
  end

  # global sample check
  if @global_sample_rate
    return sample?(@global_sample_rate)
  end

  false # don't drop the request
end

#ignore_job?(job_name) ⇒ Boolean

Returns:

  • (Boolean)


75
76
77
78
# File 'lib/scout_apm/sampling.rb', line 75

def ignore_job?(job_name)
  return false if @ignore_jobs.blank?
  @ignore_jobs.include?(job_name)
end

#ignore_uri?(uri) ⇒ Boolean

Returns:

  • (Boolean)


59
60
61
62
63
64
65
# File 'lib/scout_apm/sampling.rb', line 59

def ignore_uri?(uri)
  return false if @ignore_endpoints.blank?
  @ignore_endpoints.each do |prefix|
    return true if uri.start_with?(prefix)
  end
  false
end

#individual_sample_to_hash(sampling_config) ⇒ Object



48
49
50
51
52
53
54
55
56
57
# File 'lib/scout_apm/sampling.rb', line 48

def individual_sample_to_hash(sampling_config)
  return nil if sampling_config.blank?
  # config looks like ['/foo:50','/bar:100']. parse it into hash of string: integer
  sample_hash = {}
  sampling_config.each do |sample|
    path, rate = sample.split(':')
    sample_hash[path] = rate.to_i
  end
  sample_hash
end

#job_sample_rate(job_name) ⇒ Object



80
81
82
83
# File 'lib/scout_apm/sampling.rb', line 80

def job_sample_rate(job_name)
  return nil if @sample_jobs.blank?
  @sample_jobs.fetch(job_name, nil)
end

#sample?(rate) ⇒ Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/scout_apm/sampling.rb', line 85

def sample?(rate)
  rand * 100 > rate
end

#web_sample_rate(uri) ⇒ Object



67
68
69
70
71
72
73
# File 'lib/scout_apm/sampling.rb', line 67

def web_sample_rate(uri)
  return nil if @sample_endpoints.blank?
  @sample_endpoints.each do |prefix, rate|
    return rate if uri.start_with?(prefix)
  end
  nil
end