Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sivagao/4030460 to your computer and use it in GitHub Desktop.
Save sivagao/4030460 to your computer and use it in GitHub Desktop.
clean data, present the data with graph and chart(graphviz,scruffy) #practical ruby for system administrator
# attempting to present data without thought as to the analysis often gives rise to
# presentations that are nothing more than stylish gloss on a stinky foundation.
# 其实这一章没有太多好用的类库介绍,基本是使用。ruby的使用
# 回去可以整理下。
# Listing 9-8. Storing the Array of Logins in a Timestamped File for Later Retrieval
require "fileutils"
require "remote_host"
require "yaml"
FileUtiles.mkdir_p("data")
Dir.chdir("data")
hosts_to_monitor = ["fishbrain.local", "fishwife.local"]
hosts_to_monitor.each do |host| logins = RemoteHost.new(host).last_logins
dump_file = host + Time.now.strftime(".%Y%m%dT%H%M%S.yaml")
File.open(dump_file, "w") { |f| YAML.dump(logins, f) }
end
# Listing 9-9. Parsing Login Fields into an Event, Particularly to Coerce the Date Information
DAY_INDEX, NOW = {}, Time.now
["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"].each_with_index do |day, i|
DAY_INDEX[day] = i + 1
end
def parse_event(login_fields, host)
user, device, source, date_info = login_fields
date_info =~ /^(...) (.){12}/
wday, date = DAY_INDEX[$1], Time.parse($2)
while wday != date.wday or date > NOW
date = Time.local(date.year - 1, date.month, date.day, date.hour, date.min)
end
duration = nil
if date_info =~ /\((\d+\+)?(\d+):(\d+)\)$/
days, hours, mins = $1, $2, $3
duration = mins + hours * 60 + days.to_i * 24 * 60
end
{:user => user, :device => device, :source => source,
:date => date, :duration => duration, :host => host}
end
# Listing 9-10. Assigning Events to a Unique 24-Hour Event Bin
def assign_event(event, bin_hash)
date_key = event[:date].strftime("%Y%m%d")
bin = (bin_hash[date_key] ||= {})
event_key = event.values_at(:user, :device, :source, :date, :host).join(";")
bin[event_key] = event
end
#Listing 9-11. The Final Event Processing Script
require "yaml"
data_dir = (ARGV[0] || "data")
fail "couldn't find directory #{data_dir}" unless File.directory?(data_dir)
Dir.chdir(data_dir)
Dir.mkdir("processed") unless File.directory?("processed")
# code from Listings 9-9 and 9-10 would go here
data_files, periods = DIR["*.yaml"], {}
data_files.each do |file|
host = File.basename(file).split(".").first
logins = YAML.load_file(file)
logins.each do |login|
event = parse_event(login, host)
assign_event(event, periods)
end
end
periods.each do |date_string, events|
event_file = File.join("processed", date_string + ".yaml")
if File.exist?(event_file)
old_events = YAML.load_file(event_file)
events = old_events.merge(events)
end File.open(event_file, "w") { |f| YAML.dump(events, f) }
end
File.delete(data_files)
#Listing 9-12. Summarizing the Total Session Duration Amounts by User and Then by Date
require "yaml"
source_dir = ARGV[0]
fail "couldn't find directory #{source_dir}" unless File.directory?(source_dir)
users = {}
Dir[File.join(source_dir, "*")].each do |file|
date_string = File.basename(file, ".yaml")
events = YAML.load_file(file)
events.each do |key, event|
duration = event[:duration].to_i
next unless duration > 0
user = (users[event[:user]] ||= Hash.new(0))
user[date_string] += duration
end
end
# using Scruffy Charts
# SVG Format
# For rendering a graph, scruffy relies upon the RMagick library (itself a Ruby interface to the ImageMagick library).
require "scruffy"
include Scruffy
graph = Graph.new(:title => "Average Flatulence per Capita")
graph.add(:line, "Cows", [150, 200, 250, 240])
graph.add(:area, "Sheep", [100, 110, 120, 140])
graph.add(:bar, "Man", [50, 65, 78, 66])
graph.render(:as => "PNG", :size => [500, 400], :to => "/tmp/flatulence.png")
require "scruffy"
include Scruffy
# code from Listing 9-12 would go here
exit if users.empty?
all_dates = users.map { |user, dates| dates.keys }.flatten.uniq.sort
graph = Graph.new(:point_markers => all_dates)
graph.title = "Total Login Minutes per User"
users.each do |user, dates|
all_values = all_dates.map { |date| dates[date].to_i }
graph.add(:line, user, all_values)
end
graph.render(:as => "PNG", :width => 1024, :to => "/tmp/user_accounting.png")
# CSS Charts in Rails
# The CSS box model allows for doing pretty basic rectangular drawing, including background, border, and alignment facilities.
# $ script/plugin install http://topfunky.net/svn/plugins/css_graphs
# $ script/generate css_graphs
# edit rhtml templates using the following pattern:
=begin
<h2>Horizontal Bar Chart (Complex)</h2>
<%= complex_bar_graph(["Mail", 58], ["Web", 38], ["FTP", 29], ["P2P", 25], ["Other", 24]) %>
=end
# Graph
# Using graphviz language - dot
# the Ruby wrapper - ruby-graphviz
$ tar -xzf ruby-graphviz_0.6.0.tar.gz
$ cd ruby-graphviz
$ ruby extconf.rb
require "graphviz"
# code from Listing 9-12 modified as discussed (for indexing by host) would go here
exit if users.empty?
graph = Graphviz.new("G")
users.each do |user, hosts|
graph.add_node(user)
hosts.each do |host, usage|
graph.add_node(host)
graph.add_edge(user, host, "weight" => usage)
end
end
graph.output("output" => "png", "file" => "/tmp/user_relationships.png")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment