#!/usr/bin/perl -w
use strict;
use warnings;
use GD;
use GD::Graph::hbars;
use POSIX qw(strftime);

# License: GPL v2 (and not above)

# CONFIG Options
my $png_path = '/var/www/';

# $app /var/log/nagios/archives/nagios-*.log /var/log/nagios/nagios.log

my (%warnings, %criticals, %outages);
my $cutoff   = (time - 2_592_000); # now (epoch) minus 30 days (in seconds)
my $runtime  = localtime;
my $date_fmt = strftime("%Y-%m-%d", localtime);

my %config = (
  outages => {
    x_label => 'Hosts',
    y_label => 'Outages (30 days)',
    title   => "Outages per Host (30 day range) - Generated: $runtime",
    pngname => 'outages',
  },
  warnings => {
    x_label => 'Services',
    y_label => 'Service Warnings',
    title   => "Warnings Per Service (30 day range) - Generated: $runtime",
    pngname => 'warnings',
  },
  criticals => {
    x_label => 'Services',
    y_label => 'Service Criticals',
    title   => "Criticals Per Service (30 day range) - Generated: $runtime",
    pngname => 'criticals',
  },
);

while(<>) {
  if (m/\[(\d+)\] SERVICE ALERT: \S+?;(.+?);WARNING;HARD/) {
    $warnings{$2}++ unless ($1 < $cutoff);
  }
  if (m/\[(\d+)\] SERVICE ALERT: \S+?;(.+?);CRITICAL;HARD/) {
    $criticals{$2}++ unless ($1 < $cutoff);
  }
  if (m/\[(\d+)\] HOST ALERT: (\S+);DOWN;HARD/) {
    $outages{$2}++ unless ($1 < $cutoff);
  }
}

# TODO this is not ideal. Convert to hash of hashes
foreach my $type qw(outages warnings criticals) {
  graph($type, \%warnings,  \%config ) if $type eq 'warnings';
  graph($type, \%criticals, \%config ) if $type eq 'criticals';
  graph($type, \%outages,   \%config ) if $type eq 'outages';
}

#=======================#

sub graph {
  my $type              = shift;
  my $datapoints        = shift;
  my $config            = shift;

  my $png_filename      = $config->{$type}{pngname} . ".png";
  my $full_png_filename = $config->{$type}{pngname} ."_". $date_fmt . ".png";

  my $graph = GD::Graph::hbars->new(1000, 1000);
  my @order = sort { $datapoints->{$b} <=> $datapoints->{$a} or $a cmp $b } keys %$datapoints;
  my @data  = ( [ @order ], [ @$datapoints{ @order } ], );

  $graph->set(
    x_label      => $config->{$type}{x_label},
    y_label      => $config->{$type}{y_label},
    title        => $config->{$type}{title},
    dclrs        => [ qw( dgreen ) ],
    bar_spacing  => 2,
    cycle_clrs   => 1,
    x_all_ticks  => 1,
    show_values  => 1,
  ) or die $graph->error;

  $graph->set_x_axis_font(['verdana', 'arial', gdMediumBoldFont], 14);
  $graph->set_y_axis_font(['verdana', 'arial', gdMediumBoldFont], 14);
  $graph->set_values_font(['verdana', 'arial', gdMediumBoldFont], 14);

  my $gd = $graph->plot(\@data) or die $graph->error;

  # Create the graphs
  # We make two copies so you can always see the newest version with a
  # static file name. We also keep an old version for historical reasons

  foreach my $png_file ($png_filename, $full_png_filename) {
    open(IMG, '>', "$png_path/$png_file")
      || die "Failed to create '$png_path/$png_file': $!";
    binmode IMG;
    print IMG $gd->png;
    close IMG;
  }
}

