Rate individual error log entries for error severity.

This commit is contained in:
Alexander Shaduri
2017-09-05 14:53:47 +00:00
parent 22971e8567
commit 73fec7fa3f
5 changed files with 81 additions and 53 deletions
+3 -3
View File
@@ -32,6 +32,8 @@ Add ability (through ctrl-C?) to copy selected rows from attributes and statisti
Add menu item - "update drive database"
Run it in terminal in Linux for verbosity.
xterm -hold -e 'update-smart-drivedb'
require xterm in rpm/deb deps.
Testing:
@@ -40,11 +42,9 @@ Testing:
Detect running tests on launch (maybe ask the user too? some tests
may be stuck due to bad firmware, e.g. 3ware/windows).
Parse "==> WARNING"
Per-line selftest error highlighting.
Tab highlighting according to error severity.
Parse all test data.
+45 -16
View File
@@ -76,22 +76,23 @@ std::ostream& operator<<(std::ostream& os, const StorageStatistic& p)
std::string StorageErrorBlock::get_readable_error_types(const std::vector<std::string>& types)
{
std::map<std::string, std::string> m;
m["ABRT"] = "Command aborted";
m["AMNF"] = "Address mark not found";
m["CCTO"] = "Command completion timed out";
m["EOM"] = "End of media";
m["ICRC"] = "Interface CRC error";
m["IDNF"] = "Identity not found";
m["ILI"] = "(Packet command-set specific)";
m["MC"] = "Media changed";
m["MCR"] = "Media change request";
m["NM"] = "No media";
m["obs"] = "Obsolete";
m["TK0NF"] = "Track 0 not found";
m["UNC"] = "Uncorrectable error in data";
m["WP"] = "Media is write protected";
static std::map<std::string, std::string> m;
if (m.empty()) {
m["ABRT"] = "Command aborted";
m["AMNF"] = "Address mark not found";
m["CCTO"] = "Command completion timed out";
m["EOM"] = "End of media";
m["ICRC"] = "Interface CRC error";
m["IDNF"] = "Identity not found";
m["ILI"] = "(Packet command-set specific)";
m["MC"] = "Media changed";
m["MCR"] = "Media change request";
m["NM"] = "No media";
m["obs"] = "Obsolete";
m["TK0NF"] = "Track 0 not found";
m["UNC"] = "Uncorrectable error in data";
m["WP"] = "Media is write protected";
}
std::vector<std::string> sv;
for (std::vector<std::string>::const_iterator iter = types.begin(); iter != types.end(); ++iter) {
@@ -107,6 +108,34 @@ std::string StorageErrorBlock::get_readable_error_types(const std::vector<std::s
int StorageErrorBlock::get_warning_level_for_error_type(std::string& type)
{
static std::map<std::string, StorageProperty::warning_t> m;
if (m.empty()) {
m["ABRT"] = StorageProperty::warning_none;
m["AMNF"] = StorageProperty::warning_alert;
m["CCTO"] = StorageProperty::warning_warn;
m["EOM"] = StorageProperty::warning_warn;
m["ICRC"] = StorageProperty::warning_warn;
m["IDNF"] = StorageProperty::warning_alert;
m["ILI"] = StorageProperty::warning_notice;
m["MC"] = StorageProperty::warning_none;
m["MCR"] = StorageProperty::warning_none;
m["NM"] = StorageProperty::warning_none;
m["obs"] = StorageProperty::warning_none;
m["TK0NF"] = StorageProperty::warning_alert;
m["UNC"] = StorageProperty::warning_alert;
m["WP"] = StorageProperty::warning_none;
}
if (m.find(type) != m.end()) {
return int(m[type]);
}
return StorageProperty::warning_none; // unknown error
}
std::string StorageErrorBlock::format_lifetime_hours() const
{
std::stringstream ss;
@@ -188,6 +188,9 @@ class StorageErrorBlock {
/// Get readable error types from reported types
static std::string get_readable_error_types(const std::vector<std::string>& types);
/// Get warning level (warning_t) for an error type
static int get_warning_level_for_error_type(std::string& type);
/// Format lifetime hours with comma
std::string format_lifetime_hours() const;
@@ -1615,6 +1615,13 @@ bool storage_property_autoset_description(StorageProperty& p, StorageAttribute::
found = auto_set(p, "error_log_error_count", "Number of errors in error log. Note: Some manufacturers may list completely harmless errors in this log "
"(e.g., command invalid, not implemented, etc...).");
// || auto_set(p, "error_log_unsupported", "This device does not support error logging."); // the property text already says that
if (p.value_type == StorageProperty::value_type_error_block) {
for (size_t i = 0; i < p.value_error_block.reported_types.size(); ++i) {
p.set_description(StorageErrorBlock::get_readable_error_types(p.value_error_block.reported_types));
found = true;
}
}
break;
case StorageProperty::subsection_selftest_log:
@@ -1851,7 +1858,7 @@ StorageProperty::warning_t storage_property_autoset_warning(StorageProperty& p)
// the tooltips.
if (name_match(p, "error_log_error_count") && p.value_integer > 0) {
w = StorageProperty::warning_warn;
w = StorageProperty::warning_notice;
reason = "The drive is reporting internal errors. Usually this means uncorrectable data loss and similar severe errors. "
"Check the actual errors for details.";
@@ -1860,7 +1867,20 @@ StorageProperty::warning_t storage_property_autoset_warning(StorageProperty& p)
reason = "The drive does not support error logging. This means that SMART error history is unavailable.";
}
// TODO Rate individual error log entries.
// Rate individual error log entries.
if (!p.value_error_block.reported_types.empty()) {
StorageProperty::warning_t error_block_warning = StorageProperty::warning_none;
for (size_t i = 0; i < p.value_error_block.reported_types.size(); ++i) {
int individual_warning = StorageErrorBlock::get_warning_level_for_error_type(p.value_error_block.reported_types[i]);
if (individual_warning > int(error_block_warning)) {
error_block_warning = StorageProperty::warning_t(individual_warning);
}
}
if (int(error_block_warning) > int(StorageProperty::warning_none)) {
w = error_block_warning;
reason = "The drive is reporting internal errors. Your data may be at risk depending on error severity.";
}
}
break;
+8 -32
View File
@@ -108,32 +108,8 @@ namespace {
/// Cell renderer functions for attribute cells
inline void app_attr_cell_renderer_func(Gtk::CellRenderer* cr, const Gtk::TreeModel::iterator& iter,
Gtk::TreeModelColumn<const StorageProperty*> storage_column)
{
const StorageProperty* p = (*iter)[storage_column];
Gtk::CellRendererText* crt = hz::down_cast<Gtk::CellRendererText*>(cr);
if (crt) {
std::string fg, bg;
if (app_property_get_row_highlight_colors(p->warning, fg, bg)) {
// Note: property_cell_background makes horizontal tree lines disappear around it,
// but property_background doesn't play nice with sorted column color.
crt->property_cell_background() = bg;
crt->property_foreground() = fg;
} else {
// this is needed because cellrenderer is shared in column, so the previous call
// may set the color for all subsequent cells.
crt->property_cell_background().reset_value();
crt->property_foreground().reset_value();
}
}
}
/// Cell renderer functions for attribute cells
inline void app_statistic_cell_renderer_func(Gtk::CellRenderer* cr, const Gtk::TreeModel::iterator& iter,
/// Cell renderer functions for list cells
inline void app_list_cell_renderer_func(Gtk::CellRenderer* cr, const Gtk::TreeModel::iterator& iter,
Gtk::TreeModelColumn<const StorageProperty*> storage_column)
{
const StorageProperty* p = (*iter)[storage_column];
@@ -667,7 +643,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
for (unsigned int i = 0; i < num_tree_cols; ++i) {
Gtk::TreeViewColumn* tcol = treeview->get_column(i);
tcol->set_cell_data_func(*(tcol->get_first_cell()),
sigc::bind(sigc::ptr_fun(app_attr_cell_renderer_func), col_storage));
sigc::bind(sigc::ptr_fun(app_list_cell_renderer_func), col_storage));
}
@@ -783,7 +759,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
for (unsigned int i = 0; i < num_tree_cols; ++i) {
Gtk::TreeViewColumn* tcol = treeview->get_column(i);
tcol->set_cell_data_func(*(tcol->get_first_cell()),
sigc::bind(sigc::ptr_fun(app_statistic_cell_renderer_func), col_storage));
sigc::bind(sigc::ptr_fun(app_list_cell_renderer_func), col_storage));
}
@@ -988,7 +964,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
for (unsigned int i = 0; i < num_tree_cols; ++i) {
Gtk::TreeViewColumn* tcol = treeview->get_column(i);
tcol->set_cell_data_func(*(tcol->get_first_cell()),
sigc::bind(sigc::ptr_fun(app_attr_cell_renderer_func), col_storage));
sigc::bind(sigc::ptr_fun(app_list_cell_renderer_func), col_storage));
}
@@ -1099,7 +1075,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
for (unsigned int i = 0; i < num_tree_cols; ++i) {
Gtk::TreeViewColumn* tcol = treeview->get_column(i);
tcol->set_cell_data_func(*(tcol->get_first_cell()),
sigc::bind(sigc::ptr_fun(app_attr_cell_renderer_func), col_storage));
sigc::bind(sigc::ptr_fun(app_list_cell_renderer_func), col_storage));
}
@@ -1157,7 +1133,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
row[col_details] = (type_details.empty() ? "-" : type_details); // e.g. OBS has no details
// There are no descriptions in self-test log entries, so don't display
// "No description available" for all of them.
// row[col_tooltip] = iter->get_description();
row[col_tooltip] = iter->get_description();
row[col_storage] = &(*iter);
row[col_mark_name] = "Error " + hz::number_to_string(iter->value_error_block.error_num);
}
@@ -1309,7 +1285,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
for (unsigned int i = 0; i < num_tree_cols; ++i) {
Gtk::TreeViewColumn* tcol = treeview->get_column(i);
tcol->set_cell_data_func(*(tcol->get_first_cell()),
sigc::bind(sigc::ptr_fun(app_attr_cell_renderer_func), col_storage));
sigc::bind(sigc::ptr_fun(app_list_cell_renderer_func), col_storage));
}