1*ea37671dSMatthew Dillon /* 2*ea37671dSMatthew Dillon * Copyright (c) 2019 The DragonFly Project. All rights reserved. 3*ea37671dSMatthew Dillon * 4*ea37671dSMatthew Dillon * This code is derived from software contributed to The DragonFly Project 5*ea37671dSMatthew Dillon * by Matthew Dillon <dillon@backplane.com> 6*ea37671dSMatthew Dillon * 7*ea37671dSMatthew Dillon * This code uses concepts and configuration based on 'synth', by 8*ea37671dSMatthew Dillon * John R. Marino <draco@marino.st>, which was written in ada. 9*ea37671dSMatthew Dillon * 10*ea37671dSMatthew Dillon * Redistribution and use in source and binary forms, with or without 11*ea37671dSMatthew Dillon * modification, are permitted provided that the following conditions 12*ea37671dSMatthew Dillon * are met: 13*ea37671dSMatthew Dillon * 14*ea37671dSMatthew Dillon * 1. Redistributions of source code must retain the above copyright 15*ea37671dSMatthew Dillon * notice, this list of conditions and the following disclaimer. 16*ea37671dSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright 17*ea37671dSMatthew Dillon * notice, this list of conditions and the following disclaimer in 18*ea37671dSMatthew Dillon * the documentation and/or other materials provided with the 19*ea37671dSMatthew Dillon * distribution. 20*ea37671dSMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its 21*ea37671dSMatthew Dillon * contributors may be used to endorse or promote products derived 22*ea37671dSMatthew Dillon * from this software without specific, prior written permission. 23*ea37671dSMatthew Dillon * 24*ea37671dSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 25*ea37671dSMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26*ea37671dSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 27*ea37671dSMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 28*ea37671dSMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 29*ea37671dSMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 30*ea37671dSMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31*ea37671dSMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 32*ea37671dSMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 33*ea37671dSMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 34*ea37671dSMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35*ea37671dSMatthew Dillon * SUCH DAMAGE. 36*ea37671dSMatthew Dillon */ 37*ea37671dSMatthew Dillon 38*ea37671dSMatthew Dillon #include "dsynth.h" 39*ea37671dSMatthew Dillon 40*ea37671dSMatthew Dillon static runstats_t *RSBase; 41*ea37671dSMatthew Dillon static runstats_t **RSTailp = &RSBase; 42*ea37671dSMatthew Dillon static time_t RSStartTime; 43*ea37671dSMatthew Dillon 44*ea37671dSMatthew Dillon #define RHISTSIZE 600 /* impulse record is 10 minutes */ 45*ea37671dSMatthew Dillon #define ONEHOUR (60 * 60) 46*ea37671dSMatthew Dillon 47*ea37671dSMatthew Dillon void 48*ea37671dSMatthew Dillon RunStatsInit(void) 49*ea37671dSMatthew Dillon { 50*ea37671dSMatthew Dillon runstats_t *rs; 51*ea37671dSMatthew Dillon 52*ea37671dSMatthew Dillon RSStartTime = time(NULL); 53*ea37671dSMatthew Dillon 54*ea37671dSMatthew Dillon *RSTailp = &NCursesRunStats; 55*ea37671dSMatthew Dillon RSTailp = &(*RSTailp)->next; 56*ea37671dSMatthew Dillon 57*ea37671dSMatthew Dillon *RSTailp = &MonitorRunStats; 58*ea37671dSMatthew Dillon RSTailp = &(*RSTailp)->next; 59*ea37671dSMatthew Dillon 60*ea37671dSMatthew Dillon *RSTailp = &HtmlRunStats; 61*ea37671dSMatthew Dillon RSTailp = &(*RSTailp)->next; 62*ea37671dSMatthew Dillon 63*ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 64*ea37671dSMatthew Dillon rs->init(); 65*ea37671dSMatthew Dillon } 66*ea37671dSMatthew Dillon 67*ea37671dSMatthew Dillon void 68*ea37671dSMatthew Dillon RunStatsDone(void) 69*ea37671dSMatthew Dillon { 70*ea37671dSMatthew Dillon runstats_t *rs; 71*ea37671dSMatthew Dillon 72*ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 73*ea37671dSMatthew Dillon rs->done(); 74*ea37671dSMatthew Dillon } 75*ea37671dSMatthew Dillon 76*ea37671dSMatthew Dillon void 77*ea37671dSMatthew Dillon RunStatsReset(void) 78*ea37671dSMatthew Dillon { 79*ea37671dSMatthew Dillon runstats_t *rs; 80*ea37671dSMatthew Dillon 81*ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 82*ea37671dSMatthew Dillon rs->reset(); 83*ea37671dSMatthew Dillon } 84*ea37671dSMatthew Dillon 85*ea37671dSMatthew Dillon void 86*ea37671dSMatthew Dillon RunStatsUpdate(worker_t *work) 87*ea37671dSMatthew Dillon { 88*ea37671dSMatthew Dillon runstats_t *rs; 89*ea37671dSMatthew Dillon 90*ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 91*ea37671dSMatthew Dillon rs->update(work); 92*ea37671dSMatthew Dillon } 93*ea37671dSMatthew Dillon 94*ea37671dSMatthew Dillon void 95*ea37671dSMatthew Dillon RunStatsUpdateTop(void) 96*ea37671dSMatthew Dillon { 97*ea37671dSMatthew Dillon static int rate_history[RHISTSIZE]; 98*ea37671dSMatthew Dillon static u_int last_ti; 99*ea37671dSMatthew Dillon topinfo_t info; 100*ea37671dSMatthew Dillon runstats_t *rs; 101*ea37671dSMatthew Dillon u_int ti; 102*ea37671dSMatthew Dillon time_t t; 103*ea37671dSMatthew Dillon 104*ea37671dSMatthew Dillon /* 105*ea37671dSMatthew Dillon * Time 106*ea37671dSMatthew Dillon */ 107*ea37671dSMatthew Dillon bzero(&info, sizeof(info)); 108*ea37671dSMatthew Dillon t = time(NULL) - RSStartTime; 109*ea37671dSMatthew Dillon info.s = t % 60; 110*ea37671dSMatthew Dillon info.m = t / 60 % 60; 111*ea37671dSMatthew Dillon info.h = t / 60 / 60; 112*ea37671dSMatthew Dillon 113*ea37671dSMatthew Dillon /* 114*ea37671dSMatthew Dillon * Easy fields 115*ea37671dSMatthew Dillon */ 116*ea37671dSMatthew Dillon info.total = BuildTotal; 117*ea37671dSMatthew Dillon info.successful = BuildSuccessCount; 118*ea37671dSMatthew Dillon info.ignored = BuildIgnoreCount; 119*ea37671dSMatthew Dillon info.remaining = BuildTotal - BuildCount; 120*ea37671dSMatthew Dillon info.failed = BuildFailCount; 121*ea37671dSMatthew Dillon info.skipped = BuildSkipCount; 122*ea37671dSMatthew Dillon 123*ea37671dSMatthew Dillon /* 124*ea37671dSMatthew Dillon * Load and swap 125*ea37671dSMatthew Dillon */ 126*ea37671dSMatthew Dillon getloadavg(info.dload, 3); 127*ea37671dSMatthew Dillon info.dswap = getswappct(&info.noswap) * 100.0; 128*ea37671dSMatthew Dillon 129*ea37671dSMatthew Dillon /* 130*ea37671dSMatthew Dillon * Rate and 10-minute impulse 131*ea37671dSMatthew Dillon */ 132*ea37671dSMatthew Dillon if (t > 20) 133*ea37671dSMatthew Dillon info.pkgrate = (BuildSuccessCount + BuildFailCount) * 134*ea37671dSMatthew Dillon ONEHOUR / t; 135*ea37671dSMatthew Dillon else 136*ea37671dSMatthew Dillon info.pkgrate = 0; 137*ea37671dSMatthew Dillon ti = (u_int)((unsigned long)t % RHISTSIZE); 138*ea37671dSMatthew Dillon rate_history[ti] = BuildSuccessCount + BuildFailCount; 139*ea37671dSMatthew Dillon #if 0 140*ea37671dSMatthew Dillon dlog(DLOG_ALL, "ti[%3d] = %d\n", ti, rate_history[ti]); 141*ea37671dSMatthew Dillon #endif 142*ea37671dSMatthew Dillon while (last_ti != ti) { 143*ea37671dSMatthew Dillon rate_history[last_ti] = rate_history[ti]; 144*ea37671dSMatthew Dillon last_ti = (last_ti + 1) % RHISTSIZE; 145*ea37671dSMatthew Dillon } 146*ea37671dSMatthew Dillon 147*ea37671dSMatthew Dillon if (t < 20) { 148*ea37671dSMatthew Dillon info.pkgimpulse = 0; 149*ea37671dSMatthew Dillon } else if (t < RHISTSIZE) { 150*ea37671dSMatthew Dillon info.pkgimpulse = rate_history[ti] - 151*ea37671dSMatthew Dillon rate_history[(ti - t) % RHISTSIZE]; 152*ea37671dSMatthew Dillon info.pkgimpulse = info.pkgimpulse * ONEHOUR / t; 153*ea37671dSMatthew Dillon } else { 154*ea37671dSMatthew Dillon info.pkgimpulse = rate_history[ti] - 155*ea37671dSMatthew Dillon rate_history[(ti + 1) % RHISTSIZE]; 156*ea37671dSMatthew Dillon info.pkgimpulse = info.pkgimpulse * ONEHOUR / RHISTSIZE; 157*ea37671dSMatthew Dillon #if 0 158*ea37671dSMatthew Dillon dlog(DLOG_ALL, "pkgimpulse %d - %d -> %d\n", 159*ea37671dSMatthew Dillon rate_history[ti], 160*ea37671dSMatthew Dillon rate_history[(ti + 1) % RHISTSIZE], 161*ea37671dSMatthew Dillon info.pkgimpulse); 162*ea37671dSMatthew Dillon #endif 163*ea37671dSMatthew Dillon } 164*ea37671dSMatthew Dillon 165*ea37671dSMatthew Dillon /* 166*ea37671dSMatthew Dillon * Issue update 167*ea37671dSMatthew Dillon */ 168*ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 169*ea37671dSMatthew Dillon rs->updateTop(&info); 170*ea37671dSMatthew Dillon } 171*ea37671dSMatthew Dillon 172*ea37671dSMatthew Dillon void 173*ea37671dSMatthew Dillon RunStatsUpdateLogs(void) 174*ea37671dSMatthew Dillon { 175*ea37671dSMatthew Dillon runstats_t *rs; 176*ea37671dSMatthew Dillon 177*ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 178*ea37671dSMatthew Dillon rs->updateLogs(); 179*ea37671dSMatthew Dillon } 180*ea37671dSMatthew Dillon 181*ea37671dSMatthew Dillon void 182*ea37671dSMatthew Dillon RunStatsSync(void) 183*ea37671dSMatthew Dillon { 184*ea37671dSMatthew Dillon runstats_t *rs; 185*ea37671dSMatthew Dillon 186*ea37671dSMatthew Dillon for (rs = RSBase; rs; rs = rs->next) 187*ea37671dSMatthew Dillon rs->sync(); 188*ea37671dSMatthew Dillon } 189