Skip to content

Instantly share code, notes, and snippets.

@fujiwara
Created March 8, 2013 08:55
Show Gist options
  • Save fujiwara/5115109 to your computer and use it in GitHub Desktop.
Save fujiwara/5115109 to your computer and use it in GitHub Desktop.
use strict;
use Data::Dumper;
package ZabbixAPI {
use Mouse;
use JSON;
use HTTP::Request::Common;
use WWW::Mechanize;
use Data::Dumper;
use Log::Minimal;
has ua => (
is => "rw",
default => sub {
WWW::Mechanize->new(
ssl_opts => {
verify_hostname => 0,
SSL_verify_mode => "SSL_VERIFY_NONE",
},
timeout => 180,
);
}
);
has auth => ( is => "rw", isa => "Str", );
has id => ( is => "rw", isa => "Int", default => 1 );
has url => ( is => "rw", isa => "Str", );
has cookie => ( is => "rw", isa => "Str", );
sub login {
my $self = shift;
my %params = @_;
$self->ua->get( $self->url );
$self->ua->field( name => $params{user} );
$self->ua->field( password => $params{password} );
$self->ua->click("enter");
my $r = {
method => "user.authenticate",
params => \%params,
auth => undef,
};
$self->auth( $self->_request($r) );
debugf "auth: %s", $self->auth;
$self->auth;
}
sub call {
my ($self, $method, $params) = @_;
my $r = {
method => $method,
params => $params,
auth => $self->auth,
};
$self->_request($r);
}
sub _request {
my $self = shift;
my $r = shift;
$r->{id} = $self->{id}++;
$r->{jsonrpc} = "2.0";
my $json = encode_json $r;
my $req = POST $self->url . "api_jsonrpc.php",
"Content-Type" => "application/json-rpc",
"Content-Length" => length($json),
"Content" => $json,
;
my $res = $self->ua->request($req);
decode_json($res->content)->{result};
}
sub get {
my $self = shift;
my $url = shift;
$url = $self->url . $url
unless $url =~ m{^https?://};
my $req = GET $url;
debugf $req->as_string;
$self->ua->request($req);
}
1;
};
use Time::Piece;
use Path::Class qw/ file /;
use Log::Minimal;
use Imager;
use Try::Tiny;
use Config::Pit;
use Getopt::Long;
use Storable;
my ($weekly, $date);
GetOptions (
"weekly" => \$weekly,
"date=s" => \$date,
);
my $host = shift || die "no host";
my $graph = shift || die "no graph name";
my $config = pit_get("zabbix", require => {
"user" => "username on zabbix",
"password" => "password on zabbix",
"url" => "zabbix url",
});
my $api = ZabbixAPI->new( url => $config->{url} );
infof "login to zabbix...";
$api->login(
user => $config->{user},
password => $config->{password},
);
my $graph = $api->call(
"graph.get" => {
search => { name => $graph },
filter => { host => $host },
limit => 5,
}
);
my $period = 86400;
$period *= 7 if $weekly;
my $t = $date
? Time::Piece->strptime($date, "%Y%m%d")->epoch
: time;
my $now = localtime( $t - $period )->strftime("%Y%m%d000000");
my $prev = localtime( $t - $period * 2 )->strftime("%Y%m%d000000");
for my $g ( @$graph ) {
my $gid = $g->{graphid};
my @file;
for my $stime ($now, $prev) {
my $url = "chart2.php?stime=$stime&period=$period&width=500&graphid=$gid";
infof "graphid: %d, stime: %s", $gid, $stime;
my $res = $api->get($url);
my $file = "$gid-$stime.png";
file($file)->openw->print($res->content);
push @file, $file;
}
try {
my $img = image_diff(@file);
my $file = "$gid-diff.png";
$img->write( file => $file );
infof "write to %s", $file;
system("open", $file);
}
catch {
my $e = $_;
warnf "error in processing image: %s", $e;
};
}
sub image_diff {
my ($file1, $file2) = @_;
my $img1 = Imager->new;
$img1->read( file => $file1 )
or die $img1->errstr;
my $img2 = Imager->new;
$img2->read( file => $file2 )
or die $img2->errstr;
my $diff = $img1->difference( other => $img2, mindist => 32 );
my $dpixels = 0;
for my $x ( 0 .. $diff->getwidth - 1 ) {
for my $y ( 0 .. $diff->getheight - 1 ) {
my $c = $diff->getpixel( x => $x, y => $y );
$dpixels++ if ($c->rgba)[3] != 0;
}
}
my $total = $diff->getwidth * $diff->getheight;
infof "diff: %d pixels, %f %%\n", $dpixels, ($dpixels / $total * 100);
$diff;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment