// quick hack to separate one call per callid from a logfile #include #include #include #include #include #include #include #include using namespace std; std::vector explode(const string& s, const string& delim, const bool keep_empty = false); #include #include using namespace std; int main(int argc, char *argv[]) { if (argc<4) { cerr << "usage: " << argv[0] << " " << endl; cerr << " where is the log file to process" << endl; cerr << " the Call-ID to extract" << endl; cerr << " the column of the thread ID in the " "log, starting with 0 (i.e. number of spaces before the thread ID)" << endl; exit(1); } long int log_offset = -1; char* endptr; log_offset = strtoll(argv[3], &endptr, 10); // offset of thread if ((errno == ERANGE && (log_offset == LLONG_MAX || log_offset == LLONG_MIN)) || (errno != 0 && log_offset == 0) || endptr == argv[3] || log_offset<0) { cerr << "invalid thread column ID " << argv[3] << endl; exit(1); } if (log_offset<0) { } ifstream f; string fname = argv[1]; string callid = argv[2]; f.open(argv[1]); if (!f.good()) { cerr << "error opening file " << fname << endl; exit(1); } string app_thread; string ltag; // threadid log map udprecv_log; map appthread_log; while (!f.eof()) { string s; getline(f,s); vector v = explode(s, " "); if (v.size() < (unsigned)log_offset+1) continue; string t = v[log_offset + 0]; // thread string delim; if (v.size() > (unsigned)log_offset + 4) delim = v[log_offset + 4]; // vv or ^^ string ptype; if (v.size() > (unsigned)log_offset + 5) ptype = v[log_offset + 5]; // M or S // cout << "thread " << t << " delim " << delim << " ptype " << ptype << endl; if (delim == "vv") { // block starts if (ptype == "M") { // message received udprecv_log[t] = s+"\n"; // new thread block } else if (ptype == "S") { // app processing #define GET_CALL_IDENT \ string call_ident; \ if (v.size() > (unsigned)log_offset + 6) \ call_ident = v[log_offset + 6]; \ call_ident = call_ident.substr(1, call_ident.length()-2); \ vector ci_parts = explode(call_ident, "|", true); \ string ci_cid = ci_parts[0]; \ string ci_ltag = ci_parts[1]; GET_CALL_IDENT; if (!ci_cid.empty() && ci_cid != callid) continue; // other call appthread_log[t] = s+"\n"; } else { cerr << "unknown ptype " << ptype << " in '" << s << "'" << endl; continue; } } else if (delim == "^^") { // block ends if (ptype == "M") { // message received GET_CALL_IDENT; map::iterator it=udprecv_log.find(t); if ((ci_cid == callid) && (it != udprecv_log.end())) { cout << endl << endl << it->second << s+"\n"; } if (it != udprecv_log.end()) { udprecv_log.erase(it); } } else if (ptype == "S") { // app processing GET_CALL_IDENT; map::iterator it=appthread_log.find(t); if ((ci_cid == callid) && (it != appthread_log.end())) { cout << endl << endl << it->second << s+"\n"; } if (it != appthread_log.end()) { appthread_log.erase(it); } } else { cerr << "unknown ptype " << ptype << " in '" << s << "'" << endl; continue; } } else { map::iterator it=udprecv_log.find(t); if (it != udprecv_log.end()) { it->second+=s+"\n"; continue; } it=appthread_log.find(t); if (it != appthread_log.end()) { it->second+=s+"\n"; continue; } } } } // Explode string by a separator to a vector // see http://stackoverflow.com/questions/236129/c-how-to-split-a-string std::vector explode(const string& s, const string& delim, const bool keep_empty) { vector result; if (delim.empty()) { result.push_back(s); return result; } string::const_iterator substart = s.begin(), subend; while (true) { subend = search(substart, s.end(), delim.begin(), delim.end()); string temp(substart, subend); if (keep_empty || !temp.empty()) { result.push_back(std::move(temp)); } if (subend == s.end()) { break; } substart = subend + delim.size(); } return result; }