/* Analyse the logs produces by blackhole and conproxy to extract connection statitics /var/log/blackhole-connect.log contains all the information about new connections /var/log/conproxy-connect.log contants the stats at the end of the connection */ #include #include #include #include #include #include #include "boost/date_time/gregorian/gregorian.hpp" using namespace std; using namespace boost::gregorian; struct FROM { string server; string vserver; string target; string port; bool operator < (const FROM &c) const { bool ret = false; int cmp = strcmp(server.c_str(),c.server.c_str()); if (cmp < 0){ ret = true; }else if (cmp == 0){ cmp = strcmp(vserver.c_str(),c.vserver.c_str()); if (cmp < 0){ ret = true; }else if (cmp == 0){ cmp = strcmp(target.c_str(),c.target.c_str()); if (cmp < 0){ ret = true; }else if (cmp == 0){ ret = port < c.port; } } } return ret; } }; struct STATS{ long long bytes_in; long long bytes_out; int nbcon; }; struct LOG { string connect_date; string disconnect_date; long long bytes_in, bytes_out; FROM from; struct { string server; string vserver; string port; } to; struct { string source; string target; string port; } req; LOG(){ bytes_in = 0; bytes_out = 0; } }; static unsigned long date_2second (const string &s) { const char *pt = s.c_str(); unsigned year = atoi(pt); unsigned month = atoi(pt+5); unsigned day = atoi(pt+8); date d(year,month,day); unsigned long days = d.julian_day(); unsigned hour = atoi(pt+11); unsigned minu = atoi(pt+14); unsigned secs = atoi(pt+17); //fprintf (stderr,"pt=%s %04d/%02d/%02d-%02d:%02d:%02d\n",pt,year,month,day,hour,minu,secs); return days*(24*60*60)+hour*(60*60)+minu*60+secs; } static int date_diff (const string &end, const string &start) { if (end.size() == 0){ // Happen when the conproxy log lacks some entries return 0; }else{ unsigned long second_end = date_2second(end); unsigned long second_start = date_2second(start); return second_end - second_start; } } int main (int argc, char *argv[]) { glocal int ret = -1; glocal vector conproxy_logs; glocal vector blackhole_logs; glocal bool details = false; glocal.conproxy_logs.push_back("/var/log/conproxy-connect.log"); glocal.blackhole_logs.push_back("/var/log/blackhole-connect.log"); glocal.ret = (argc,argv); setproginfo ("blackhole-logs",VERSION,"Analyse connection logs"); setarg ('b',"blackhole-log","Connection info produced by blackhole",glocal.blackhole_logs,false); setarg ('c',"conproxy-log","Connection statistics produced by conproxy",glocal.conproxy_logs,false); setarg ('d',"details","Do not agregate connections",glocal.details,false); glocal map logs; for (auto &it:glocal.blackhole_logs){ (it,',',12); int logid = atoi(fields[0]); LOG log; log.connect_date = fields[1]; log.from.server = fields[2]; log.from.vserver = fields[3]; log.from.target = fields[4]; log.from.port = fields[5]; log.to.server = fields[6]; log.to.vserver = fields[7]; log.to.port = fields[8]; log.req.source = fields[9]; log.req.target = fields[10]; log.req.port = fields[11]; glocal.logs[logid] = log; //for (int i=0; i<12; i++) printf ("i=%d :%s:\n",i,fields[i]); //exit (-1); return 0; } for (auto &it:glocal.conproxy_logs){ (it,',',4); int logid = atoi(fields[0]); map::iterator it = glocal.logs.find(logid); if (it == glocal.logs.end()){ tlmp_error ("logid %d missing from blackhole_log file(s)\n",logid); }else{ it->second.disconnect_date = fields[1]; long long bytes_in = atoll(fields[2]); long long bytes_out = atoll(fields[3]); it->second.bytes_in = bytes_in; it->second.bytes_out = bytes_out; } return 0; } if (glocal.details){ printf ("%-20s %3s %-12s %-12s %-12s %-12s %-6s %-6s %-12s %-22s %-6s\n" ,"Start","","Bytes-in","Bytes-out","Server","Vserver","Target","Port","Server","Vserver","Port"); printf ("%-20s %3s %-12s %-12s %-12s %-12s %-6s %-6s %-12s %-22s %-6s\n" ,"--------------------","---" ,"------------","------------" ,"------------","------------","------","------" ,"------------","----------------------","------"); for (auto &it:glocal.logs){ LOG &l = it.second; int duration = date_diff (l.disconnect_date,l.connect_date); printf ("%-20s %3d %'12Ld %'12Ld %-12s %-12s %-6s %-6s %-12s %-22s %-6s\n" ,l.connect_date.c_str(),duration ,l.bytes_in,l.bytes_out ,l.from.server.c_str(),l.from.vserver.c_str(),l.from.target.c_str(),l.from.port.c_str() ,l.to.server.c_str(),l.to.vserver.c_str(),l.to.port.c_str() ); } }else{ map stats; for (auto &it:glocal.logs){ map::iterator itt = stats.find(it.second.from); if (itt == stats.end()){ STATS st; st.bytes_in = it.second.bytes_in; st.bytes_out = it.second.bytes_out; st.nbcon = 1; stats[it.second.from] = st; }else{ itt->second.bytes_in += it.second.bytes_in; itt->second.bytes_out += it.second.bytes_out; itt->second.nbcon++; } } printf ("%-12s %-12s %-5s %-12s %-12s %-6s %s\n","Bytes-in","Bytes-out","Nbcon","Server","Target","Port","Vserver/Source"); printf ("%-12s %-12s %-5s %-12s %-12s %-6s %s\n","------------","------------","-----","------------","------------","------","--------------------"); for (auto &it:stats){ printf ("%'12Ld %'12Ld %5d %-12s %-12s %-6s %s\n" ,it.second.bytes_in,it.second.bytes_out,it.second.nbcon ,it.first.server.c_str(),it.first.target.c_str(),it.first.port.c_str(),it.first.vserver.c_str()); } } return 0; return glocal.ret; }