home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!munnari.oz.au!manuel.anu.edu.au!coombs!avalon
- From: avalon@coombs.anu.edu.au (Darren Reed)
- Newsgroups: alt.irc
- Subject: IRC Traffic Stats stuff.
- Date: 17 Dec 92 16:05:45 GMT
- Organization: Australian National University
- Lines: 702
- Message-ID: <avalon.724608345@coombs>
- NNTP-Posting-Host: 150.203.76.2
-
-
- I've reworked the stats program a bit and included a couple of perl
- scripts which can be used to easily generate a set of commands for
- gnuplot. If you dont have gnuplot then this wont be of much use,
- even less use if your system isn't a member of the perl club.
-
- unshar, "make all" and run "runplot". The stats collector backgrounds
- into a 'daemon' mode. use "genplot" to generate the plot file for
- gnuplot. A few data files are also created. Any bugs, send me email.
- Nothing much else has changed. The graph should turn out to be bytes vs
- time and messages vs time. If you know a bit about gnuplot, you can
- get a postscript file of the graph too. This would be best run by those
- who are concerned about traffic and/or would like some hard data about
- how much bandwidth IRC is using.
-
- avalon
- ----cut here--------cut here--------cut here--------cut here--------cut here----
- #!/bin/sh
- # This is a shell archive. Save it in a file, remove anything before
- # this line, and then unpack it by entering "sh file". Note, it may
- # create directories; files and directories will be owned by you and
- # have default permissions.
- #
- # This archive contains:
- #
- # stat/Makefile
- # stat/README
- # stat/flowmon.c
- # stat/genplot
- # stat/runplot
- #
- echo x - stat/Makefile
- sed 's/^X//' >stat/Makefile << 'END-of-stat/Makefile'
- X# Makefile (C)1992 Darren Reed
- X# Makefile for realtime server stats clients
- X#
- XLIBS=-lcurses -ltermcap
- XCFLAGS=-O
- XPROGS=flowmon
- X
- Xall: $(PROGS)
- X
- Xcmdmon: cmdmon.c
- X $(CC) $@.c $(CFLAGS) -o $@ $(LIBS)
- X
- Xflowmon: flowmon.c
- X $(CC) $@.c $(CFLAGS) -o $@ $(LIBS)
- X
- Xclean:
- X /bin/rm -f core *.o $(PROGS)
- END-of-stat/Makefile
- echo x - stat/README
- sed 's/^X//' >stat/README << 'END-of-stat/README'
- X
- XSimple...
- X
- XEdit them to set the nicks, user info and server and then get them compiled.
- X
- Xthen run using
- X
- Xcmdmon [ server [ port [ updatedelay ] ] ]
- Xflowmon [ server [ port [ updatedelay ] ] ]
- X
- XBrief.
- X------
- X
- Xcmdmon
- X
- X Shows the changing use of the most used commands on the server in sorted
- Xorder of most used to least used.
- X
- Xflowmon
- X
- X Shows the flow of data into a server and out its links. Can be very
- Xuseful. Try flowmon -h for command line options.
- X
- XBoth use curses to maintain the display and should show as many entries
- Xas possible.
- X
- XThere are probably bugs somewhere too.
- END-of-stat/README
- echo x - stat/flowmon.c
- sed 's/^X//' >stat/flowmon.c << 'END-of-stat/flowmon.c'
- X/*
- X * flownmon.c (C)1992 Darren Reed.
- X * monitors data flow over irc server connections.
- X * maybe of use to someone.
- X */
- X#ifndef lint
- Xstatic char sccsid[] = "@(#)flowmon.c 2.2 12/18/92 (C)1992 Darren Reed";
- X#endif
- X
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <netinet/in.h>
- X#include <sys/socket.h>
- X#include <stdio.h>
- X#include <fcntl.h>
- X#include <curses.h>
- X#include <netdb.h>
- X/*
- X * change this.
- X */
- Xchar signon[] ="NICK %s\n\rUSER %s xx xx :Flow monitor\n\rMODE %s +i\r\n";
- X/*
- X * leave these
- X */
- Xchar pong[] = "PONG ping\r\n";
- Xchar statsm[] ="STATS l *\r\n";
- Xchar sends[100], *msg;
- Xchar operm[] = "OPER ---- -----\r\n";
- X
- X#define SERVERIP "150.203.76.2"
- X#define SERVERPORT 6667
- X#define UPDATEDELAY 60
- X
- Xchar buff[8192], servn[60], nick[20];
- Xchar name[60];
- Xint port;
- Xlong sq, sm, sb, rm, rb;
- Xint logfd[4];
- X
- Xstruct stats {
- X int sndq, sndm, sndb, rcvm, rcvb;
- X};
- X
- Xtypedef struct Message {
- X char cnam[60];
- X struct stats now;
- X struct stats old;
- X long update;
- X} MType;
- X
- Xstruct Message msgtab[256];
- X
- Xstatic int entries = sizeof(msgtab)/sizeof(MType);
- X
- Xvoid doio();
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X FILE *f;
- X int fd, mlen, daemon = 0;
- X int log = 0, set = 0, samples = 0;
- X char *remote = NULL, *server, *progname = *argv;
- X char *nick = NULL, *user = NULL;
- X long waittime;
- X struct hostent *hp = NULL;
- X
- X bzero(msgtab, sizeof(msgtab));
- X
- X argv++;
- X argc--;
- X server = SERVERIP;
- X port = SERVERPORT;
- X waittime = UPDATEDELAY;
- X
- X while (*argv && **argv == '-')
- X {
- X register char *s = *argv;
- X
- X argc--;
- X for (s++; *s; s++)
- X switch(*s)
- X {
- X case 'd' :
- X daemon = 1;
- X break;
- X case 'l' :
- X log = 1;
- X break;
- X case 'n' :
- X if (*(argv+1))
- X nick = *++argv;
- X break;
- X case 'p' :
- X if (*(argv+1))
- X port = atoi(*++argv);
- X break;
- X case 'r' :
- X if (*(argv+1))
- X remote = *++argv;
- X break;
- X case 's' :
- X if (*(argv+1))
- X server = *++argv;
- X break;
- X case 'u' :
- X if (*(argv+1))
- X user = *++argv;
- X break;
- X case 'w' :
- X if (*(argv+1))
- X waittime = atoi(*++argv);
- X break;
- X case 'z' :
- X if (*(argv+1))
- X samples = atoi(*++argv);
- X break;
- X case '?' :
- X printf("Usage: %s [-dl] [-n nick] [-p port] \
- X[-r server] [-s server] [-u username] [-w seconds]\n");
- X exit(1);
- X default :
- X break;
- X }
- X argv++;
- X }
- X /*
- X * ip# of server to connect to
- X */
- X
- X if (remote)
- X {
- X sprintf(sends, "STATS l %s\r\n", remote);
- X if (strcasecmp(remote, server))
- X mlen = strlen(msg = sends);
- X else
- X mlen = strlen(msg = statsm);
- X }
- X else
- X {
- X remote = server;
- X mlen = strlen(msg = statsm);
- X }
- X if (!nick)
- X nick = "flower";
- X if (!user)
- X user = "power";
- X
- X sprintf(buff, signon, nick, user, nick);
- X if (log)
- X openlogs(remote);
- X
- X fd = connectto(server);
- X
- X printf("Connected.\n");
- X write(fd, buff, strlen(buff));
- X write(fd, msg, mlen);
- X bzero(buff, sizeof(buff));
- X if (waittime < 10)
- X waittime = 10;
- X
- X if (!daemon)
- X {
- X initscr();
- X clear();
- X refresh();
- X }
- X else
- X {
- X if (fork())
- X exit(0);
- X setpgrp(getpid(),0);
- X }
- X
- X while (1)
- X doio(fd, msg, mlen, remote, log, waittime, daemon, samples);
- X}
- X
- Xint connectto(server)
- Xchar *server;
- X{
- X struct hostent *hp;
- X struct sockaddr_in sock;
- X int fd;
- X
- X bzero(&sock, sizeof(sock));
- X if (*server)
- X {
- X hp = gethostbyname(server);
- X if (hp)
- X bcopy(hp->h_addr_list[0], (char *)&sock.sin_addr,
- X sizeof(struct in_addr));
- X else
- X {
- X printf("couldnt lookup %s\n",server);
- X exit(0);
- X }
- X }
- X else
- X sock.sin_addr.s_addr = inet_addr(server);
- X printf("Connecting to %s\n", inet_ntoa(sock.sin_addr));
- X sock.sin_port = htons(port);
- X sock.sin_family = AF_INET;
- X
- X if ((fd = socket(AF_INET, SOCK_STREAM, 0))<0) {
- X perror("socket");
- X exit(-1);
- X }
- X
- X if (connect(fd, (char *)&sock, sizeof(sock))==-1) {
- X perror("connect");
- X exit(-1);
- X }
- X return fd;
- X}
- X
- Xvoid doio(fd, cmd, cmdlen, remserver, dolog, waittime, daemon, samples)
- Xchar *cmd, *remserver;
- Xint cmdlen, dolog, daemon, samples;
- Xlong waittime;
- X{
- X static long last = 0, lastm = 0, scanned = 0;
- X static char *head = buff, *tail = buff;
- X static int done = 0;
- X int n, len, fields, numb;
- X char *s = NULL, *t = NULL;
- X fd_set rd;
- X struct timeval wait;
- X
- X if (!last)
- X last = time(NULL);
- X if (!lastm)
- X lastm = time(NULL);
- X if (!scanned)
- X scanned = time(NULL);
- X
- X wait.tv_sec = 1;
- X wait.tv_usec = 0;
- X FD_ZERO(&rd);
- X FD_SET(fd, &rd);
- X n = select(FD_SETSIZE, &rd, NULL, NULL, &wait);
- X if (FD_ISSET(fd, &rd))
- X {
- X len = sizeof(buff) - (tail - buff);
- X if ((len = read(fd, tail, len)) <= 0)
- X {
- X s_error(s);
- X exit(-1);
- X }
- X tail += len;
- X *tail = '\0';
- X /*
- X ** check buffer for presence of full replies (terminated by
- X ** \n's).
- X */
- X while (s = (char *)index(head, '\n'))
- X {
- X *s++ = '\0';
- X len -= (s - head);
- X head = s;
- X if (len <= 0)
- X *buff = '\0';
- X if (t = (char *)index(head, ' '))
- X if (!isdigit(*++t))
- X continue;
- X fields = sscanf(head, ":%s %d %s", servn, &numb, nick);
- X if ((fields != 3) || (numb < 211) || (numb > 219))
- X continue;
- X if (numb == 219)
- X {
- X if (!daemon)
- X showstats(remserver, scanned);
- X done++;
- X if (samples && (done == samples))
- X {
- X if (dolog)
- X closelogs();
- X exit(0);
- X }
- X }
- X else if (numb == 211)
- X {
- X fields = sscanf(head,
- X ":%s %d %s %s %d %d %d %d %d",
- X servn, &numb, nick, name,
- X &sq, &sm, &sb, &rm, &rb);
- X if (fields == 9)
- X dostats(remserver, dolog, scanned);
- X }
- X }
- X if (len > 0 && head != buff)
- X {
- X movemem(head, buff, len);
- X head = buff;
- X tail = head + len;
- X *(tail+1) = '\0';
- X }
- X else
- X {
- X head = tail = buff;
- X *buff = '\0';
- X }
- X }
- X
- X if ((time(NULL) - last) > 30)
- X {
- X write(fd, pong, strlen(pong));
- X last = time(NULL);
- X }
- X
- X if ((time(NULL) - lastm) > waittime)
- X {
- X write(fd, cmd, cmdlen);
- X scanned = lastm = time(NULL);
- X }
- X}
- X
- Xs_error(fd)
- Xint fd;
- X{
- X perror("read");
- X}
- X
- Xdostats(remserver, dolog, scantime)
- Xchar *remserver;
- Xint dolog;
- Xlong scantime;
- X{
- X register int i;
- X register MType *mp;
- X
- X /*
- X ** update old table entry
- X */
- X mp = msgtab;
- X for (i = 256; i; i--, mp++)
- X if (!strcasecmp(mp->cnam, name))
- X {
- X bcopy(&mp->now, &mp->old,
- X sizeof(struct stats));
- X mp->now.sndq = sq;
- X mp->now.sndb = sb;
- X mp->now.sndm = sm;
- X mp->now.rcvb = rb;
- X mp->now.rcvm = rm;
- X mp->update = scantime;
- X if (dolog && !strcasecmp(name, remserver))
- X {
- X char num[16];
- X
- X sprintf(num, "%d\n",
- X sb - mp->old.sndb);
- X write(logfd[0], num, strlen(num));
- X sprintf(num, "%d\n",
- X sm - mp->old.sndm);
- X write(logfd[1], num, strlen(num));
- X sprintf(num, "%d\n",
- X rb - mp->old.rcvb);
- X write(logfd[2], num, strlen(num));
- X sprintf(num, "%d\n",
- X rm - mp->old.rcvm);
- X write(logfd[3], num, strlen(num));
- X }
- X return;
- X }
- X
- X /*
- X ** add a new one in
- X */
- X mp = msgtab;
- X for (i = 256; i; i--, mp++)
- X if (!*mp->cnam)
- X {
- X strcpy(mp->cnam, name);
- X mp->now.sndq = sq;
- X mp->now.sndb = sb;
- X mp->now.sndm = sm;
- X mp->now.rcvb = rb;
- X mp->now.rcvm = rm;
- X mp->update = scantime;
- X break;
- X }
- X}
- X
- X/*
- X** remove un updated entries from the table
- X*/
- Xremoveold(scantime)
- Xlong scantime;
- X{
- X register int i;
- X register MType *mp;
- X
- X mp = msgtab;
- X for (i = 256; i; i--,mp++)
- X if (mp->update && (mp->update < scantime))
- X {
- X mp->now.rcvb = 0;
- X mp->now.sndb = 0;
- X *mp->cnam = '\0';
- X }
- X}
- X
- X/*
- X** sort table on bytes received
- X*/
- Xsortm(p1, p2)
- Xregister MType *p1, *p2;
- X{
- X return (p2->now.rcvb - p1->now.rcvb);
- X}
- X
- Xshowstats(remserver, scantime)
- Xchar *remserver;
- Xlong scantime;
- X{
- X register MType *mp;
- X int i, show;
- X long now = time(0);
- X char *s;
- X
- X if ((show = entries) > LINES - 3)
- X show = LINES - 3;
- X
- X removeold(scantime);
- X qsort(msgtab, sizeof(msgtab)/sizeof(MType), sizeof(MType), sortm);
- X move(0,0);
- X refresh();
- X mvcur(LINES-1,COLS-1,0,0);
- X refresh();
- X printw("%s %d %s", remserver, port, ctime(&now));
- X printw("Connection SendQ SendM SendB \
- X RecvM RecvB\n");
- X printw("------------------------- ------ --------- -----------\
- X --------- -----------\n");
- X
- X mp = msgtab;
- X for (i = COLS - 3; i; i--, mp++)
- X {
- X if (!*mp->cnam)
- X clrtoeol();
- X else
- X {
- X printw("%-25.25s %6d %9d %11d ", mp->cnam,
- X mp->now.sndq, mp->now.sndm - mp->old.sndm,
- X mp->now.sndb - mp->old.sndb);
- X printw("%9d %11d\n", mp->now.rcvm - mp->old.rcvm,
- X mp->now.rcvb - mp->old.rcvb);
- X }
- X }
- X refresh();
- X mvcur(LINES-1,COLS-1,0,0);
- X refresh();
- X}
- X
- X
- Xmovemem(s,t,l)
- Xregister char *s, *t;
- Xregister int l;
- X{
- X for (; l >= 0; l--, s++, t++) *t = *s;
- X}
- X
- Xint stlen(s)
- Xregister char *s;
- X{
- X register int i = 0;
- X
- X for (; *s; s++, i++)
- X ;
- X return i;
- X}
- X
- X/*
- X** open 1 log file for each report: bytes in and out, messages in and out
- X*/
- Xopenlogs(server)
- Xchar *server;
- X{
- X char name[50], *s, logname[70];
- X
- X if (s = (char *)index(server, '.'))
- X {
- X *s = '\0';
- X strncpy(name, server, sizeof(name)-1);
- X name[sizeof(name)-1] = '\0';
- X *s = '.';
- X }
- X else
- X {
- X strncpy(name, server, sizeof(name)-1);
- X name[sizeof(name)-1] = '\0';
- X }
- X sprintf(logname, "%s.b-out", name);
- X truncate(logname, 0);
- X if ((logfd[0] = open(logname, O_WRONLY|O_CREAT,0600)) == -1)
- X logopen_error();
- X sprintf(logname, "%s.m-out", name);
- X truncate(logname, 0);
- X if((logfd[1] = open(logname, O_WRONLY|O_CREAT,0600)) == -1)
- X logopen_error();
- X sprintf(logname, "%s.b-in", name);
- X truncate(logname, 0);
- X if((logfd[2] = open(logname, O_WRONLY|O_CREAT,0600)) == -1)
- X logopen_error();
- X sprintf(logname, "%s.m-in", name);
- X truncate(logname, 0);
- X if((logfd[3] = open(logname, O_WRONLY|O_CREAT,0600)) == -1)
- X logopen_error();
- X}
- X
- Xlogopen_error()
- X{
- X perror("open");
- X exit(-1);
- X}
- X
- Xcloselogs()
- X{
- X int i;
- X
- X for (i = 0; i < 4; i++)
- X close(logfd[i]);
- X}
- END-of-stat/flowmon.c
- echo x - stat/genplot
- sed 's/^X//' >stat/genplot << 'END-of-stat/genplot'
- X#!/usr/bin/perl
- X
- X$sccsid = "@(#)genplot 1.1 12/17/92 (C)1992 Darren Reed";
- X
- Xprint "Generate plot for which server ? ";
- X$server=<STDIN>;
- Xchop($server);
- Xif ($server =~ /[^\.]*\./) {
- X $server =~ s/([^\.]*).*/$1/;
- X}
- X
- X
- Xopen(PLT,">$server.plt") || die $!;
- Xopen(WC,"wc -l $server.b-in|") || die $!;
- X$txt = <WC>;
- X@s = split(' ',$txt);
- X$lines = @s[0];
- Xclose(WC);
- Xprint "$lines samples.\n";
- X
- Xprint PLT "set samples $lines\n";
- Xprint PLT "set autoscale y; set grid; set border\n";
- Xprint PLT "set xrange[0:$lines]\n";
- Xprint PLT "set xlabel \"Time\"\n";
- Xprint PLT "plot [0:$lines] '$server.b-in' w lines, '$server.b-out' w lines\n";
- Xprint PLT "pause -1\n";
- Xprint PLT "plot [0:$lines] '$server.m-in' w lines, '$server.m-out' w lines\n";
- Xprint PLT "pause -1\n";
- Xclose(PLT);
- Xprint "File for gnuplot: $server.plt\n";
- Xprint "Datafiles: $server.b-in $server.b-out $server.m-in $server.m-out\n";
- X
- END-of-stat/genplot
- echo x - stat/runplot
- sed 's/^X//' >stat/runplot << 'END-of-stat/runplot'
- X#!/usr/bin/perl
- X$sccsid = "@(#)runplot 1.2 12/18/92 (C)1992 Darren Reed";
- X
- Xsub ReadName {
- X $_ = <>;
- X chop;
- X if (length < 1) {
- X exit(0);
- X }
- X return $_;
- X}
- X
- X
- Xprint "\nIRC Traffic Monitor\n-------------------\n";
- Xprint "Server to connect monitor to > ";
- X$server = &ReadName();
- Xprint "Server to gather stats on > ";
- X$remserver = &ReadName();
- Xprint "Nick for monitor to use > ";
- X$nick = &ReadName();
- Xprint "Number of samples to collect > ";
- X$samples = &ReadName();
- Xprint "Interval between samples (eg 1s or 1, 2m, 1h) > ";
- X$_ = &ReadName();
- X
- Xif (/[1-9]*m$/) {
- X chop;
- X $interval = $_ * 60;
- X} elsif (/[1-9]*h$/) {
- X chop;
- X $interval = $_ * 3600;
- X} elsif (/[1-9]*$/) {
- X $interval = $_;
- X} elsif ($intv =~ /[1-9]*s$/) {
- X chop;
- X $interval = $_;
- X} else {
- X print "Unkown quantity \"$_\"\n";
- X exit(-1);
- X}
- X
- Xprint "Server : $server\nTarget Server: $remserver\n";
- Xprint "Nick : $nick\nNo. of samples : $samples\n";
- Xprint "Interval : $interval\n";
- Xprint "\nOk ? (y/N) ";
- X
- X$_ = &ReadName();
- X
- Xif (/^y|^Y/) {
- X system("flowmon -dlsrnwz $server $remserver $nick $interval $samples");
- X print "Monitoring started.\n";
- X print "Come back later and run \"genplot\" to generate gnuplot file\n";
- X}
- END-of-stat/runplot
- exit
-
-