class Dropsonde::Metrics
Public Class Methods
new()
click to toggle source
# File lib/dropsonde/metrics.rb, line 6 def initialize if Dropsonde.settings[:enable] Dropsonde.settings[:disable] ||= [] disable = Dropsonde::Metrics.plugins.keys - Dropsonde.settings[:enable].map(&:to_sym) Dropsonde.settings[:disable].concat disable end Dropsonde::Metrics.disregard_plugins(*Dropsonde.settings[:disable]) Dropsonde::Metrics.initialize_plugins end
Public Instance Methods
check_for_duplicates(schema)
click to toggle source
# File lib/dropsonde/metrics.rb, line 153 def check_for_duplicates(schema) keys = schema.map {|col| col[:name] } dupes = keys.select{ |e| keys.count(e) > 1 }.uniq raise "The schema defines duplicate keys: #{dupes}" unless dupes.empty? end
example()
click to toggle source
# File lib/dropsonde/metrics.rb, line 101 def example require 'ipaddr' results = skeleton_report results[:message_id] = generate_guid results[:timestamp] = rand((Time.now - 60 * 60 * 24 * 365)..Time.now).utc results[:ip] = IPAddr.new(rand(2**32), Socket::AF_INET) results.delete(:'self-service-analytics') Dropsonde::Metrics.plugins.each do |name, plugin| sanity_check_data(plugin, plugin.example).each do |row| results.merge!(row) end end results end
generate_guid()
click to toggle source
# File lib/dropsonde/metrics.rb, line 212 def generate_guid "%s-%s-%s-%s-%s" % [ (0..8).to_a.map{|a| rand(16).to_s(16)}.join, (0..4).to_a.map{|a| rand(16).to_s(16)}.join, (0..4).to_a.map{|a| rand(16).to_s(16)}.join, (0..4).to_a.map{|a| rand(16).to_s(16)}.join, (0..12).to_a.map{|a| rand(16).to_s(16)}.join ] end
list()
click to toggle source
# File lib/dropsonde/metrics.rb, line 28 def list str = " Loaded telemetry plugins\n" str << " ===============================\n\n" Dropsonde::Metrics.plugins.each do |name, plugin| str << name.to_s str << "\n--------\n" str << plugin.description.strip str << "\n\n" end if Dropsonde.settings[:disable] str << "Disabled plugins:\n" str << " #{Dropsonde.settings[:disable].join(', ')}" end str end
preview()
click to toggle source
# File lib/dropsonde/metrics.rb, line 53 def preview str = " Puppet Telemetry Report Preview\n" str << " ===============================\n\n" Dropsonde::Metrics.plugins.each do |name, plugin| schema = plugin.schema plugin.setup if plugin.respond_to? :setup data = sanity_check_data(plugin, plugin.run) plugin.cleanup if plugin.respond_to? :cleanup str << plugin.name+"\n" str << "-------------------------------\n" str << plugin.description data.each do |row| key = row.keys.first values = row.values.flatten desc = schema.find {|item| item[:name].to_sym == key.to_sym}[:description] str << "- #{key}: #{desc}\n" values.each do |item| str << " #{item}\n" end end str << "\n\n" end str << "Site ID:\n" str << siteid str end
report()
click to toggle source
# File lib/dropsonde/metrics.rb, line 83 def report snapshots = {} Dropsonde::Metrics.plugins.each do |name, plugin| plugin.setup sanity_check_data(plugin, plugin.run).each do |row| snapshots[row.keys.first] = { 'value' => row.values.first, 'timestamp' => Time.now.iso8601, } end plugin.cleanup end results = skeleton_report results[:'self-service-analytics'][:snapshots] = snapshots results end
sanity_check_data(plugin, data)
click to toggle source
We accept both the plugin and data gathered from the plugin so that we can sanitize both data and example data
# File lib/dropsonde/metrics.rb, line 120 def sanity_check_data(plugin, data) # This allows plugin authors to easily skip metrics with no results return [] if data.nil? keys_data = data.map {|item| item.keys }.flatten.map(&:to_s) keys_schema = plugin.schema.map {|item| item[:name] } disallowed = (keys_data - keys_schema) raise "ERROR: The #{plugin.name} plugin exported the following keys not documented in the schema: #{disallowed}" unless disallowed.empty? data end
sanity_check_schema(plugin)
click to toggle source
# File lib/dropsonde/metrics.rb, line 134 def sanity_check_schema(plugin) schema = plugin.schema if schema.class != Array or schema.find {|item| item.class != Hash} raise "The #{plugin.name} plugin schema is not an array of hashes" end error = '' [:name, :type, :description].each do |field| count = schema.reject {|item| item[field] }.count next if count == 0 error << "The #{plugin.name} plugin schema has #{count} missing #{field}s\n" end raise error unless error.empty? schema end
schema()
click to toggle source
# File lib/dropsonde/metrics.rb, line 44 def schema schema = skeleton_schema Dropsonde::Metrics.plugins.each do |name, plugin| schema.concat(sanity_check_schema(plugin)) end check_for_duplicates(schema) schema end
siteid()
click to toggle source
# File lib/dropsonde/metrics.rb, line 17 def siteid return @siteid if @siteid sha2 = Digest::SHA512.new sha2.update Puppet.settings[:certname] sha2.update Puppet.settings[:cacert] sha2.update Dropsonde.settings[:seed] if Dropsonde.settings[:seed] @siteid = sha2.hexdigest @siteid end
skeleton_report()
click to toggle source
# File lib/dropsonde/metrics.rb, line 201 def skeleton_report { "product": "popularity-module", "version": "1.0.0", "site_id": siteid, "self-service-analytics": { "snapshots": { } } } end
skeleton_schema()
click to toggle source
# File lib/dropsonde/metrics.rb, line 160 def skeleton_schema [ { "description": "An ID that's unique for each checkin to Dujour.", "mode": "NULLABLE", "name": "message_id", "type": "STRING" }, { "description": "A unique identifier for a site, derived as a hash of the CA certificate and optional seed.", "mode": "NULLABLE", "name": "site_id", "type": "BYTES" }, { "description": "The name of the product.", "mode": "NULLABLE", "name": "product", "type": "STRING" }, { "description": "Version of the project.", "mode": "NULLABLE", "name": "version", "type": "STRING" }, { "description": "Time the checkin to Dujour occurred.", "mode": "NULLABLE", "name": "timestamp", "type": "TIMESTAMP" }, { "description": "IP Address of node checking in to Dujour.", "mode": "NULLABLE", "name": "ip", "type": "STRING" } ] end