* Attempt to read back the next log statement contained in the BufferFragment, * output the original log message to outputFd, and if applicable, run an * aggregation function on the log message. * * The aggregation function should take in the same arguments as the original * invocation of NANO_LOG. For example, NANO_LOG("The number is %d." num) should * have the function signature of (const
| 1302 | * we reached the end of the file or the file is corrupt. |
| 1303 | */ |
| 1304 | bool |
| 1305 | Log::Decoder::BufferFragment::decompressNextLogStatement(FILE *outputFd, |
| 1306 | uint64_t &logMsgsProcessed, |
| 1307 | LogMessage &logArgs, |
| 1308 | const Checkpoint &checkpoint, |
| 1309 | std::vector<void*>& fmtId2metadata, |
| 1310 | long aggregationFilterId, |
| 1311 | void (*aggregationFn)(const char*, ...)) |
| 1312 | { |
| 1313 | double secondsSinceCheckpoint, nanos = 0.0; |
| 1314 | char timeString[32]; |
| 1315 | |
| 1316 | if (readPos > endOfBuffer || !hasMoreLogs) { |
| 1317 | hasMoreLogs = false; |
| 1318 | return false; |
| 1319 | } |
| 1320 | |
| 1321 | // no need to format the time if we're not going to output |
| 1322 | if (outputFd) { |
| 1323 | // Convert to relative time |
| 1324 | // double timeDiff; |
| 1325 | // if (nextLogTimestamp >= lastTimestamp) |
| 1326 | // timeDiff = 1.0e9*PerfUtils::Cycles::toSeconds( |
| 1327 | // nextLogTimestamp - lastTimestamp, |
| 1328 | // checkpoint.cyclesPerSecond)); |
| 1329 | // else |
| 1330 | // timeDiff = -1.0e9*PerfUtils::Cycles::toSeconds( |
| 1331 | // lastTimestamp - nextLogTimestamp, |
| 1332 | // checkpoint.cyclesPerSecond)); |
| 1333 | // if (logMsgsProcessed == 0) |
| 1334 | // timeDiff = 0; |
| 1335 | // |
| 1336 | // fprintf(outputFd, "%4ld) +%12.2lf ns ", logMsgsProcessed, timeDiff); |
| 1337 | |
| 1338 | // Convert to absolute time |
| 1339 | secondsSinceCheckpoint = PerfUtils::Cycles::toSeconds( |
| 1340 | nextLogTimestamp - checkpoint.rdtsc, |
| 1341 | checkpoint.cyclesPerSecond); |
| 1342 | int64_t wholeSeconds = static_cast<int64_t>(secondsSinceCheckpoint); |
| 1343 | nanos = 1.0e9 * (secondsSinceCheckpoint |
| 1344 | - static_cast<double>(wholeSeconds)); |
| 1345 | std::time_t absTime = wholeSeconds + checkpoint.unixTime; |
| 1346 | std::tm *tm = localtime(&absTime); |
| 1347 | strftime(timeString, sizeof(timeString), "%Y-%m-%d %H:%M:%S", tm); |
| 1348 | } |
| 1349 | |
| 1350 | if (fmtId2metadata.empty() || aggregationFn != nullptr) { |
| 1351 | // Output the context |
| 1352 | struct GeneratedFunctions::LogMetadata meta = |
| 1353 | GeneratedFunctions::logId2Metadata[nextLogId]; |
| 1354 | if (outputFd) { |
| 1355 | fprintf(outputFd,"%s.%09.0lf %s:%u %s[%u]: " |
| 1356 | , timeString |
| 1357 | , nanos |
| 1358 | , meta.fileName |
| 1359 | , meta.lineNumber |
| 1360 | , logLevelNames[meta.logLevel] |
| 1361 | , runtimeId); |