// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab // #include #include #include "LogEntry.h" #include "Formatter.h" #include "include/stringify.h" using std::list; using std::map; using std::make_pair; using std::pair; using std::string; using ceph::bufferlist; using ceph::decode; using ceph::encode; using ceph::Formatter; // ---- // LogEntryKey void LogEntryKey::dump(Formatter *f) const { f->dump_stream("rank") << rank; f->dump_stream("stamp") << stamp; f->dump_unsigned("seq", seq); } void LogEntryKey::generate_test_instances(list& o) { o.push_back(new LogEntryKey); o.push_back(new LogEntryKey(entity_name_t::CLIENT(1234), utime_t(1,2), 34)); } clog_type LogEntry::str_to_level(std::string const &str) { std::string level_str = str; std::transform(level_str.begin(), level_str.end(), level_str.begin(), [](char c) {return std::tolower(c);}); if (level_str == "debug") { return CLOG_DEBUG; } else if (level_str == "info") { return CLOG_INFO; } else if (level_str == "sec") { return CLOG_SEC; } else if (level_str == "warn" || level_str == "warning") { return CLOG_WARN; } else if (level_str == "error" || level_str == "err") { return CLOG_ERROR; } else { return CLOG_UNKNOWN; } } // ---- int clog_type_to_syslog_level(clog_type t) { switch (t) { case CLOG_DEBUG: return LOG_DEBUG; case CLOG_INFO: return LOG_INFO; case CLOG_WARN: return LOG_WARNING; case CLOG_ERROR: return LOG_ERR; case CLOG_SEC: return LOG_CRIT; default: ceph_abort(); return 0; } } clog_type string_to_clog_type(const string& s) { if (boost::iequals(s, "debug") || boost::iequals(s, "dbg")) return CLOG_DEBUG; if (boost::iequals(s, "info") || boost::iequals(s, "inf")) return CLOG_INFO; if (boost::iequals(s, "warning") || boost::iequals(s, "warn") || boost::iequals(s, "wrn")) return CLOG_WARN; if (boost::iequals(s, "error") || boost::iequals(s, "err")) return CLOG_ERROR; if (boost::iequals(s, "security") || boost::iequals(s, "sec")) return CLOG_SEC; return CLOG_UNKNOWN; } int string_to_syslog_level(string s) { if (boost::iequals(s, "debug")) return LOG_DEBUG; if (boost::iequals(s, "info") || boost::iequals(s, "notice")) return LOG_INFO; if (boost::iequals(s, "warning") || boost::iequals(s, "warn")) return LOG_WARNING; if (boost::iequals(s, "error") || boost::iequals(s, "err")) return LOG_ERR; if (boost::iequals(s, "crit") || boost::iequals(s, "critical") || boost::iequals(s, "emerg")) return LOG_CRIT; // err on the side of noise! return LOG_DEBUG; } int string_to_syslog_facility(string s) { if (boost::iequals(s, "auth")) return LOG_AUTH; if (boost::iequals(s, "authpriv")) return LOG_AUTHPRIV; if (boost::iequals(s, "cron")) return LOG_CRON; if (boost::iequals(s, "daemon")) return LOG_DAEMON; if (boost::iequals(s, "ftp")) return LOG_FTP; if (boost::iequals(s, "kern")) return LOG_KERN; if (boost::iequals(s, "local0")) return LOG_LOCAL0; if (boost::iequals(s, "local1")) return LOG_LOCAL1; if (boost::iequals(s, "local2")) return LOG_LOCAL2; if (boost::iequals(s, "local3")) return LOG_LOCAL3; if (boost::iequals(s, "local4")) return LOG_LOCAL4; if (boost::iequals(s, "local5")) return LOG_LOCAL5; if (boost::iequals(s, "local6")) return LOG_LOCAL6; if (boost::iequals(s, "local7")) return LOG_LOCAL7; if (boost::iequals(s, "lpr")) return LOG_LPR; if (boost::iequals(s, "mail")) return LOG_MAIL; if (boost::iequals(s, "news")) return LOG_NEWS; if (boost::iequals(s, "syslog")) return LOG_SYSLOG; if (boost::iequals(s, "user")) return LOG_USER; if (boost::iequals(s, "uucp")) return LOG_UUCP; // default to USER return LOG_USER; } string clog_type_to_string(clog_type t) { switch (t) { case CLOG_DEBUG: return "debug"; case CLOG_INFO: return "info"; case CLOG_WARN: return "warn"; case CLOG_ERROR: return "err"; case CLOG_SEC: return "crit"; default: ceph_abort(); return 0; } } void LogEntry::log_to_syslog(string level, string facility) const { int min = string_to_syslog_level(level); int l = clog_type_to_syslog_level(prio); if (l <= min) { int f = string_to_syslog_facility(facility); syslog(l | f, "%s %s %llu : %s", name.to_cstr(), stringify(rank).c_str(), (long long unsigned)seq, msg.c_str()); } } void LogEntry::encode(bufferlist& bl, uint64_t features) const { assert(HAVE_FEATURE(features, SERVER_NAUTILUS)); ENCODE_START(5, 5, bl); __u16 t = prio; encode(name, bl); encode(rank, bl); encode(addrs, bl, features); encode(stamp, bl); encode(seq, bl); encode(t, bl); encode(msg, bl); encode(channel, bl); ENCODE_FINISH(bl); } void LogEntry::decode(bufferlist::const_iterator& bl) { DECODE_START_LEGACY_COMPAT_LEN(5, 2, 2, bl); if (struct_v < 5) { __u16 t; entity_inst_t who; decode(who, bl); rank = who.name; addrs.v.clear(); addrs.v.push_back(who.addr); decode(stamp, bl); decode(seq, bl); decode(t, bl); prio = (clog_type)t; decode(msg, bl); if (struct_v >= 3) { decode(channel, bl); } else { // prior to having logging channels we only had a cluster log. // Ensure we keep that appearance when the other party has no // clue of what a 'channel' is. channel = CLOG_CHANNEL_CLUSTER; } if (struct_v >= 4) { decode(name, bl); } } else { __u16 t; decode(name, bl); decode(rank, bl); decode(addrs, bl); decode(stamp, bl); decode(seq, bl); decode(t, bl); prio = (clog_type)t; decode(msg, bl); decode(channel, bl); } DECODE_FINISH(bl); } void LogEntry::dump(Formatter *f) const { f->dump_stream("name") << name; f->dump_stream("rank") << rank; f->dump_object("addrs", addrs); f->dump_stream("stamp") << stamp; f->dump_unsigned("seq", seq); f->dump_string("channel", channel); f->dump_stream("priority") << prio; f->dump_string("message", msg); } void LogEntry::generate_test_instances(list& o) { o.push_back(new LogEntry); } // ----- void LogSummary::build_ordered_tail_legacy(list *tail) const { tail->clear(); // channel -> (begin, end) map>::const_iterator, list>::const_iterator>> pos; for (auto& i : tail_by_channel) { pos.emplace(i.first, make_pair(i.second.begin(), i.second.end())); } while (true) { uint64_t min_seq = 0; list>::const_iterator *minp = 0; for (auto& i : pos) { if (i.second.first == i.second.second) { continue; } if (min_seq == 0 || i.second.first->first < min_seq) { min_seq = i.second.first->first; minp = &i.second.first; } } if (min_seq == 0) { break; // done } tail->push_back((*minp)->second); ++(*minp); } } void LogSummary::encode(bufferlist& bl, uint64_t features) const { assert(HAVE_FEATURE(features, SERVER_MIMIC)); ENCODE_START(4, 3, bl); encode(version, bl); encode(seq, bl); encode(tail_by_channel, bl, features); encode(channel_info, bl); recent_keys.encode(bl); ENCODE_FINISH(bl); } void LogSummary::decode(bufferlist::const_iterator& bl) { DECODE_START_LEGACY_COMPAT_LEN(4, 2, 2, bl); decode(version, bl); decode(seq, bl); decode(tail_by_channel, bl); if (struct_v >= 4) { decode(channel_info, bl); recent_keys.decode(bl); } DECODE_FINISH(bl); keys.clear(); for (auto& i : tail_by_channel) { for (auto& e : i.second) { keys.insert(e.second.key()); } } } void LogSummary::dump(Formatter *f) const { f->dump_unsigned("version", version); f->open_object_section("tail_by_channel"); for (auto& i : tail_by_channel) { f->open_object_section(i.first.c_str()); for (auto& j : i.second) { string s = stringify(j.first); f->dump_object(s.c_str(), j.second); } f->close_section(); } f->close_section(); } void LogSummary::generate_test_instances(list& o) { o.push_back(new LogSummary); // more! }