Module: TingYun::Agent::CrossAppTracing

Extended by:
Instrumentation::Support::ExternalError, Instrumentation::Support::ExternalHelper
Defined in:
lib/ting_yun/agent/cross_app/cross_app_tracing.rb

Defined Under Namespace

Classes: Error

Constant Summary collapse

TY_ID_HEADER =

The cross app id header for “outgoing” calls

'X-Tingyun'.freeze
TY_DATA_HEADER =
'X-Tingyun-Data'.freeze

Class Method Summary collapse

Methods included from Instrumentation::Support::ExternalError

capture_exception, handle_error, set_attributes

Methods included from Instrumentation::Support::ExternalHelper

create_tingyun_id, create_tingyun_idV2, metrics_for_message, tingyun_externel_guid

Class Method Details

.add_transaction_trace_info(request, response, cross_app, tx_data) ⇒ Object



127
128
129
130
131
132
133
134
# File 'lib/ting_yun/agent/cross_app/cross_app_tracing.rb', line 127

def add_transaction_trace_info(request, response, cross_app, tx_data)
  state = TingYun::Agent::TransactionState.tl_get
  ::TingYun::Agent::Collector::TransactionSampler.add_node_info(:uri => TingYun::Agent::HTTPClients::URIUtil.filter_uri(request.uri))
  if cross_app
    state.add_current_node_paramsV3(:txData=> TingYun::Support::Serialize::JSONWrapper.dump(tx_data))
    ::TingYun::Agent::Collector::TransactionSampler.tl_builder.set_txId_and_txData(state.client_transaction_id || state.request_guid, tx_data)
  end
end

.cross_app_enabled?Boolean

Returns:

  • (Boolean)


158
159
160
161
162
# File 'lib/ting_yun/agent/cross_app/cross_app_tracing.rb', line 158

def cross_app_enabled?
  TingYun::Agent.config[:idSecret] && TingYun::Agent.config[:idSecret].size > 0 &&
      TingYun::Agent.config[:'action_tracer.enabled'] &&
      TingYun::Agent.config[:'nbs.transaction_tracer.enabled']
end

.finish_trace(state, t0, node, request, response) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/ting_yun/agent/cross_app/cross_app_tracing.rb', line 92

def finish_trace(state, t0, node, request, response)

  t1 = Time.now.to_f
  duration = (t1- t0) * 1000
  state.timings.external_duration = duration

  begin
    if request
      cross_app = response_is_cross_app?(response)
      tx_data = TingYun::Support::Serialize::JSONWrapper.load(get_ty_data_header(response).gsub("'",'"')) || {}
      # net_block_duration = tx_data["time"]? duration - tx_data["time"]["duration"]- tx_data["time"]["qu"] : duration
      # net_block_duration = duration if net_block_duration < 0
      # ::TingYun::Agent.instance.stats_engine.record_scoped_and_unscoped_metrics(state, node_name, metrics, duration)
      # if cross_app
      #   _duration =  tx_data["time"]["duration"] + tx_data["time"]["qu"] + 0.1
      #   metrics_for_cross_app(request, response)
      #   # txn = state.current_transaction
      #   # txn.metrics.record_scoped(metrics_cross_app.pop, duration, _duration)
      #   # txn.metrics.record_unscoped(metrics_cross_app, _duration)
      # end
      if node
        node.name ="#{request.from}/#{request.uri.to_s}"
        add_transaction_trace_info(request, response, cross_app, tx_data)
      end
    end
  rescue => err
    TingYun::Agent.logger.error "Uncaught exception while finishing an HTTP request trace", err
  ensure
    if node
      stack = state.traced_method_stack
      stack.pop_frame(state, node, node.name, t1)
    end
  end
end

.finish_traceV2(state, t0, node, request, response) ⇒ Object



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
# File 'lib/ting_yun/agent/cross_app/cross_app_tracing.rb', line 53

def finish_traceV2(state, t0, node, request, response)

  t1 = Time.now.to_f
  duration = (t1- t0) * 1000
  state.timings.external_duration = duration

  begin
    if request
      cross_app = response_is_cross_app?(response)

      metrics = metrics_for(request)
      node_name = metrics.pop
      tx_data = TingYun::Support::Serialize::JSONWrapper.load(get_ty_data_header(response).gsub("'",'"')) || {}
      # net_block_duration = tx_data["time"]? duration - tx_data["time"]["duration"]- tx_data["time"]["qu"] : duration
      # net_block_duration = duration if net_block_duration < 0
      # ::TingYun::Agent.instance.stats_engine.record_scoped_and_unscoped_metrics(state, node_name, metrics, duration)
      if cross_app
        _duration =  tx_data["time"]["duration"] + tx_data["time"]["qu"] + 0.1
        metrics_cross_app = metrics_for_cross_app(request, response)
        txn = state.current_transaction
        txn.metrics.record_scoped(metrics_cross_app.pop, duration, _duration)
        txn.metrics.record_unscoped(metrics_cross_app, _duration)
      end

      if node
        node.name = node_name
        add_transaction_trace_info(request, response, cross_app, tx_data)
      end
    end
  rescue => err
    TingYun::Agent.logger.error "Uncaught exception while finishing an HTTP request trace", err
  ensure
    if node
      stack = state.traced_method_stack
      stack.pop_frame(state, node, node_name, t1)
    end
  end
end

.get_ty_data_header(response) ⇒ Object



181
182
183
184
185
186
187
# File 'lib/ting_yun/agent/cross_app/cross_app_tracing.rb', line 181

def get_ty_data_header(response)
  if defined?(::HTTP) && defined?(::HTTP::Message) && response.class == ::HTTP::Message
    response.header[TY_DATA_HEADER].first.to_s rescue ""
  else
    response[TY_DATA_HEADER].to_s rescue ""
  end
end

.inject_request_headers(state, request) ⇒ Object

Inject the X-Process header into the outgoing request.



165
166
167
# File 'lib/ting_yun/agent/cross_app/cross_app_tracing.rb', line 165

def inject_request_headers(state, request)
  request[TY_ID_HEADER] = create_tingyun_id(nil,nil,request)
end

.metrics_for(request) ⇒ Object



145
146
147
148
149
150
151
152
153
154
# File 'lib/ting_yun/agent/cross_app/cross_app_tracing.rb', line 145

def metrics_for(request)
  metrics = [ "External/NULL/ALL" ]
  if TingYun::Agent::Transaction.recording_web_transaction?
    metrics << "External/NULL/AllWeb"
  else
    metrics << "External/NULL/AllBackground"
  end
  metrics << "External/#{request.uri.to_s.gsub(/\/\z/,'')}/#{request.from}"
  return metrics
end

.metrics_for_cross_app(request, response) ⇒ Object



137
138
139
140
141
142
143
# File 'lib/ting_yun/agent/cross_app/cross_app_tracing.rb', line 137

def metrics_for_cross_app(request, response)
  my_data =  TingYun::Support::Serialize::JSONWrapper.load get_ty_data_header(response).gsub("'",'"')
  metrics = ["ExternalTransaction/NULL/#{my_data["id"]}",
             "ExternalTransaction/http/#{my_data["id"]}"]
  metrics << "ExternalTransaction/#{request.uri.to_s.gsub(/\/\z/,'')}/#{my_data["id"]}/#{my_data["action"].to_s
                                                                                             .gsub(/\/\z/,'')}"
end

.response_is_cross_app?(response) ⇒ Boolean

Returns true if Cross Application Tracing is enabled, and the given response has the appropriate headers.

Returns:

  • (Boolean)


171
172
173
174
175
176
177
# File 'lib/ting_yun/agent/cross_app/cross_app_tracing.rb', line 171

def response_is_cross_app?( response )
  return false unless response
  return false unless cross_app_enabled?
  return false if get_ty_data_header(response).empty?

  return true
end

.start_trace(state, t0, request) ⇒ Object



46
47
48
49
50
51
# File 'lib/ting_yun/agent/cross_app/cross_app_tracing.rb', line 46

def start_trace(state, t0, request)
  stack = state.traced_method_stack
  node = stack.push_frame(state, :http_request, t0)
  inject_request_headers(state, request) if cross_app_enabled?
  return node
end

.tl_trace_http_request(request) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/ting_yun/agent/cross_app/cross_app_tracing.rb', line 31

def tl_trace_http_request(request)
  state = TingYun::Agent::TransactionState.tl_get
  return yield unless state.execution_traced?
  return yield unless state.current_transaction #如果还没有创建Transaction,就发生跨应用,就直接先跳过跟踪。
  t0 = Time.now.to_f
  begin
    node = start_trace(state, t0, request)
    response = yield
    capture_exception(response, request)
  ensure
    finish_trace(state, t0, node, request, response)
  end
  return response
end