diff options
Diffstat (limited to 'third_party/nix/src/libutil/logging.hh')
-rw-r--r-- | third_party/nix/src/libutil/logging.hh | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/third_party/nix/src/libutil/logging.hh b/third_party/nix/src/libutil/logging.hh new file mode 100644 index 000000000000..5df03da74e00 --- /dev/null +++ b/third_party/nix/src/libutil/logging.hh @@ -0,0 +1,172 @@ +#pragma once + +#include "types.hh" + +namespace nix { + +typedef enum { + lvlError = 0, + lvlWarn, + lvlInfo, + lvlTalkative, + lvlChatty, + lvlDebug, + lvlVomit +} Verbosity; + +typedef enum { + actUnknown = 0, + actCopyPath = 100, + actDownload = 101, + actRealise = 102, + actCopyPaths = 103, + actBuilds = 104, + actBuild = 105, + actOptimiseStore = 106, + actVerifyPaths = 107, + actSubstitute = 108, + actQueryPathInfo = 109, + actPostBuildHook = 110, +} ActivityType; + +typedef enum { + resFileLinked = 100, + resBuildLogLine = 101, + resUntrustedPath = 102, + resCorruptedPath = 103, + resSetPhase = 104, + resProgress = 105, + resSetExpected = 106, + resPostBuildLogLine = 107, +} ResultType; + +typedef uint64_t ActivityId; + +class Logger +{ + friend struct Activity; + +public: + + struct Field + { + // FIXME: use std::variant. + enum { tInt = 0, tString = 1 } type; + uint64_t i = 0; + std::string s; + Field(const std::string & s) : type(tString), s(s) { } + Field(const char * s) : type(tString), s(s) { } + Field(const uint64_t & i) : type(tInt), i(i) { } + }; + + typedef std::vector<Field> Fields; + + virtual ~Logger() { } + + virtual void log(Verbosity lvl, const FormatOrString & fs) = 0; + + void log(const FormatOrString & fs) + { + log(lvlInfo, fs); + } + + virtual void warn(const std::string & msg); + + virtual void startActivity(ActivityId act, Verbosity lvl, ActivityType type, + const std::string & s, const Fields & fields, ActivityId parent) { }; + + virtual void stopActivity(ActivityId act) { }; + + virtual void result(ActivityId act, ResultType type, const Fields & fields) { }; +}; + +ActivityId getCurActivity(); +void setCurActivity(const ActivityId activityId); + +struct Activity +{ + Logger & logger; + + const ActivityId id; + + Activity(Logger & logger, Verbosity lvl, ActivityType type, const std::string & s = "", + const Logger::Fields & fields = {}, ActivityId parent = getCurActivity()); + + Activity(Logger & logger, ActivityType type, + const Logger::Fields & fields = {}, ActivityId parent = getCurActivity()) + : Activity(logger, lvlError, type, "", fields, parent) { }; + + Activity(const Activity & act) = delete; + + ~Activity(); + + void progress(uint64_t done = 0, uint64_t expected = 0, uint64_t running = 0, uint64_t failed = 0) const + { result(resProgress, done, expected, running, failed); } + + void setExpected(ActivityType type2, uint64_t expected) const + { result(resSetExpected, type2, expected); } + + template<typename... Args> + void result(ResultType type, const Args & ... args) const + { + Logger::Fields fields; + nop{(fields.emplace_back(Logger::Field(args)), 1)...}; + result(type, fields); + } + + void result(ResultType type, const Logger::Fields & fields) const + { + logger.result(id, type, fields); + } + + friend class Logger; +}; + +struct PushActivity +{ + const ActivityId prevAct; + PushActivity(ActivityId act) : prevAct(getCurActivity()) { setCurActivity(act); } + ~PushActivity() { setCurActivity(prevAct); } +}; + +extern Logger * logger; + +Logger * makeDefaultLogger(); + +Logger * makeJSONLogger(Logger & prevLogger); + +bool handleJSONLogMessage(const std::string & msg, + const Activity & act, std::map<ActivityId, Activity> & activities, + bool trusted); + +extern Verbosity verbosity; /* suppress msgs > this */ + +/* Print a message if the current log level is at least the specified + level. Note that this has to be implemented as a macro to ensure + that the arguments are evaluated lazily. */ +#define printMsg(level, args...) \ + do { \ + if (level <= nix::verbosity) { \ + logger->log(level, fmt(args)); \ + } \ + } while (0) + +#define printError(args...) printMsg(lvlError, args) +#define printInfo(args...) printMsg(lvlInfo, args) +#define printTalkative(args...) printMsg(lvlTalkative, args) +#define debug(args...) printMsg(lvlDebug, args) +#define vomit(args...) printMsg(lvlVomit, args) + +template<typename... Args> +inline void warn(const std::string & fs, Args... args) +{ + boost::format f(fs); + nop{boost::io::detail::feed(f, args)...}; + logger->warn(f.str()); +} + +void warnOnce(bool & haveWarned, const FormatOrString & fs); + +void writeToStderr(const string & s); + +} |