Merge branch 'collectd-4.3' into collectd-4.4
[collectd.git] / contrib / collection3 / bin / graph.cgi
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use lib ('../lib');
6
7 use FindBin ('$RealBin');
8 use Carp (qw(confess cluck));
9 use CGI (':cgi');
10 use RRDs ();
11
12 use Collectd::Graph::Config (qw(gc_read_config gc_get_scalar));
13 use Collectd::Graph::TypeLoader (qw(tl_load_type));
14
15 use Collectd::Graph::Common (qw(sanitize_type get_selected_files
16       epoch_to_rfc1123 flush_files));
17 use Collectd::Graph::Type ();
18
19 our $Debug = param ('debug');
20 our $Begin = param ('begin');
21 our $End = param ('end');
22 our $GraphWidth = param ('width');
23
24 if ($Debug)
25 {
26   print <<HTTP;
27 Content-Type: text/plain
28
29 HTTP
30 }
31
32 gc_read_config ("$RealBin/../etc/collection.conf");
33
34 if ($GraphWidth)
35 {
36   $GraphWidth =~ s/\D//g;
37 }
38
39 if (!$GraphWidth)
40 {
41   $GraphWidth = gc_get_scalar ('GraphWidth', 400);
42 }
43
44 { # Sanitize begin and end times
45   $End ||= 0;
46   $Begin ||= 0;
47
48   if ($End =~ m/\D/)
49   {
50     $End = 0;
51   }
52
53   if (!$Begin || !($Begin =~ m/^-?([1-9][0-9]*)$/))
54   {
55     $Begin = -86400;
56   }
57
58   if ($Begin < 0)
59   {
60     if ($End)
61     {
62       $Begin = $End + $Begin;
63     }
64     else
65     {
66       $Begin = time () + $Begin;
67     }
68   }
69
70   if ($Begin < 0)
71   {
72     $Begin = time () - 86400;
73   }
74
75   if (($End > 0) && ($Begin > $End))
76   {
77     my $temp = $End;
78     $End = $Begin;
79     $Begin = $temp;
80   }
81 }
82
83 my $type = param ('type') or die;
84 my $obj;
85
86 $obj = tl_load_type ($type);
87 if (!$obj)
88 {
89   confess ("tl_load_type ($type) failed");
90 }
91
92 $type = ucfirst (lc ($type));
93 $type =~ s/_([A-Za-z])/\U$1\E/g;
94 $type = sanitize_type ($type);
95
96 my $files = get_selected_files ();
97 if ($Debug)
98 {
99   require Data::Dumper;
100   print STDOUT Data::Dumper->Dump ([$files], ['files']);
101 }
102 for (@$files)
103 {
104   $obj->addFiles ($_);
105 }
106
107 my $expires = time ();
108 # IF (End is `now')
109 #    OR (Begin is before `now' AND End is after `now')
110 if (($End == 0) || (($Begin <= $expires) && ($End >= $expires)))
111 {
112   # 400 == width in pixels
113   my $timespan;
114
115   if ($End == 0)
116   {
117     $timespan = $expires - $Begin;
118   }
119   else
120   {
121     $timespan = $End - $Begin;
122   }
123   $expires += int ($timespan / 400.0);
124 }
125 # IF (End is not `now')
126 #    AND (End is before `now')
127 # ==> Graph will never change again!
128 elsif (($End > 0) && ($End < $expires))
129 {
130   $expires += (366 * 86400);
131 }
132 elsif ($Begin > $expires)
133 {
134   $expires = $Begin;
135 }
136
137 # Send FLUSH command to the daemon if necessary and possible.
138 flush_files ($files,
139     begin => $Begin,
140     end => $End,
141     addr => gc_get_scalar ('UnixSockAddr', undef),
142     interval => gc_get_scalar ('Interval', 10));
143
144 print STDOUT header (-Content_type => 'image/png',
145   -Last_Modified => epoch_to_rfc1123 ($obj->getLastModified ()),
146   -Expires => epoch_to_rfc1123 ($expires));
147
148 if ($Debug)
149 {
150   print "\$expires = $expires;\n";
151 }
152
153 my $args = $obj->getRRDArgs (0);
154
155 if ($Debug)
156 {
157   require Data::Dumper;
158   print STDOUT Data::Dumper->Dump ([$obj], ['obj']);
159   print STDOUT join (",\n", @$args) . "\n";
160   print STDOUT "Last-Modified: " . epoch_to_rfc1123 ($obj->getLastModified ()) . "\n";
161 }
162 else
163 {
164   my @timesel = ();
165
166   if ($End) # $Begin is always true
167   {
168     @timesel = ('-s', $Begin, '-e', $End);
169   }
170   else
171   {
172     @timesel = ('-s', $Begin); # End is implicitely `now'.
173   }
174
175   $| = 1;
176   RRDs::graph ('-', '-a', 'PNG', '--width', $GraphWidth, @timesel, @$args);
177   if (my $err = RRDs::error ())
178   {
179     print STDERR "RRDs::graph failed: $err\n";
180     exit (1);
181   }
182 }
183
184 exit (0);
185
186 # vim: set shiftwidth=2 softtabstop=2 tabstop=8 :