diff options
Diffstat (limited to '')
-rw-r--r-- | src/common/LogEntry.h | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/common/LogEntry.h b/src/common/LogEntry.h new file mode 100644 index 000000000..3ddebbd30 --- /dev/null +++ b/src/common/LogEntry.h @@ -0,0 +1,212 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net> + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef CEPH_LOGENTRY_H +#define CEPH_LOGENTRY_H + +#include <fmt/format.h> + +#include "include/utime.h" +#include "msg/msg_fmt.h" +#include "msg/msg_types.h" +#include "common/entity_name.h" +#include "ostream_temp.h" +#include "LRUSet.h" + +namespace ceph { + class Formatter; +} + +static const std::string CLOG_CHANNEL_NONE = "none"; +static const std::string CLOG_CHANNEL_DEFAULT = "cluster"; +static const std::string CLOG_CHANNEL_CLUSTER = "cluster"; +static const std::string CLOG_CHANNEL_AUDIT = "audit"; + +// this is the key name used in the config options for the default, e.g. +// default=true foo=false bar=false +static const std::string CLOG_CONFIG_DEFAULT_KEY = "default"; + +/* + * Given a clog log_type, return the equivalent syslog priority + */ +int clog_type_to_syslog_level(clog_type t); + +clog_type string_to_clog_type(const std::string& s); +int string_to_syslog_level(std::string s); +int string_to_syslog_facility(std::string s); + +std::string clog_type_to_string(clog_type t); + + +struct LogEntryKey { +private: + uint64_t _hash = 0; + + void _calc_hash() { + std::hash<entity_name_t> h; + _hash = seq + h(rank); + } + + entity_name_t rank; + utime_t stamp; + uint64_t seq = 0; + +public: + LogEntryKey() {} + LogEntryKey(const entity_name_t& w, utime_t t, uint64_t s) + : rank(w), stamp(t), seq(s) { + _calc_hash(); + } + + uint64_t get_hash() const { + return _hash; + } + + void dump(ceph::Formatter *f) const; + static void generate_test_instances(std::list<LogEntryKey*>& o); + + friend bool operator==(const LogEntryKey& l, const LogEntryKey& r) { + return l.rank == r.rank && l.stamp == r.stamp && l.seq == r.seq; + } + + void encode(bufferlist& bl) const { + using ceph::encode; + encode(rank, bl); + encode(stamp, bl); + encode(seq, bl); + } + void decode(bufferlist::const_iterator &p) { + using ceph::decode; + decode(rank, p); + decode(stamp, p); + decode(seq, p); + } +}; +WRITE_CLASS_ENCODER(LogEntryKey) + + +namespace std { +template<> struct hash<LogEntryKey> { + size_t operator()(const LogEntryKey& r) const { + return r.get_hash(); + } +}; +} // namespace std + +struct LogEntry { + EntityName name; + entity_name_t rank; + entity_addrvec_t addrs; + utime_t stamp; + uint64_t seq; + clog_type prio; + std::string msg; + std::string channel; + + LogEntry() : seq(0), prio(CLOG_DEBUG) {} + + LogEntryKey key() const { return LogEntryKey(rank, stamp, seq); } + + void log_to_syslog(std::string level, std::string facility) const; + + void encode(ceph::buffer::list& bl, uint64_t features) const; + void decode(ceph::buffer::list::const_iterator& bl); + void dump(ceph::Formatter *f) const; + static void generate_test_instances(std::list<LogEntry*>& o); + static clog_type str_to_level(std::string const &str); +}; +WRITE_CLASS_ENCODER_FEATURES(LogEntry) + +struct LogSummary { + version_t version; + + // ---- pre-quincy ---- + // channel -> [(seq#, entry), ...] + std::map<std::string,std::list<std::pair<uint64_t,LogEntry>>> tail_by_channel; + uint64_t seq = 0; + ceph::unordered_set<LogEntryKey> keys; + + // ---- quincy+ ---- + LRUSet<LogEntryKey> recent_keys; + std::map<std::string, std::pair<uint64_t,uint64_t>> channel_info; // channel -> [begin, end) + + LogSummary() : version(0) {} + + void build_ordered_tail_legacy(std::list<LogEntry> *tail) const; + + void add_legacy(const LogEntry& e) { + keys.insert(e.key()); + tail_by_channel[e.channel].push_back(std::make_pair(++seq, e)); + } + void prune(size_t max) { + for (auto& i : tail_by_channel) { + while (i.second.size() > max) { + keys.erase(i.second.front().second.key()); + i.second.pop_front(); + } + } + recent_keys.prune(max); + } + bool contains(const LogEntryKey& k) const { + return keys.count(k) || recent_keys.contains(k); + } + + void encode(ceph::buffer::list& bl, uint64_t features) const; + void decode(ceph::buffer::list::const_iterator& bl); + void dump(ceph::Formatter *f) const; + static void generate_test_instances(std::list<LogSummary*>& o); +}; +WRITE_CLASS_ENCODER_FEATURES(LogSummary) + +inline std::ostream& operator<<(std::ostream& out, const clog_type t) +{ + switch (t) { + case CLOG_DEBUG: + return out << "[DBG]"; + case CLOG_INFO: + return out << "[INF]"; + case CLOG_SEC: + return out << "[SEC]"; + case CLOG_WARN: + return out << "[WRN]"; + case CLOG_ERROR: + return out << "[ERR]"; + default: + return out << "[???]"; + } +} + +inline std::ostream& operator<<(std::ostream& out, const LogEntry& e) +{ + return out << e.stamp << " " << e.name << " (" << e.rank << ") " + << e.seq << " : " + << e.channel << " " << e.prio << " " << e.msg; +} + +template <> struct fmt::formatter<EntityName> : fmt::formatter<std::string_view> { + template <typename FormatContext> + auto format(const EntityName& e, FormatContext& ctx) { + return formatter<std::string_view>::format(e.to_str(), ctx); + } +}; + +template <> struct fmt::formatter<LogEntry> : fmt::formatter<std::string_view> { + template <typename FormatContext> + auto format(const LogEntry& e, FormatContext& ctx) { + return fmt::format_to(ctx.out(), "{} {} ({}) {} : {} {} {}", + e.stamp, e.name, e.rank, e.seq, e.channel, e.prio, e.msg); + } +}; + +#endif |