Module: TingYun::TingYunService::UploadService

Included in:
TingYun::TingYunService
Defined in:
lib/ting_yun/ting_yun_service/upload_service.rb

Constant Summary collapse

EMPTY_PARENT =
''.freeze

Instance Method Summary collapse

Instance Method Details

#base64_compressed_jsonObject



17
18
19
# File 'lib/ting_yun/ting_yun_service/upload_service.rb', line 17

def base64_compressed_json
  TingYun::Support::Serialize::Encoders::Base64CompressedJSON
end

#build_metric_data_array(stats_hash, base_quantile_hash) ⇒ Object

The collector wants to recieve metric data in a format that’s different # from how we store it inte -nally, so this method handles the translation. # It also handles translating metric names to IDs using our metric ID cache.



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
# File 'lib/ting_yun/ting_yun_service/upload_service.rb', line 51

def build_metric_data_array(stats_hash, base_quantile_hash)
  action_array = []
  adpex_array = []
  general_array = []
  components_array = []
  errors_array = []
  exception_array = []

  calculate_quantile(base_quantile_hash.hash)

  stats_hash.each do |metric_spec, stats|

    # Omit empty stats as an optimization
    unless stats.is_reset?
      metric_id = metric_id_cache[metric_spec.hash]

      if metric_spec.name.start_with?('WebAction','BackgroundAction')
        action_array << generate_action(metric_spec, stats, metric_id)
      elsif metric_spec.name.start_with?('Apdex')
        adpex_array << TingYun::Metrics::MetricData.new(metric_spec, stats, metric_id)
      elsif metric_spec.name.start_with?('Errors') && metric_spec.scope.empty?
        errors_array << TingYun::Metrics::MetricData.new(metric_spec, stats, metric_id)
      elsif metric_spec.name.start_with?('Exception') && metric_spec.scope.empty?
        exception_array << TingYun::Metrics::MetricData.new(metric_spec, stats, metric_id)
      else
        if metric_spec.scope.empty?
          general_array << TingYun::Metrics::MetricData.new(metric_spec, stats, metric_id)  unless metric_spec.name.start_with?("View","Middleware","Nested","Rack")
        else
          components_array << TingYun::Metrics::MetricData.new(metric_spec, stats, metric_id) unless metric_spec.name.start_with?("Nested")
        end
      end

    end
  end

  [action_array, adpex_array, general_array, components_array, errors_array,exception_array]
end

#calculate_quantile(base) ⇒ Object



98
99
100
101
102
103
104
105
106
107
# File 'lib/ting_yun/ting_yun_service/upload_service.rb', line 98

def calculate_quantile(base)
  if TingYun::Support::QuantileP2.support?
    quantile = TingYun::Agent.config[:'nbs.quantile']
    base.each do |action_name, base_list|
      qm = TingYun::Support::QuantileP2.new(JSON.parse(quantile).map{|i| i.to_f/100})
      base_list.each{ |l| qm.add(l) }
      self.quantile_cache[action_name] = qm.markers
    end
  end
end

#compressed_jsonObject



13
14
15
# File 'lib/ting_yun/ting_yun_service/upload_service.rb', line 13

def compressed_json
  TingYun::Support::Serialize::Encoders::CompressedJSON
end

#fill_metric_id_cache(pairs_of_specs_and_ids) ⇒ Object

takes an array of arrays of spec and id, adds it into the metric cache so we can save the collector some work by sending integers instead of strings the next time around



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/ting_yun/ting_yun_service/upload_service.rb', line 113

def fill_metric_id_cache(pairs_of_specs_and_ids)
  pairs_of_specs_and_ids.each do |_, value|
    if value.is_a? Array
      value.each do |array|
        if array.is_a? Array
          metric_id_cache[array[0]['name'].hash ^ (array[0]['parent']||EMPTY_PARENT).hash] = array[1]
        end
      end
    end
  end
rescue => e
  # If we've gotten this far, we don't want this error to propagate and
  # make this post appear to have been non-successful, which would trigger
  # re-aggregation of the same metric data into the next post, so just log
  TingYun::Agent.logger.error("Failed to fill metric ID cache from response, error details follow ", e)
end

#generate_action(metric_spec, stats, metric_id) ⇒ Object



89
90
91
92
93
94
95
96
# File 'lib/ting_yun/ting_yun_service/upload_service.rb', line 89

def generate_action(metric_spec, stats, metric_id)
  if !TingYun::Support::QuantileP2.support? || metric_spec.name.start_with?('BackgroundAction')
    TingYun::Metrics::MetricData.new(metric_spec, stats, metric_id)
  else
    quantile = self.quantile_cache[metric_spec.full_name] || []
    TingYun::Metrics::MetricData.new(metric_spec, stats, metric_id, quantile)
  end
end

#jsonObject



21
22
23
# File 'lib/ting_yun/ting_yun_service/upload_service.rb', line 21

def json
  TingYun::Support::Serialize::Encoders::Json
end

#metric_data(stats_hash, base_quantile_hash) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/ting_yun/ting_yun_service/upload_service.rb', line 25

def metric_data(stats_hash, base_quantile_hash)
  action_array, adpex_array, general_array, components_array, errors_array,exception_array = build_metric_data_array(stats_hash, base_quantile_hash)

  upload_data = {
      :type => 'perfMetrics',
      :timeFrom => stats_hash.started_at.to_i,
      :timeTo => stats_hash.harvested_at.to_i || Time.now.to_i,
      :interval =>  TingYun::Agent.config[:data_report_period],
      :actions => action_array,
      :apdex => adpex_array,
      :components => components_array,
      :general => general_array,
      :errors  => errors_array,
      :exceptions  => exception_array
  }
  upload_data.merge!(:config => {"nbs.quantile" => TingYun::Agent.config[:'nbs.quantile']}) if TingYun::Agent.config[:'nbs.quantile']
  result = invoke_remote(:upload, [upload_data])
  self.quantile_cache = {}
  fill_metric_id_cache(result)
  result
end