// -*- 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 * * 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 #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 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& 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 { 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& 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>> tail_by_channel; uint64_t seq = 0; ceph::unordered_set keys; // ---- quincy+ ---- LRUSet recent_keys; std::map> channel_info; // channel -> [begin, end) LogSummary() : version(0) {} void build_ordered_tail_legacy(std::list *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& 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 : fmt::formatter { template auto format(const EntityName& e, FormatContext& ctx) { return formatter::format(e.to_str(), ctx); } }; template <> struct fmt::formatter : fmt::formatter { template 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