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