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