about summary refs log tree commit diff
path: root/third_party/nix/src/libutil/logging.hh
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/nix/src/libutil/logging.hh')
-rw-r--r--third_party/nix/src/libutil/logging.hh172
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 0000000000..5df03da74e
--- /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);
+
+}