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