implement log parser

This commit is contained in:
Fabian Posch 2025-01-03 12:52:34 +01:00
parent d4667506dd
commit 5b3b3b9810
2 changed files with 187 additions and 1 deletions

View file

@ -27,6 +27,7 @@
#define __LOG_PARSER__
#include <cluster/artifact.hpp>
#include <vector>
#include "agent_artifact.hpp"
class LogParser {
@ -38,13 +39,31 @@ class LogParser {
void parse_log(const std::string& line);
void parse_error(const std::string& line);
void finalize();
bool check_busy_deadlock();
private:
using log_it_t = std::vector<std::string>::const_iterator;
bool compare_logs(log_it_t& iterator, const std::string& line);
void check_token_count(const std::string& line);
void check_value_fault(const std::string& line);
void check_coding_fault(const std::string& line);
std::unique_ptr<DBSimOutputArtifact>& artifact;
std::shared_ptr<pl::SimOutputArtifact> reference;
bool has_reference;
log_it_t log_it;
log_it_t err_it;
bool logs_diverge = false;
bool err_diverge = false;
int dut_output_tokens_ = 0;
int output_token_difference_ = 0;
};
#endif

View file

@ -23,11 +23,18 @@
**************************************************************************
*/
#include <iostream>
#include <string>
#define DEBUG
#include "util.h"
#include "log_parser.hpp"
LogParser::LogParser(std::unique_ptr<DBSimOutputArtifact>& artifact, std::shared_ptr<pl::SimOutputArtifact> reference) : artifact(artifact) {
this->reference = reference;
this->has_reference = true;
this->log_it = reference->get_content().first.begin();
this->err_it = reference->get_content().second.begin();
}
LogParser::LogParser(std::unique_ptr<DBSimOutputArtifact>& artifact) : artifact(artifact) {
@ -35,9 +42,169 @@ LogParser::LogParser(std::unique_ptr<DBSimOutputArtifact>& artifact) : artifact(
};
void LogParser::parse_log(const std::string& line) {
// check for output tokens
check_token_count(line);
// check for excl high constraint violations
check_coding_fault(line);
// check for value fault
check_value_fault(line);
// if there is no reference, just add the log line and return
if (!this->has_reference || logs_diverge) {
this->artifact->add_log_output(line);
return;
}
// if logs are the same, there is nothing to do
if (compare_logs(log_it, line)) {
return;
}
// check for glitch
// the logs have diverged
logs_diverge = true;
this->artifact->add_log_output(line);
}
void LogParser::parse_error(const std::string& line) {
this->artifact->add_err_output(line);
// if there is no reference, just add the log line and return
if (!this->has_reference || err_diverge) {
this->artifact->add_err_output(line);
return;
}
// actsim actually outputs everything on stdout
// Only the warnings in the beginning are on stderr.
// // if logs are the same, there is nothing to do
// if (compare_logs(err_it, line)) {
// return;
// }
// // the logs have diverged
// err_diverge = true;
// this->artifact->add_err_output(line);
}
void LogParser::finalize() {
/*
So the only way to do this cleanly is to make sure that either
- the model has not sent all tokens yet -> deadlock
- or the model has sent everything but there is one missing -> token fault
This has the consequence that we cannot inject close to the end of the test!
This also means that we don't really know if a deadlock occurred without
a reference run to go off.
Only that there was a potential token count difference.
*/
if (has_reference) {
// model has not sent all tokens yet
if ((dut_output_tokens_ + output_token_difference_) < reference->output_tokens) {
// a deadlock must have occured
artifact->set_fault_deadlock(true);
DEBUG_PRINT("Deadlock detected during finalization (compared to reference)");
DEBUG_PRINT("Reference had " +
std::to_string(reference->output_tokens) +
" tokens, task had " +
std::to_string(dut_output_tokens_) +
" + " + std::to_string(output_token_difference_));
// model has sent all tokens but DUT has not sent all of them
} else if (output_token_difference_ != 0) {
// a token amount error has occurred
artifact->set_fault_token_count(true);
DEBUG_PRINT("Token count mismatch detected during finalization (compared to reference)");
}
} else {
// if token difference != 0: token count error
if (output_token_difference_ != 0) {
artifact->set_fault_token_count(true);
artifact->set_output_tokens(dut_output_tokens_);
DEBUG_PRINT("Token count mismatch detected during finalization.");
}
}
}
inline void LogParser::check_token_count(const std::string& line) {
// difference counter should be back at 0 when log is finished
// -> both model and DUT have emitted the same number of tokens
const std::string model_token = "Model response received";
const std::string dut_token = "DUT response received";
if (line.find(model_token) != std::string::npos) {
++output_token_difference_;
}
if (line.find(dut_token) != std::string::npos) {
--output_token_difference_;
++dut_output_tokens_;
}
}
inline void LogParser::check_value_fault(const std::string& line) {
// simply check if the standard test failed output
// is given by the scoreboard
const std::string test_failed = "TEST FAILED";
if (line.find(test_failed) != std::string::npos) {
artifact->set_fault_value(true);
DEBUG_PRINT("Value error detected");
}
}
void LogParser::check_coding_fault(const std::string& line) {
// check for actsim's excl-hi warning
const std::string excl_hi_violated = "WARNING: excl-hi constraint in";
if (line.find(excl_hi_violated) != std::string::npos) {
artifact->set_fault_coding(true);
DEBUG_PRINT("Excl-hi constraint violated");
}
}
bool LogParser::check_busy_deadlock() {
// we allow for more than 3x the events to happen compared
// to the reference run, then we assume a deadlock
// if there is no reference, we have nothing to do
if (!has_reference) {
return false;
}
if (artifact->get_size() > (reference->get_size() * 3)) {
return true;
DEBUG_PRINT("Busy deadlock detected");
}
return false;
}
bool LogParser::compare_logs([[maybe_unused]]log_it_t& it, [[maybe_unused]]const std::string& line) {
return false;
}