Class: D13n::Metric::Stream

Inherits:
Object
  • Object
show all
Defined in:
lib/d13n/metric/stream.rb,
lib/d13n/metric/stream/traced_span_stack.rb,
lib/d13n/metric/stream/span_tracer_helpers.rb,
lib/d13n/metric/stream/stream_tracer_helpers.rb

Defined Under Namespace

Modules: SpanTracerHelpers, StreamTracerHelpers Classes: StackFrame, TracedSpanStack, UnexpectedStackError

Constant Summary collapse

SINATRA_PREFIX =
'controller.sinatra'.freeze
MIDDLEWARE_PREFIX =
'controller.middleware'.freeze
WEB_TRANSACTION_CATEGORIES =
[:controller, :uri, :rack, :sinatra, :websocket].freeze
APDEX_S =
'S'.freeze
APDEX_T =
'T'.freeze
APDEX_F =
'F'.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(category, options) ⇒ Stream

Returns a new instance of Stream.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/d13n/metric/stream.rb', line 108

def initialize(category, options)
  @frame_stack = []

  @category = category
  @started_at = Time.now.to_f

  @default_name = options[:stream_name]
  
  @apdex_started_at = options[:apdex_started_at] || @started_at

  @ignore_apdex = false
  @ignore_this_stream = false

  @uuid = nil
  @exceptions = {}
  @request_content_length = 0
  @response_content_type = nil
  @response_content_length = 0
end

Instance Attribute Details

#frame_stackObject

Returns the value of attribute frame_stack.



20
21
22
# File 'lib/d13n/metric/stream.rb', line 20

def frame_stack
  @frame_stack
end

#http_response_codeObject

Returns the value of attribute http_response_code.



20
21
22
# File 'lib/d13n/metric/stream.rb', line 20

def http_response_code
  @http_response_code
end

#request_content_lengthObject

Returns the value of attribute request_content_length.



20
21
22
# File 'lib/d13n/metric/stream.rb', line 20

def request_content_length
  @request_content_length
end

#response_content_lengthObject

Returns the value of attribute response_content_length.



20
21
22
# File 'lib/d13n/metric/stream.rb', line 20

def response_content_length
  @response_content_length
end

#response_content_typeObject

Returns the value of attribute response_content_type.



20
21
22
# File 'lib/d13n/metric/stream.rb', line 20

def response_content_type
  @response_content_type
end

#started_atObject

Returns the value of attribute started_at.



19
20
21
# File 'lib/d13n/metric/stream.rb', line 19

def started_at
  @started_at
end

#stateObject

Returns the value of attribute state.



19
20
21
# File 'lib/d13n/metric/stream.rb', line 19

def state
  @state
end

#uuidObject

Returns the value of attribute uuid.



19
20
21
# File 'lib/d13n/metric/stream.rb', line 19

def uuid
  @uuid
end

Class Method Details

.apdex_bucket(duration, failed, apdex_t) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/d13n/metric/stream.rb', line 90

def self.apdex_bucket(duration, failed, apdex_t)

  case
  when failed
    :apdex_f
  when duration <= apdex_t
    :apdex_s
  when duration <= (4 * apdex_t)
    :apdex_t
  else
    :apdex_f
  end
end

.nested_stream_name(name) ⇒ Object



104
105
106
# File 'lib/d13n/metric/stream.rb', line 104

def self.nested_stream_name(name)
  name
end

.notice_error(exception, options = {}) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/d13n/metric/stream.rb', line 82

def self.notice_error(exception, options={})
  state = D13n::Metric::StreamState.st_get
  stream = state.current_stream
  if stream
    stream.notice_error(exception, options)
  end
end

.set_default_stream_name(name, category = nil, node_name = nil) ⇒ Object



29
30
31
32
33
34
# File 'lib/d13n/metric/stream.rb', line 29

def self.set_default_stream_name(name, category = nil, node_name = nil)
  stream = st_current
  name = stream.make_stream_name(name, category)
  stream.name_last_frame(node_name || name)
  stream.set_default_stream_name(name, category)
end

.st_currentObject



25
26
27
# File 'lib/d13n/metric/stream.rb', line 25

def self.st_current
  StreamState.st_get.current_stream
end

.start(state, category, options) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/d13n/metric/stream.rb', line 36

def self.start(state, category, options)
  category ||= :controller
  stream = state.current_stream

  if stream 
    stream.create_nested_stream(state, category, options)
  else
    stream = start_new_stream(state, category, options)
  end
  stream
rescue => e
  D13n.logger.error("Exception during Stream.start", e)
  nil
end

.start_new_stream(state, category, options) ⇒ Object



51
52
53
54
55
56
57
# File 'lib/d13n/metric/stream.rb', line 51

def self.start_new_stream(state, category, options)
  stream = new(category, options)
  state.reset(stream)
  stream.state = state
  stream.start(state)
  stream
end

.stop(state, ended_time = Time.now.to_f) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/d13n/metric/stream.rb', line 59

def self.stop(state, ended_time=Time.now.to_f)
  stream = state.current_stream
  if stream.nil?
    D13n.logger.error("Failed during Stream.stop because there is no current stream")
    return
  end

  nested_frame = stream.frame_stack.pop
  if stream.frame_stack.empty?
    stream.stop(state, ended_time, nested_frame)
    state.reset
  else
    nested_name = nested_stream_name(nested_frame.name)
    begin
      D13n::Metric::Stream::SpanTracerHelpers.trace_footer(state, nested_frame.start_time.to_f, nested_name, nested_frame, {})
    rescue => e
      D13n.logger.debug "Error in trace_footer #{e}"
    end
  end

  #:stream_stopped
end

Instance Method Details

#apdex_bucket(duration, current_apdex_t) ⇒ Object



230
231
232
# File 'lib/d13n/metric/stream.rb', line 230

def apdex_bucket(duration, current_apdex_t)
  self.class.apdex_bucket(duration, had_exception_affecting_apdex?, current_apdex_t)
end

#apdex_tObject



153
154
155
# File 'lib/d13n/metric/stream.rb', line 153

def apdex_t
  stream_specific_apdex_t || D13n.config[:'metric.app.http.in.apdex_t']
end

#append_apdex_perf_zone(duration, metric_data) ⇒ Object



234
235
236
237
238
239
240
241
242
243
244
245
246
247
# File 'lib/d13n/metric/stream.rb', line 234

def append_apdex_perf_zone(duration, metric_data)
  bucket = apdex_bucket(duration, apdex_t)

  return unless bucket
 
  bucket_str = case bucket
  when :apdex_s then APDEX_S
  when :apdex_t then APDEX_T
  when :apdex_f then APDEX_F
  else nil
  end

  metric_data[:apdex_perf_zone] = bucket_str if bucket_str
end

#append_web_response(http_response_code, response_content_type, response_content_length, request_content_length, metric_data) ⇒ Object



249
250
251
252
253
254
255
256
# File 'lib/d13n/metric/stream.rb', line 249

def append_web_response(http_response_code,response_content_type,response_content_length,request_content_length,metric_data)
  return if http_response_code.nil?

  metric_data[:http_response_code] = http_response_code
  metric_data[:http_response_content_type] = response_content_type
  metric_data[:http_response_content_length] = response_content_length
  metric_data[:http_request_content_length] = request_content_length
end

#collect_metric_data(state, metric_data, ended_time = Time.now.to_f) ⇒ Object



166
167
168
169
170
171
172
# File 'lib/d13n/metric/stream.rb', line 166

def collect_metric_data(state, metric_data, ended_time = Time.now.to_f)
  total_duration = ended_time - @apdex_started_at
  action_duration = ended_time - @started_at.to_f

  # collect_apdex_metric(total_duration, action_duration, apdex_t)
  generate_metric_data(state, metric_data, @started_at, ended_time)
end

#collect_metrics(state, metric_data) ⇒ Object



162
163
164
# File 'lib/d13n/metric/stream.rb', line 162

def collect_metrics(state, metric_data)
  StreamTracerHelpers.collect_metrics(state, metric_data)
end

#commit!(state, exclusive, ended_time) ⇒ Object



147
148
149
150
151
# File 'lib/d13n/metric/stream.rb', line 147

def commit!(state, exclusive, ended_time)
  @metric_data = {:exclusive => exclusive}
  collect_metric_data(state, @metric_data, ended_time)
  collect_metrics(state, @metric_data)
end

#create_nested_stream(state, category, options) ⇒ Object



280
281
282
283
284
285
286
287
# File 'lib/d13n/metric/stream.rb', line 280

def create_nested_stream(state, category, options)
  @has_children = true

  @frame_stack.push D13n::Metric::Stream::SpanTracerHelpers.trace_header(state, Time.now.to_f)
  name_last_frame(options[:stream_name])

  set_default_stream_name(options[:stream_name], category)
end

#default_metric_dataObject

def collect_apdex_metric(total_duration, action_duration, current_apdex_t)

apdex_bucket_global = apdex_bucket(total_duration, current_apdex_t)
apdex_bucket_stream = apdex_bucket(action_duration, current_apdex_t)

end



179
180
181
182
183
184
185
186
187
188
189
# File 'lib/d13n/metric/stream.rb', line 179

def default_metric_data
  metric_data = {
    :name => @frozen_name || @default_name,
    :uuid => uuid,
    :error => false
  }

  generate_error_data(metric_data)
  metric_data[:referring_stream_id] = @state.referring_stream_id if @state.referring_stream_id
  metric_data
end

#generate_default_metric_data(state, started_at, ended_time, metric_data) ⇒ Object



200
201
202
203
204
205
206
207
208
209
210
# File 'lib/d13n/metric/stream.rb', line 200

def generate_default_metric_data(state, started_at, ended_time, metric_data)
  duration = ended_time - started_at
  
  metric_data.merge!(default_metric_data)
  metric_data.merge!({
    :type => :request,
    :started_at => started_at,
    :duration => duration,
  })
  metric_data
end

#generate_error_data(metric_data) ⇒ Object



191
192
193
194
195
196
197
198
# File 'lib/d13n/metric/stream.rb', line 191

def generate_error_data(metric_data)
  if had_error?
    metric_data.merge!({
     :error => true,
     :errors => @exceptions 
    })
  end
end

#generate_metric_data(state, metric_data, started_at, ended_time) ⇒ Object



212
213
214
215
216
217
218
219
# File 'lib/d13n/metric/stream.rb', line 212

def generate_metric_data(state, metric_data, started_at, ended_time)
  duration = ended_time - started_at
  metric_data ||= {}
  generate_default_metric_data(state, started_at, ended_time, metric_data)
  append_apdex_perf_zone(duration, metric_data)
  append_web_response(@http_response_code, @response_content_type, @response_content_length, @request_content_length, metric_data) if recording_web_transaction?
  metric_data
end

#get_idObject



311
312
313
# File 'lib/d13n/metric/stream.rb', line 311

def get_id
  uuid
end

#had_error?Boolean

Returns:

  • (Boolean)


221
222
223
# File 'lib/d13n/metric/stream.rb', line 221

def had_error?
  !@exceptions.empty?
end

#had_exception_affecting_apdex?Boolean

Returns:

  • (Boolean)


225
226
227
228
# File 'lib/d13n/metric/stream.rb', line 225

def had_exception_affecting_apdex?
  # all exceptions are affecting
  had_error?  
end

#make_stream_name(name, category = nil) ⇒ Object



258
259
260
261
# File 'lib/d13n/metric/stream.rb', line 258

def make_stream_name(name, category=nil)
  namer = Instrumentation::ControllerInstrumentation::StreamNamer
  "#{namer.prefix_for_category(self, category)}.#{name}"
end

#name_frozen?Boolean

Returns:

  • (Boolean)


295
296
297
# File 'lib/d13n/metric/stream.rb', line 295

def name_frozen?
  @frozen_name ? true : false
end

#name_last_frame(name) ⇒ Object



268
269
270
# File 'lib/d13n/metric/stream.rb', line 268

def name_last_frame(name)
  @frame_stack.last.name = name
end

#notice_error(exception, options = {}) ⇒ Object



272
273
274
275
276
277
278
# File 'lib/d13n/metric/stream.rb', line 272

def notice_error(exception, options={})
  if @exceptions[exception]
    @exceptions[exception].merge! options
  else
    @exceptions[exception] = options
  end
end

#recording_web_transaction?Boolean

Returns:

  • (Boolean)


303
304
305
# File 'lib/d13n/metric/stream.rb', line 303

def recording_web_transaction?
  web_category?(@category)
end

#set_default_stream_name(name, category) ⇒ Object



263
264
265
266
# File 'lib/d13n/metric/stream.rb', line 263

def set_default_stream_name(name, category)
  @default_name = name
  @category = category if category
end

#start(state) ⇒ Object



128
129
130
131
# File 'lib/d13n/metric/stream.rb', line 128

def start(state)
  @frame_stack.push D13n::Metric::Stream::SpanTracerHelpers.trace_header(state, @started_at)
  name_last_frame @default_name
end

#stop(state, ended_time, outermost_frame) ⇒ Object



133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/d13n/metric/stream.rb', line 133

def stop(state, ended_time, outermost_frame)
  trace_options = {}
  if @has_children
    name = self.class.nested_stream_name(outermost_frame.name)
  else
    name = @frozen_name
  end

  D13n::Metric::Stream::SpanTracerHelpers.trace_footer(state, @started_at.to_f, name, outermost_frame, trace_options, ended_time.to_f)
  duration = ended_time - @started_at
  exclusive = duration - outermost_frame.children_time
  commit!(state, exclusive, ended_time) unless @ignore_this_stream
end

#stream_specific_apdex_tObject



157
158
159
160
# File 'lib/d13n/metric/stream.rb', line 157

def stream_specific_apdex_t
  key = "metric.app.http.in.apdex_t.#{@frozen_name}".to_sym
  D13n.config[key]
end

#web_category?(category) ⇒ Boolean

Returns:

  • (Boolean)


307
308
309
# File 'lib/d13n/metric/stream.rb', line 307

def web_category?(category)
  WEB_TRANSACTION_CATEGORIES.include?(category)
end