File: stripchart

package info (click to toggle)
boinc 7.14.2+dfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 111,132 kB
  • sloc: cpp: 163,589; php: 113,173; ansic: 49,284; pascal: 35,620; xml: 17,864; java: 13,521; python: 6,551; sh: 4,082; perl: 1,843; makefile: 1,796; objc: 1,543; sql: 959; csh: 126; lisp: 47
file content (442 lines) | stat: -rwxr-xr-x 15,681 bytes parent folder | download | duplicates (13)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
#!/usr/bin/perl

# The contents of this file are subject to the Mozilla Public License
# Version 1.0 (the "License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/ 
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
# License for the specific language governing rights and limitations
# under the License. 
# 
# The Original Code is the Berkeley Open Infrastructure for Network Computing. 
# 
# The Initial Developer of the Original Code is the SETI@home project.
# Portions created by the SETI@home project are Copyright (C) 2002
# University of California at Berkeley. All Rights Reserved. 
# 
# Contributor(s):
#

# Stripchart - Version 2.1 by Matt Lebofsky  ( started: November 11, 2002 )
#
# Requires: gnuplot with .gif support (which may require gd)
#           perl 5.0 or later  
#           stripchart.cnf (make sure you set the path the .cnf file below)
#
# Stripchart is a wrapper around gnuplot which takes in time-based
# data from a file and creates a web-friendly image. It is quite
# useful for system diagnostic checking, especially when used with
# stripchart.cgi
#
# You should only need to edit the variables in the section
# "GLOBAL/DEFAULT VARS" below
#
# Type "stripchart -h" for usage
#
# See doc/stripchart.txt for details
#

use Getopt::Std;
use File::Basename;
$|++;

################
# READ IN .cnf
################

# Where is the .cnf file?
$cnfpath = "/etc/stripchart.cnf";

# Read it in:
open (CNFFILE,$cnfpath) or die "cannot open configuration file: $cnfpath\nmake sure this variable is set properly";
while (<CNFFILE>) { eval }
close (CNFFILE);

#############
# SUBS
#############

sub to_unix_time {
  # times should generally be in epoch seconds, but just in case they're not:

  # no colons and no decimal point? must already be in unix time
  if ($_[0] !~ /:/ && $_[0] !~ /\./ ) { return $_[0] }

  # colons = civil time
  if ($_[0] =~ /:/) { 
    (my $year, my $month, my $day, my $hour, my $minute) = split /:/, $_[0];
    $month--;
    return timelocal(0,$minute,$hour,$day,$month,$year)
    }
 
  # must be julian date
  return (($_[0] - 2440587.5) * $daysecs);
 
  }

sub unix_to_civillabel {
  # convert epoch seconds to a pretty date string

  (my $minute, my $hour, my $day, my $month, my $year) =
     (localtime($_[0]))[1,2,3,4,5];
  $month++;
  $year+=1900;
  $year = substr($year,2,2);
  my $label = sprintf("%02d/%02d/%02d %02d:%02d",$month,$day,$year,$hour,$minute);
  return $label
  }

sub time_to_monthlabel {
  # convert epoch seconds to a simple month label (for x axis)

  (my $day, my $month) = (localtime($_[0]))[3,4];
  my $label = $monthabbs[$month] . " $day";
  return $label;
  
  }

sub time_to_hourlabel {
  # convert epoch seconds to a simple hour label (for x axis)

  (my $minute, my $hour) = (localtime($_[0]))[1,2];
  my $label = sprintf("%02d:%02d",$hour,$minute);
  return $label;
 
  } 

#############
# MAIN
#############

# get command line options

if (getopts("f:t:r:i:o:O:l:T:x:y:Y:b:Bd:D:vLc:CsjVh") == FALSE || $opt_h) {
  print STDERR << "EOF";
stripchart: creates stripchart .gif graphic based on data in flat files
options:
  -i: input FILE      - name of input data file (mandatory)
  -o: output FILE     - name of output .gif file (default: STDOUT)
  -O: output FILE     - name of output .gif file and dump to STDOUT as well
  -f: from TIME       - stripchart with data starting at TIME 
                        (default: 24 hours ago)
  -t: to TIME         - stripchart with data ending at TIME (default: now)
  -r: range RANGE     - stripchart data centered around "from" time the size
                        of RANGE (overrides -t)
  -l: last LINES      - stripchart last number of LINES in data file
                        (overrides -f and -t and -r)
  -T: title TITLE     - title to put on graphic (default: FILE RANGE)
  -x: column X        - time or "x" column (default: 2)
  -y: column Y        - value or "y" column (default: 3)
  -Y: column Y'       - overplot second "y" column (default: none)
  -b: baseline VALUE  - overplot baseline of arbitrary value VALUE
  -B: baseline-avg    - overrides -b, it plots baseline of computed average
  -d: dump low VALUE  - ignore data less than VALUE
  -D: dump high VALUE - ignore data higher than VALUE
  -v: verbose         - puts verbose runtime output to STDERR
  -L: log             - makes y axis log scale
  -c: colors "COLORS" - set gnuplot colors for graph/axis/fonts/data (default:
                        "$colorvals"
                        in order: bground, axis/fonts, grids, pointcolor1,2,3)
  -C: cgi             - output CGI header to STDOUT if being called as CGI
  -s: stats           - turn extra plot stats on (current, avg, min, max)
  -j: julian times    - time columns is in local julian date (legacy stuff)
  -V: version         - print version number and exit
  -h: help            - display this help 

notes:
  * TIME either unix date, julian date, or civil date in the form:
      YYYY:MM:DD:HH:MM (year, month, day, hour, minute)
    If you enter something with colons, it assumes it is civil date
    If you have a decimal point, it assumes it is julian date
    If it is an integer, it assumes it is unix date (epoch seconds)
    If it is a negative number, it is in decimal days from current time
      (i.e. -2.5 = two and a half days ago)
    * All times on command line are assumed to be "local" times
    * All times in the data file must be in unix date (epoch seconds)
  * RANGE is given in decimal days (i.e. 1.25 = 1 day, 6 hours)
  * if LINES == 0, (i.e. -l 0) then the whole data file is read in
  * columns (given with -x, -y, -Y flags) start at 1
  * titles given with -T can contain the following key words which will
    be converted:
      FILE - basename of input file
      RANGE - pretty civil date range (in local time zone)
    the default title is: FILE RANGE
EOF
  exit 1
  } 

if ($opt_V) {
  print STDERR "Stripchart version $majorversion.$minorversion by Matt Lebofsky\n";
  exit 1
  }

if ($opt_C && $opt_v) {
  print STDERR "you cannot have -v and -C set at the same time..\n"; exit 1 }

if ($opt_i) { $infile = $opt_i }
else { print STDERR "need to set input file via -i. exiting..\n"; exit 1 }

if ($opt_f) { 
  if ($opt_f < 0) { $fromtime = to_unix_time($rightnow) + ($daysecs * $opt_f) }
  else { $fromtime = to_unix_time($opt_f) }
  }
else { $fromtime = to_unix_time($rightnow) - $daysecs }

if ($opt_t) { $totime = to_unix_time($opt_t) }
else { $totime = to_unix_time($rightnow) }

if ($opt_v) { print STDERR "selected time range: $fromtime - $totime\n" }

if ($opt_r) { 
  $totime = $fromtime + ($opt_r * $daysecs);   
  $fromtime -= ($opt_r * $daysecs)
  }

# if -l is set, override from/to with close-to-impossible all-inclusive range
if (defined($opt_l)) { $fromtime = 0; $totime = 2147483647 }

if ($opt_x) { $timecol = $opt_x } else { $timecol = 2 }
if ($opt_y) { $datacol = $opt_y } else { $datacol = 3 }
if ($opt_Y) { $extracol = $opt_Y }

if ($opt_c) { $colorvals = $opt_c }

# read in file

if ($opt_v) { print STDERR "reading in data from $infile..\n" }

if ($opt_l > 0) {
  $numlines = $opt_l;
  @stripdata = `$tailexe -$numlines $infile` or die "cannot open file: $infile";
  }
else {
  @stripdata = `$catexe $infile` or die "cannot open file: $infile";
  $numlines = @stripdata;
  }

if ($opt_v) { print STDERR "read in $numlines lines..\n" }

# make gnuplot data file

if ($opt_v) { print STDERR "making temp data file for gnuplot..\n" }

open (GNUDATA,">$gnudata") or die "cannot write temp data file: $gnudata";

$statcurrent = 0;
$statmax = "x";
$statmin = "x";
$stattotal = 0;

$checkfromtime = $fromtime;
if ($opt_j) { $checkfromtime = (($fromtime + $tzdiff) / $daysecs ) + 2440587.5 }

$thisextra = 0;
$thisbaseline = 0;
if ($opt_b) { $thisbaseline = $opt_b }
$numlines = 0;
$firstunixdate = -1;
foreach $dataline (@stripdata) {
  chomp $dataline;
  @dataarray = split /\s/, $dataline;
  $thistime = $dataarray[$timecol-1];
  if ($thistime < $checkfromtime) { next }
  if ($opt_j) { $thistime = int(($dataarray[$timecol-1] - 2440587.5) * $daysecs) - $tzdiff }
  $thisdata = $dataarray[$datacol-1];
  if ($thistime <= $totime) { 
    if ($thistime !~ /[a-zA-Z]/ && $thisdata !~ /[a-zA-Z]/ &&  # ignore junky numbers
        $thisdata ne "" ) {
      if ((defined($opt_d) && ($thisdata >= $opt_d)) || !defined($opt_d)) {
        if ((defined($opt_D) && ($thisdata <= $opt_D)) || !defined($opt_D)) {
          $numlines++;
          if ($firstunixdate == -1) { $firstunixdate = $thistime }
          $lastunixdate = $thistime;
          if ($opt_Y) { $thisextra = $dataarray[$extracol-1]; }
          if ($opt_s) {
            $statcurrent = $thisdata;
            $stattotal += $thisdata;
            if ($statmax eq "x" || $thisdata > $statmax) { $statmax = $thisdata }
            if ($statmin eq "x" || $thisdata < $statmin) { $statmin = $thisdata }
            }
          print GNUDATA "$thistime $thisdata $thisextra $thisbaseline\n"
          }
        }
      }
    }
  }
close (GNUDATA);

$statavg = ($stattotal / $numlines);

if ($opt_B) {
  @tmpdata = `$catexe $gnudata`;
  open (GNUDATA,">$gnudata") or die "cannot write temp data file: $gnudata";
  foreach $tmpline (@tmpdata) {
    chomp $tmpline;
    ($tempone,$temptwo,$tempthree,$tempfour) = (split /\s/, $tmpline);
    $tempfour = $statavg;
    print GNUDATA "$tempone $temptwo $tempthree $tempfour\n";
    }
  close (GNUDATA);
  }

if ($numlines == 0) {
  print STDERR "no data selected due to user constraints.\n";
  exit 1
  }

if ($opt_v) { print STDERR "$numlines data points within time range..\n" }

$begin = $firstunixdate; $end = $lastunixdate;
if (!defined($opt_l)) { $begin = $fromtime; $end = $totime }

if ($opt_v) { print STDERR "actual time range being plotted: $begin - $end\n" }

# make gnuplot xtics file

$daydiff = $end - $begin;

if ($opt_v) { print STDERR "making xtics file..\n" }

# depending on the range, pick appropriate tic steps and label steps

$labelstep = 7200;
$ticstep = 3600;

# less than 10 minutes: label every minute, extra tics every 30 seconds 
if ($daydiff <= 600) { $labelstep = 60; $ticstep = 30 }
# less than 50 minutes: label every 5 minutes, extra tics every minute
elsif ($daydiff <= 3000) { $labelstep = 300; $ticstep = 60 }
# less than 100 minutes: label every 10 minutes, extra tics every 5 minutes
elsif ($daydiff <= 6000) { $labelstep = 600; $ticstep = 300 }
# less than 200 minutes: label every 20 minutes, extra tics every 10 minutes
elsif ($daydiff <= 12000) { $labelstep = 1200; $ticstep = 600 }

# less than 5 hours: label every 30 minutes, extra tics every 15 minutes
elsif ($daydiff <= 18000) { $labelstep = 1800; $ticstep = 900 }
# less than 10 hours: label every hour, extra tics every 30 minutes
elsif ($daydiff <= 36000) { $labelstep = 3600; $ticstep = 1800 }
# less than 20 hours: label every 2 hours, extra tics every hour
elsif ($daydiff <= 72000) { $labelstep = 7200; $ticstep = 3600 }
# less than 40 hours: label every 4 hours, extra tics every hour
elsif ($daydiff <= 144000) { $labelstep = 14400 ; $ticstep = 3600 }
# less than 60 hours: label every 6 hours, extra tics every hour
elsif ($daydiff <= 216000) { $labelstep = 21600; $ticstep = 3600 }
# less than 120 hours: label every 12 hours, extra tics every 6 hours
elsif ($daydiff <= 432000) { $labelstep = 43200; $ticstep = 21600 }

# less than 10 days: label every day, extra tics every half day
elsif ($daydiff <= 864000) { $labelstep = 86400; $ticstep = 43200 }
# less than 20 days: label every 2 days, extra tics every day
elsif ($daydiff <= 1728000) { $labelstep = 172800; $ticstep = 86400 }
# less than 40 days: label every 4 days, extra tics every 2 days
elsif ($daydiff <= 3456000) { $labelstep = 345600; $ticstep = 172800 }
# less than 70 days: label every 7 days, extra tics every 7 days
elsif ($daydiff <= 6048000) { $labelstep = 604800; $ticstep = 604800 }
# less than 140 days: label every 14 days, extra tics every 7 days
elsif ($daydiff <= 12096000) { $labelstep = 1209600; $ticstep = 604800 }
# less than 280 days: label every 28 days, extra tics every 14 days
elsif ($daydiff <= 24192000) { $labelstep = 2419200; $ticstep = 1209600 }
# less than 600 days: label every 60 days, extra tics every 30 days
elsif ($daydiff <= 51840000) { $labelstep = 5184000; $ticstep = 2592000 }
# less than 1000 days: label every 100 days, extra tics every 50 days
elsif ($daydiff <= 86400000) { $labelstep = 8640000; $ticstep = 4320000 }
# okay, you're on your own now: every 200 days, extra tics every 100 days
else { $labelstep = 17280000; $ticstep = 8640000 }

if ($opt_v) { 
  print STDERR "x label resolution: $labelstep seconds..\n";
  print STDERR "x tic resolution: $ticstep seconds..\n" }

open (TICDATA,">$ticdata") or die "cannot write temp tic file: $ticdata";
print TICDATA "set xtics( \\\n";

if ($daydiff >= 18000 && $daydiff <= 216000) {
  # round down/up to nearest hour
  $firstunixdate = int($firstunixdate/3600) * 3600;
  $lastunixdate = (int($lastunixdate/3600)+1) * 3600;
  }
elsif ($daydiff >= 216000) {
  # round down/up to nearest day
  $firstunixdate = ((int($firstunixdate/86400)) * 86400) - $tzdiff;
  $lastunixdate = ((int($lastunixdate/86400)+1) * 86400) - $tzdiff;
  }

for ($thisdate = $firstunixdate; $thisdate < $lastunixdate; $thisdate += $ticstep) {
  $label = '""';
  if (($thisdate - $firstunixdate) % $labelstep == 0) {
    if ($daydiff <= 432000) {
      $label = '"' . time_to_hourlabel($thisdate) . '"'
      }
    else {
      $label = '"' . time_to_monthlabel($thisdate) . '"'
      }
    }
  print TICDATA $label . " " . $thisdate;
  if (($thisdate + $ticstep) < $lastunixdate) { print TICDATA "," }
  print TICDATA " \\\n";
  }
print TICDATA ")\n";
close (TICDATA);

# make gnuplot file and run it!

if ($opt_v) { print STDERR "running gnuplot to create $opt_o..\n" }

if (defined($opt_l)) { # fix for title
  $fromtime = $begin;
  $totime = $end;
  } 

if ($opt_T) { $title = $opt_T } else { $title = "FILE RANGE" }
$thisfile = basename($infile);
$thisrange = "(" . unix_to_civillabel($fromtime) . " -> " .
             unix_to_civillabel($totime) . ")"; 
$title =~ s/FILE/$thisfile/g;
$title =~ s/RANGE/$thisrange/g;

if ($opt_s) { 
  $plotheight += 12;
  $statlabel = sprintf("(cur: %.2f  max: %.2f  min: %.2f  avg: %.2f)",$statcurrent,$statmax,$statmin,$statavg);
  $title .= "\\n$statlabel";
  }

open (GNUSCRIPT,">$gnuscript") or die "cannot open gnuscript file: $gnuscript";
print GNUSCRIPT "set terminal gif small size $plotwidth, $plotheight \\\n";
print GNUSCRIPT "$colorvals\n";
print GNUSCRIPT "set nokey\nset grid\nset title \"$title\"\n";
if ($opt_L) { print GNUSCRIPT "set logscale y\n" }
print GNUSCRIPT "set pointsize 0.1\n";
print GNUSCRIPT "plot \"$gnudata\" using 1:2 with impulses";
if ($opt_Y) { 
  print GNUSCRIPT ", \"$gnudata\" using 1:3 with lines" 
  }
if ($opt_b || $opt_B) { 
  print GNUSCRIPT ", \"$gnudata\" using 1:4 with lines" 
  }
print GNUSCRIPT "\n";
close (GNUSCRIPT);

if ($opt_C) {
  print "Content-type: image/gif\n\n";
  }

if ($opt_o) { `$gnuplot/gnuplot $ticdata $gnuscript > $opt_o` }
else { 
  `$gnuplot/gnuplot $ticdata $gnuscript > $outfile`;
  open (OUTFILE,"$outfile");
  while ($bytesread=read(OUTFILE,$buffer,1024)) { print $buffer }
  close (OUTFILE);
  if ($opt_O) { `$gnuplot/gnuplot $ticdata $gnuscript > $opt_O` }
  }

# the end. clean up.

if ($opt_v) { print "done. cleaning up..\n" }

unlink ($outfile);
unlink ($ticdata);
unlink ($gnudata);
unlink ($gnuscript);
exit 0;