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



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

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.



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

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



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

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



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

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



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

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



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

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



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

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

#metric_data(stats_hash, base_quantile_hash) ⇒ Object



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

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