Class: RubyZipkin::RackHandler

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

Instance Method Summary collapse

Constructor Details

#initialize(app, service_name, scribe_server, scribe_port, uri_filter_list = [], http_header_filter_list = [], uri_sample_filter_list = {}, sampling_rate = 0.0001, scribe_max_buffer = 50, redis_config = 'config/redis.yml') ⇒ RackHandler

Returns a new instance of RackHandler.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rubyzipkin.rb', line 17

def initialize(app, service_name, scribe_server, scribe_port, uri_filter_list = [], http_header_filter_list = [], uri_sample_filter_list = {}, sampling_rate = 0.0001, scribe_max_buffer = 50, redis_config = 'config/redis.yml')
  @app = app
  @lock = Mutex.new

  @service_name = service_name
  @scribe_port = scribe_port
  @sample_rate = sampling_rate
  @uri_filter_list = uri_filter_list
  @http_header_filter_list = http_header_filter_list
  @uri_sample_filter_list = uri_sample_filter_list
  @scribe = Scribe.new("#{scribe_server}:#{scribe_port}")
  @redis_config = redis_config
  @sampled_ids = {}
  $redis_check_time = Time.now
  ::Trace.tracer = ::Trace::ZipkinTracer.new(Scriber.new(@scribe), scribe_max_buffer)

  begin
    if $redis.nil?
      $redis = redis_from_config(@redis_config) if File.exist?(@redis_config)
    end
  rescue => e
    $stderr.puts "ZIPKIN [ERR] Redis instance could not be configured (nil)"
  end
end

Instance Method Details

#add_referer(env) ⇒ Object



154
155
156
157
158
# File 'lib/rubyzipkin.rb', line 154

def add_referer(env)
  if env['HTTP_REFERER']
    ::Trace.record(::Trace::BinaryAnnotation.new("http.referer", env['HTTP_REFERER'], "STRING", ::Trace.default_endpoint))
  end
end

#call(env) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/rubyzipkin.rb', line 42

def call(env)

  if $redis.nil?
    return
  end

  begin
    ::Trace.default_endpoint = ::Trace.default_endpoint.with_service_name(@service_name + "/#{top_level_path(env['PATH_INFO'])}")
    set_sample_rate(env)
    trace_id = get_or_create_trace_id(env)
  rescue => e
    $stderr.puts "ZIPKIN [ERR] #{e}"
  end

  begin
    status, headers, response = @app.call(env)
    redis_sampling(headers)
    tracing_filter(trace_id, env, headers, status)
  rescue => e
    # we want to do the call even if zipkin fails
    $stderr.puts "ZIPKIN [ERR] #{e} \n\n\n #{e.backtrace}"
  end
  [status, headers, response]
end

#get_or_create_trace_id(env) ⇒ Object

Generates a trace ID set in Finagle’s format

  • @param _traceId The id for this request.

  • @param _parentId The id for the request one step up the service stack.

  • @param spanId The id for this particular request

  • @param _sampled Should we sample this request or not? True means sample, false means don’t.



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/rubyzipkin.rb', line 201

def get_or_create_trace_id(env)

  if env[ZipkinTraceHeader::TRACE_ID].nil? or env[ZipkinTraceHeader::TRACE_ID].to_s.empty?
    @tid = Trace.generate_id
    env[ZipkinTraceHeader::TRACE_ID] = @tid
  else
    @tid = env[ZipkinTraceHeader::TRACE_ID]
  end

  if env[ZipkinTraceHeader::SPAN_ID].nil? or env[ZipkinTraceHeader::SPAN_ID].to_s.empty?
      @parentspan = nil
  else
      @parentspan = env[ZipkinTraceHeader::SPAN_ID]
  end

  @spanid = Trace.generate_id

  # Save into HTTP headers
  env[ZipkinTraceHeader::TRACE_ID] = @trace_id
  env[ZipkinTraceHeader::SPAN_ID] = @spanid
  env[ZipkinTraceHeader::PARENT_SPAN_ID] = @parentspan

  Trace::TraceId.new(@tid, @parentspan, @spanid, true)
end

#get_or_create_trace_id2(env) ⇒ Object



226
227
228
# File 'lib/rubyzipkin.rb', line 226

def get_or_create_trace_id2(env)
  ::Trace::TraceId.new(::Trace.generate_id, nil, ::Trace.generate_id, true)
end

#normalized_uri(path) ⇒ Object



160
161
162
# File 'lib/rubyzipkin.rb', line 160

def normalized_uri(path)
  path.gsub(/\/\d+/, '/:id')
end

#redis_sampled_idsObject

Return the current set of IDS to be unsampled as selected from redis.



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

def redis_sampled_ids
  @sampled_ids.to_s
end

#set_trace_caption(env, status) ⇒ Object



177
178
179
# File 'lib/rubyzipkin.rb', line 177

def set_trace_caption(env, status)
  ::Trace.set_rpc_name("#{env['REQUEST_METHOD']} - #{status.to_s} - #{uri_summary(env['PATH_INFO'])}")
end

#top_level_path(path) ⇒ Object



164
165
166
# File 'lib/rubyzipkin.rb', line 164

def top_level_path(path)
  path.split('/')[1]
end

#trace_hash(content) ⇒ Object



186
187
188
189
190
191
192
193
194
# File 'lib/rubyzipkin.rb', line 186

def trace_hash(content)
  if content
    content.sort.map do |k,v|
      unless RubyZipkin::TraceFilter.KeywordFilterMatches?(k.to_s, @http_header_filter_list)
        MetadataLogger.log(k.to_s, v)
      end
    end
  end
end

#trace_post_data(content) ⇒ Object



181
182
183
184
# File 'lib/rubyzipkin.rb', line 181

def trace_post_data(content)
  # Slightly large size cap to the request input to accomodate larger JSON bodies.
  MetadataLogger.log('HTTP_REQUEST_INPUT', content.to_s, 1024)
end

#uri_summary(path) ⇒ Object



168
169
170
171
172
173
174
175
# File 'lib/rubyzipkin.rb', line 168

def uri_summary(path)
  suffix = path.match /\w+$/
  if suffix.to_s.length > 10
    normalized_uri(path.gsub(/\w+$/,''))
  else
    normalized_uri(path)
  end
end