Issues (2963)

includes/billing.php (3 issues)

1
<?php
2
3
use LibreNMS\Config;
4
use LibreNMS\Util\Number;
5
6
function format_bytes_billing($value)
7
{
8
    return Number::formatBase($value, Config::get('billing.base'));
9
}//end format_bytes_billing()
10
11
function format_bytes_billing_short($value)
12
{
13
    return Number::formatBase($value, Config::get('billing.base'), 2, 3, '');
14
}//end format_bytes_billing_short()
15
16
function getDates($dayofmonth, $months = 0)
17
{
18
    $dayofmonth = zeropad($dayofmonth);
19
    $year = date('Y');
20
    $month = date('m');
21
22
    if (date('d') > $dayofmonth) {
23
        // Billing day is past, so it is next month
24
        $date_end = date_create($year . '-' . $month . '-' . $dayofmonth);
25
        $date_start = date_create($year . '-' . $month . '-' . $dayofmonth);
26
        date_add($date_end, date_interval_create_from_date_string('1 month'));
27
    } else {
28
        // Billing day will happen this month, therefore started last month
29
        $date_end = date_create($year . '-' . $month . '-' . $dayofmonth);
30
        $date_start = date_create($year . '-' . $month . '-' . $dayofmonth);
31
        date_sub($date_start, date_interval_create_from_date_string('1 month'));
32
    }
33
34
    if ($months > 0) {
35
        date_sub($date_start, date_interval_create_from_date_string($months . ' month'));
36
        date_sub($date_end, date_interval_create_from_date_string($months . ' month'));
37
    }
38
39
    // date_sub($date_start, date_interval_create_from_date_string('1 month'));
40
    date_sub($date_end, date_interval_create_from_date_string('1 day'));
41
42
    $date_from = date_format($date_start, 'Ymd') . '000000';
43
    $date_to = date_format($date_end, 'Ymd') . '235959';
44
45
    date_sub($date_start, date_interval_create_from_date_string('1 month'));
46
    date_sub($date_end, date_interval_create_from_date_string('1 month'));
47
48
    $last_from = date_format($date_start, 'Ymd') . '000000';
49
    $last_to = date_format($date_end, 'Ymd') . '235959';
50
51
    $return = [];
52
    $return['0'] = $date_from;
53
    $return['1'] = $date_to;
54
    $return['2'] = $last_from;
55
    $return['3'] = $last_to;
56
57
    return $return;
58
}//end getDates()
59
60
function getPredictedUsage($bill_day, $cur_used)
61
{
62
    $tmp = getDates($bill_day, 0);
63
    $start = new DateTime($tmp[0], new DateTimeZone(date_default_timezone_get()));
64
    $end = new DateTime($tmp[1], new DateTimeZone(date_default_timezone_get()));
65
    $now = new DateTime(date('Y-m-d'), new DateTimeZone(date_default_timezone_get()));
66
    $total = $end->diff($start)->format('%a');
67
    $since = $now->diff($start)->format('%a');
68
69
    return $cur_used / $since * $total;
70
}
71
72
function getValue($host, $port, $id, $inout)
73
{
74
    $oid = 'IF-MIB::ifHC' . $inout . 'Octets.' . $id;
75
    $device = dbFetchRow('SELECT * from `devices` WHERE `hostname` = ? LIMIT 1', [$host]);
76
    $value = snmp_get($device, $oid, '-Oqv');
77
78
    if (! is_numeric($value)) {
79
        $oid = 'IF-MIB::if' . $inout . 'Octets.' . $id;
80
        $value = snmp_get($device, $oid, '-Oqv');
81
    }
82
83
    return $value;
84
}//end getValue()
85
86
function getLastPortCounter($port_id, $bill_id)
87
{
88
    $return = [];
89
    $row = dbFetchRow('SELECT timestamp, in_counter, in_delta, out_counter, out_delta FROM bill_port_counters WHERE `port_id` = ? AND `bill_id` = ?', [$port_id, $bill_id]);
90
    if (! is_null($row)) {
91
        $return['timestamp'] = $row['timestamp'];
92
        $return['in_counter'] = $row['in_counter'];
93
        $return['in_delta'] = $row['in_delta'];
94
        $return['out_counter'] = $row['out_counter'];
95
        $return['out_delta'] = $row['out_delta'];
96
        $return['state'] = 'ok';
97
    } else {
98
        $return['state'] = 'failed';
99
    }
100
101
    return $return;
102
}//end getLastPortCounter()
103
104
function getLastMeasurement($bill_id)
105
{
106
    $return = [];
107
    $row = dbFetchRow('SELECT timestamp,delta,in_delta,out_delta FROM bill_data WHERE bill_id = ? ORDER BY timestamp DESC LIMIT 1', [$bill_id]);
108
    if (! is_null($row)) {
109
        $return['delta'] = $row['delta'];
110
        $return['delta_in'] = $row['delta_in'];
111
        $return['delta_out'] = $row['delta_out'];
112
        $return['timestamp'] = $row['timestamp'];
113
        $return['state'] = 'ok';
114
    } else {
115
        $return['state'] = 'failed';
116
    }
117
118
    return $return;
119
}//end getLastMeasurement()
120
121
function get95thagg($bill_id, $datefrom, $dateto)
122
{
123
    $mq_sql = 'SELECT count(delta) FROM bill_data WHERE bill_id = ?';
124
    $mq_sql .= ' AND timestamp > ? AND timestamp <= ?';
125
    $measurements = dbFetchCell($mq_sql, [$bill_id, $datefrom, $dateto]);
126
    $measurement_95th = (round(($measurements / 100 * 95)) - 1);
127
128
    $q_95_sql = 'SELECT (delta / period * 8) AS rate FROM bill_data  WHERE bill_id = ?';
129
    $q_95_sql .= ' AND timestamp > ? AND timestamp <= ? ORDER BY rate ASC';
130
    $a_95th = dbFetchColumn($q_95_sql, [$bill_id, $datefrom, $dateto]);
131
    $m_95th = $a_95th[$measurement_95th];
132
133
    return round($m_95th, 2);
134
}//end get95thagg()
135
136
function get95thIn($bill_id, $datefrom, $dateto)
137
{
138
    $mq_sql = 'SELECT count(delta) FROM bill_data WHERE bill_id = ?';
139
    $mq_sql .= ' AND timestamp > ? AND timestamp <= ?';
140
    $measurements = dbFetchCell($mq_sql, [$bill_id, $datefrom, $dateto]);
141
    $measurement_95th = (round(($measurements / 100 * 95)) - 1);
142
143
    $q_95_sql = 'SELECT (in_delta / period * 8) AS rate FROM bill_data  WHERE bill_id = ?';
144
    $q_95_sql .= ' AND timestamp > ? AND timestamp <= ? ORDER BY rate ASC';
145
    $a_95th = dbFetchColumn($q_95_sql, [$bill_id, $datefrom, $dateto]);
146
    $m_95th = $a_95th[$measurement_95th];
147
148
    return round($m_95th, 2);
149
}//end get95thIn()
150
151
function get95thout($bill_id, $datefrom, $dateto)
152
{
153
    $mq_sql = 'SELECT count(delta) FROM bill_data WHERE bill_id = ?';
154
    $mq_sql .= ' AND timestamp > ? AND timestamp <= ?';
155
    $measurements = dbFetchCell($mq_sql, [$bill_id, $datefrom, $dateto]);
156
    $measurement_95th = (round(($measurements / 100 * 95)) - 1);
157
158
    $q_95_sql = 'SELECT (out_delta / period * 8) AS rate FROM bill_data  WHERE bill_id = ?';
159
    $q_95_sql .= ' AND timestamp > ? AND timestamp <= ? ORDER BY rate ASC';
160
    $a_95th = dbFetchColumn($q_95_sql, [$bill_id, $datefrom, $dateto]);
161
    $m_95th = $a_95th[$measurement_95th];
162
163
    return round($m_95th, 2);
164
}//end get95thout()
165
166
function getRates($bill_id, $datefrom, $dateto, $dir_95th)
167
{
168
    $data = [];
169
170
    $sum_data = getSum($bill_id, $datefrom, $dateto);
171
    $mtot = $sum_data['total'];
172
    $mtot_in = $sum_data['inbound'];
173
    $mtot_out = $sum_data['outbound'];
174
    $ptot = $sum_data['period'];
175
176
    $data['rate_95th_in'] = get95thIn($bill_id, $datefrom, $dateto);
177
    $data['rate_95th_out'] = get95thout($bill_id, $datefrom, $dateto);
178
179
    if ($dir_95th == 'agg') {
180
        $data['rate_95th'] = get95thagg($bill_id, $datefrom, $dateto);
181
        $data['dir_95th'] = 'agg';
182
    } else {
183
        if ($data['rate_95th_out'] > $data['rate_95th_in']) {
184
            $data['rate_95th'] = $data['rate_95th_out'];
185
            $data['dir_95th'] = 'out';
186
        } else {
187
            $data['rate_95th'] = $data['rate_95th_in'];
188
            $data['dir_95th'] = 'in';
189
        }
190
    }
191
192
    $data['total_data'] = $mtot;
193
    $data['total_data_in'] = $mtot_in;
194
    $data['total_data_out'] = $mtot_out;
195
    $data['rate_average'] = ($mtot / $ptot * 8);
196
    $data['rate_average_in'] = ($mtot_in / $ptot * 8);
197
    $data['rate_average_out'] = ($mtot_out / $ptot * 8);
198
199
    // print_r($data);
200
    return $data;
201
}//end getRates()
202
203
function getTotal($bill_id, $datefrom, $dateto)
204
{
205
    $mtot = dbFetchCell('SELECT SUM(delta) FROM bill_data WHERE bill_id = ? AND timestamp > ? AND timestamp <= ?', [$bill_id, $datefrom, $dateto]);
206
207
    return $mtot;
208
}//end getTotal()
209
210
function getSum($bill_id, $datefrom, $dateto)
211
{
212
    $sum = dbFetchRow('SELECT SUM(period) as period, SUM(delta) as total, SUM(in_delta) as inbound, SUM(out_delta) as outbound FROM bill_data WHERE bill_id = ? AND timestamp > ? AND timestamp <= ?', [$bill_id, $datefrom, $dateto]);
213
214
    return $sum;
215
}//end getSum()
216
217
function getPeriod($bill_id, $datefrom, $dateto)
218
{
219
    $ptot = dbFetchRow('SELECT SUM(period) as `period`, MAX(in_delta) as `peak_in`, MAX(out_delta) as `peak_out`  FROM bill_data WHERE bill_id = ? AND timestamp > ? AND timestamp <= ?', [$bill_id, $datefrom, $dateto]);
220
221
    return $ptot;
222
}//end getPeriod()
223
224
function getBillingHistoryBitsGraphData($bill_id, $bill_hist_id, $reducefactor)
225
{
226
    $histrow = dbFetchRow('SELECT UNIX_TIMESTAMP(bill_datefrom) as `from`, UNIX_TIMESTAMP(bill_dateto) AS `to`, rate_95th, rate_average, bill_type FROM bill_history WHERE bill_id = ? AND bill_hist_id = ?', [$bill_id, $bill_hist_id]);
227
228
    if (is_null($histrow)) {
229
        return null;
230
    }
231
232
    $graph_data = getBillingBitsGraphData($bill_id, $histrow['from'], $histrow['to'], $reducefactor);
233
234
    // Overwrite the rate data with the historical version
235
    $graph_data['rate_95th'] = $histrow['rate_95th'];
236
    $graph_data['rate_average'] = $histrow['rate_average'];
237
    $graph_data['bill_type'] = $histrow['bill_type'];
238
239
    return $graph_data;
240
}
241
242
function getBillingBitsGraphData($bill_id, $from, $to, $reducefactor)
243
{
244
    $i = '0';
245
    $iter = 0;
246
    $first = null;
247
    $last = null;
248
    $iter_in = 0;
249
    $iter_out = 0;
250
    $iter_period = 0;
251
    $max_in = 0;
252
    $max_out = 0;
253
    $tot_in = 0;
254
    $tot_out = 0;
255
    $tot_period = 0;
256
    $in_delta = null;
257
    $out_delta = null;
258
    $period = null;
259
    $in_data = [];
260
    $out_data = [];
261
    $tot_data = [];
262
    $ticks = [];
263
264
    if (! isset($reducefactor) || ! is_numeric($reducefactor) || $reducefactor < 1) {
265
        // Auto calculate reduce factor
266
        $expectedpoints = ceil(($to - $from) / 300);
267
        $desiredpoints = 400;
268
        $reducefactor = max(1, floor($expectedpoints / $desiredpoints));
269
    }
270
271
    $bill_data = dbFetchRow('SELECT * from `bills` WHERE `bill_id`= ? LIMIT 1', [$bill_id]);
272
273
    foreach (dbFetch('SELECT *, UNIX_TIMESTAMP(timestamp) AS formatted_date FROM bill_data WHERE bill_id = ? AND `timestamp` >= FROM_UNIXTIME( ? ) AND `timestamp` <= FROM_UNIXTIME( ? ) ORDER BY timestamp ASC', [$bill_id, $from, $to]) as $row) {
274
        $timestamp = $row['formatted_date'];
275
        if (! $first) {
276
            $first = $timestamp;
277
        }
278
279
        $period = $row['period'];
280
        $in_delta = $row['in_delta'] * 8;
281
        $out_delta = $row['out_delta'] * 8;
282
        $last = $timestamp;
283
284
        $iter_in += $in_delta;
285
        $iter_out += $out_delta;
286
        $iter_period += $period;
287
288
        if ($period > 0) {
289
            $max_in = max($max_in, $in_delta / $period);
290
            $max_out = max($max_out, $out_delta / $period);
291
            $tot_in += $in_delta;
292
            $tot_out += $out_delta;
293
            $tot_period += $period;
294
295
            if (++$iter >= $reducefactor) {
296
                $out_data[$i] = round(($iter_out / $iter_period), 2);
297
                $in_data[$i] = round(($iter_in / $iter_period), 2);
298
                $tot_data[$i] = ($out_data[$i] + $in_data[$i]);
299
                $ticks[$i] = $timestamp;
300
                $i++;
301
                $iter = 0;
302
                unset($iter_out, $iter_in, $iter_period);
303
            }
304
        }
305
    }//end foreach
306
307
    if (! empty($iter_in)) {  // Write last element
308
        $out_data[$i] = round(($iter_out / $iter_period), 2);
309
        $in_data[$i] = round(($iter_in / $iter_period), 2);
310
        $tot_data[$i] = ($out_data[$i] + $in_data[$i]);
311
        $ticks[$i] = $timestamp;
312
        $i++;
313
    }
314
    $result = [
315
        'from'          => $from,
316
        'to'            => $to,
317
        'first'         => $first,
318
        'last'          => $last,
319
320
        'in_data'       => $in_data,
321
        'out_data'      => $out_data,
322
        'tot_data'      => $tot_data,
323
        'ticks'         => $ticks,
324
325
        'rate_95th'     => $bill_data['rate_95th'],
326
        'rate_average'  => $bill_data['rate_average'],
327
        'bill_type'     => $bill_data['bill_type'],
328
    ];
329
330
    if ($period) {
331
        $result['max_in'] = $max_in;
332
        $result['max_out'] = $max_out;
333
        $result['ave_in'] = $tot_in / $tot_period;
334
        $result['ave_out'] = $tot_out / $tot_period;
335
        $result['last_in'] = $in_delta / $period;
336
        $result['last_out'] = $out_delta / $period;
337
    }
338
339
    return $result;
340
}//end getBillingBitsGraphData
341
342
function getHistoricTransferGraphData($bill_id)
343
{
344
    $i = '0';
345
346
    $in_data = [];
347
    $out_data = [];
348
    $tot_data = [];
349
    $allow_data = [];
350
    $ave_data = [];
351
    $overuse_data = [];
352
    $ticklabels = [];
353
    $allowed_val = null;
354
355
    foreach (dbFetchRows('SELECT * FROM `bill_history` WHERE `bill_id` = ? ORDER BY `bill_datefrom` DESC LIMIT 12', [$bill_id]) as $data) {
356
        $datefrom = strftime('%Y-%m-%d', strtotime($data['bill_datefrom']));
357
        $dateto = strftime('%Y-%m-%d', strtotime($data['bill_dateto']));
358
        $datelabel = $datefrom . ' - ' . $dateto;
359
360
        array_push($ticklabels, $datelabel);
361
        array_push($in_data, $data['traf_in']);
362
        array_push($out_data, $data['traf_out']);
363
        array_push($tot_data, $data['traf_total']);
364
        array_push($allow_data, $allowed_val = ($data['bill_type'] == 'Quota' ? $data['bill_allowed'] : 0));
365
        array_push($overuse_data, $data['bill_type'] == 'Quota' ? $data['bill_overuse'] : 0);
366
        $i++;
367
    }//end foreach
368
369
    if ($i < 12) {
370
        $y = (12 - $i);
371
        for ($x = 0; $x < $y; $x++) {
372
            $allowed = (($x == '0') ? $allowed_val : '0');
373
            array_push($in_data, '0');
374
            array_push($out_data, '0');
375
            array_push($tot_data, '0');
376
            array_push($allow_data, $allowed);
377
            array_push($overuse_data, '0');
378
            array_push($ticklabels, '');
379
        }
380
    }
381
382
    $graph_name = 'Historical bandwidth over the last 12 billing periods';
383
384
    return [
385
        'graph_name'        => $graph_name,
386
        'in_data'           => $in_data,
387
        'out_data'          => $out_data,
388
        'tot_data'          => $tot_data,
389
        'allow_data'        => $allow_data,
390
        'ave_data'          => $ave_data,
391
        'overuse_data'      => $overuse_data,
392
        'ticklabels'        => $ticklabels,
393
    ];
394
}
395
396
function getBillingBandwidthGraphData($bill_id, $bill_hist_id, $from, $to, $imgtype)
397
{
398
    if (is_numeric($bill_hist_id)) {
399
        $histrow = dbFetchRow('SELECT UNIX_TIMESTAMP(bill_datefrom) as `from`, UNIX_TIMESTAMP(bill_dateto) AS `to`, rate_95th, rate_average FROM bill_history WHERE bill_id = ? AND bill_hist_id = ?', [$bill_id, $bill_hist_id]);
400
401
        if (is_null($histrow)) {
402
            return null;
403
        }
404
        $from = $histrow['from'];
405
        $to = $histrow['to'];
406
    } else {
407
        if (! is_numeric($from) || ! is_numeric($to)) {
408
            exit('Must supply from and to if bill_hist_id is not supplied');
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
409
        }
410
    }
411
412
    $in_data = [];
413
    $out_data = [];
414
    $tot_data = [];
415
    $allow_data = [];
416
    $ave_data = [];
417
    $overuse_data = [];
418
    $ticklabels = [];
419
420
    $data = [];
421
    $average = 0;
422
    if ($imgtype == 'day') {
423
        foreach (dbFetch('SELECT DISTINCT UNIX_TIMESTAMP(timestamp) as timestamp, SUM(delta) as traf_total, SUM(in_delta) as traf_in, SUM(out_delta) as traf_out FROM bill_data WHERE `bill_id` = ? AND `timestamp` >= FROM_UNIXTIME(?) AND `timestamp` <= FROM_UNIXTIME(?) GROUP BY DATE(timestamp) ORDER BY timestamp ASC', [$bill_id, $from, $to]) as $data) {
424
            array_push($ticklabels, strftime('%Y-%m-%d', $data['timestamp']));
425
            array_push($in_data, isset($data['traf_in']) ? $data['traf_in'] : 0);
426
            array_push($out_data, isset($data['traf_out']) ? $data['traf_out'] : 0);
427
            array_push($tot_data, isset($data['traf_total']) ? $data['traf_total'] : 0);
428
            $average += $data['traf_total'];
429
        }
430
431
        $ave_count = count($tot_data);
432
433
        // Add empty items for the days not yet passed
434
        $days = (strftime('%e', date($to - $from)) - $ave_count - 1);
0 ignored issues
show
date($to - $from) of type string is incompatible with the type integer|null expected by parameter $timestamp of strftime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

434
        $days = (strftime('%e', /** @scrutinizer ignore-type */ date($to - $from)) - $ave_count - 1);
Loading history...
435
        for ($x = 0; $x < $days; $x++) {
436
            array_push($ticklabels, '');
437
            array_push($in_data, 0);
438
            array_push($out_data, 0);
439
            array_push($tot_data, 0);
440
        }
441
    } elseif ($imgtype == 'hour') {
442
        foreach (dbFetch('SELECT DISTINCT HOUR(timestamp) as hour, SUM(delta) as traf_total, SUM(in_delta) as traf_in, SUM(out_delta) as traf_out FROM bill_data WHERE `bill_id` = ? AND `timestamp` >= FROM_UNIXTIME(?) AND `timestamp` <= FROM_UNIXTIME(?) GROUP BY HOUR(timestamp) ORDER BY HOUR(timestamp) ASC', [$bill_id, $from, $to]) as $data) {
443
            array_push($ticklabels, sprintf('%02d', $data['hour']) . ':00');
444
            array_push($in_data, isset($data['traf_in']) ? $data['traf_in'] : 0);
445
            array_push($out_data, isset($data['traf_out']) ? $data['traf_out'] : 0);
446
            array_push($tot_data, isset($data['traf_total']) ? $data['traf_total'] : 0);
447
            $average += $data['traf_total'];
448
        }
449
450
        $ave_count = count($tot_data);
451
    } else {
452
        exit("Unknown graph type $imgtype");
0 ignored issues
show
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
453
    }//end if
454
455
    $average = ($average / $ave_count);
456
    $tot_data_size = count($tot_data);
457
    for ($x = 0; $x <= $tot_data_size; $x++) {
458
        array_push($ave_data, $average);
459
    }
460
461
    $graph_name = date('M j g:ia', $from) . ' - ' . date('M j g:ia', $to);
462
463
    return [
464
        'graph_name'        => $graph_name,
465
        'in_data'           => $in_data,
466
        'out_data'          => $out_data,
467
        'tot_data'          => $tot_data,
468
        'allow_data'        => $allow_data,
469
        'ave_data'          => $ave_data,
470
        'overuse_data'      => $overuse_data,
471
        'ticklabels'        => $ticklabels,
472
    ];
473
}
474
//end getBillingBandwidthGraphData
475