2016-04-25 16:26:07 +03:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "types.hh"
|
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
lvlError = 0,
|
|
|
|
lvlInfo,
|
|
|
|
lvlTalkative,
|
|
|
|
lvlChatty,
|
|
|
|
lvlDebug,
|
|
|
|
lvlVomit
|
|
|
|
} Verbosity;
|
|
|
|
|
2017-08-14 16:28:16 +03:00
|
|
|
typedef enum {
|
2017-08-14 20:00:03 +03:00
|
|
|
actUnknown = 0,
|
2017-08-14 16:28:16 +03:00
|
|
|
actCopyPath = 100,
|
2017-08-14 21:14:55 +03:00
|
|
|
actDownload = 101,
|
|
|
|
actRealise = 102,
|
2017-08-14 23:12:36 +03:00
|
|
|
actCopyPaths = 103,
|
2017-08-15 16:31:59 +03:00
|
|
|
actBuilds = 104,
|
|
|
|
actBuild = 105,
|
2017-08-16 18:00:24 +03:00
|
|
|
actOptimiseStore = 106,
|
2017-08-16 20:23:46 +03:00
|
|
|
actVerifyPaths = 107,
|
2017-08-25 18:49:40 +03:00
|
|
|
actSubstitute = 108,
|
2017-08-31 16:25:58 +03:00
|
|
|
actQueryPathInfo = 109,
|
2017-08-14 16:28:16 +03:00
|
|
|
} ActivityType;
|
|
|
|
|
2017-08-16 18:32:18 +03:00
|
|
|
typedef enum {
|
|
|
|
resFileLinked = 100,
|
|
|
|
resBuildLogLine = 101,
|
2017-08-16 20:23:46 +03:00
|
|
|
resUntrustedPath = 102,
|
|
|
|
resCorruptedPath = 103,
|
2017-08-25 19:04:05 +03:00
|
|
|
resSetPhase = 104,
|
2017-08-25 22:26:37 +03:00
|
|
|
resProgress = 105,
|
2017-08-28 15:30:35 +03:00
|
|
|
resSetExpected = 106,
|
2017-08-16 18:32:18 +03:00
|
|
|
} ResultType;
|
|
|
|
|
2017-08-16 17:38:23 +03:00
|
|
|
typedef uint64_t ActivityId;
|
2016-04-25 16:26:07 +03:00
|
|
|
|
|
|
|
class Logger
|
|
|
|
{
|
2017-08-31 12:04:52 +03:00
|
|
|
friend struct Activity;
|
2016-04-25 16:26:07 +03:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2017-08-25 15:53:50 +03:00
|
|
|
struct Field
|
|
|
|
{
|
|
|
|
// FIXME: use std::variant.
|
2017-08-28 19:49:42 +03:00
|
|
|
enum { tInt = 0, tString = 1 } type;
|
2017-08-25 15:53:50 +03:00
|
|
|
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;
|
|
|
|
|
2016-04-25 16:26:07 +03:00
|
|
|
virtual ~Logger() { }
|
|
|
|
|
|
|
|
virtual void log(Verbosity lvl, const FormatOrString & fs) = 0;
|
|
|
|
|
|
|
|
void log(const FormatOrString & fs)
|
|
|
|
{
|
|
|
|
log(lvlInfo, fs);
|
|
|
|
}
|
|
|
|
|
2017-04-12 15:53:10 +03:00
|
|
|
virtual void warn(const std::string & msg);
|
|
|
|
|
2017-08-28 20:13:24 +03:00
|
|
|
virtual void startActivity(ActivityId act, Verbosity lvl, ActivityType type,
|
2017-08-25 18:49:40 +03:00
|
|
|
const std::string & s, const Fields & fields, ActivityId parent) { };
|
2017-08-16 17:38:23 +03:00
|
|
|
|
|
|
|
virtual void stopActivity(ActivityId act) { };
|
|
|
|
|
2017-08-25 15:53:50 +03:00
|
|
|
virtual void result(ActivityId act, ResultType type, const Fields & fields) { };
|
2017-08-16 17:38:23 +03:00
|
|
|
};
|
|
|
|
|
2017-08-25 18:49:40 +03:00
|
|
|
extern thread_local ActivityId curActivity;
|
|
|
|
|
2017-08-16 17:38:23 +03:00
|
|
|
struct Activity
|
|
|
|
{
|
|
|
|
Logger & logger;
|
|
|
|
|
|
|
|
const ActivityId id;
|
|
|
|
|
2017-08-28 20:13:24 +03:00
|
|
|
Activity(Logger & logger, Verbosity lvl, ActivityType type, const std::string & s = "",
|
2017-08-25 18:49:40 +03:00
|
|
|
const Logger::Fields & fields = {}, ActivityId parent = curActivity);
|
2017-08-16 17:38:23 +03:00
|
|
|
|
2017-08-28 20:13:24 +03:00
|
|
|
Activity(Logger & logger, ActivityType type,
|
|
|
|
const Logger::Fields & fields = {}, ActivityId parent = curActivity)
|
|
|
|
: Activity(logger, lvlError, type, "", fields, parent) { };
|
|
|
|
|
2017-08-21 13:00:41 +03:00
|
|
|
Activity(const Activity & act) = delete;
|
|
|
|
|
2018-03-03 22:39:04 +02:00
|
|
|
~Activity();
|
2017-08-16 17:38:23 +03:00
|
|
|
|
|
|
|
void progress(uint64_t done = 0, uint64_t expected = 0, uint64_t running = 0, uint64_t failed = 0) const
|
2017-08-25 22:26:37 +03:00
|
|
|
{ result(resProgress, done, expected, running, failed); }
|
2017-08-16 17:38:23 +03:00
|
|
|
|
|
|
|
void setExpected(ActivityType type2, uint64_t expected) const
|
2017-08-28 15:30:35 +03:00
|
|
|
{ result(resSetExpected, type2, expected); }
|
2016-04-25 16:26:07 +03:00
|
|
|
|
2017-08-16 18:32:18 +03:00
|
|
|
template<typename... Args>
|
2017-08-25 22:26:37 +03:00
|
|
|
void result(ResultType type, const Args & ... args) const
|
2017-08-16 18:32:18 +03:00
|
|
|
{
|
2017-08-25 15:53:50 +03:00
|
|
|
Logger::Fields fields;
|
2017-08-16 18:32:18 +03:00
|
|
|
nop{(fields.emplace_back(Logger::Field(args)), 1)...};
|
2017-08-25 22:26:37 +03:00
|
|
|
result(type, fields);
|
|
|
|
}
|
|
|
|
|
|
|
|
void result(ResultType type, const Logger::Fields & fields) const
|
|
|
|
{
|
2017-08-16 18:32:18 +03:00
|
|
|
logger.result(id, type, fields);
|
|
|
|
}
|
|
|
|
|
2017-08-16 17:38:23 +03:00
|
|
|
friend class Logger;
|
2016-04-25 16:26:07 +03:00
|
|
|
};
|
|
|
|
|
2017-08-25 18:49:40 +03:00
|
|
|
struct PushActivity
|
|
|
|
{
|
|
|
|
const ActivityId prevAct;
|
|
|
|
PushActivity(ActivityId act) : prevAct(curActivity) { curActivity = act; }
|
|
|
|
~PushActivity() { curActivity = prevAct; }
|
|
|
|
};
|
|
|
|
|
2016-04-25 16:26:07 +03:00
|
|
|
extern Logger * logger;
|
|
|
|
|
|
|
|
Logger * makeDefaultLogger();
|
|
|
|
|
2017-10-24 14:41:52 +03:00
|
|
|
Logger * makeJSONLogger(Logger & prevLogger);
|
|
|
|
|
|
|
|
bool handleJSONLogMessage(const std::string & msg,
|
2017-10-24 15:47:23 +03:00
|
|
|
const Activity & act, std::map<ActivityId, Activity> & activities,
|
|
|
|
bool trusted);
|
2017-10-24 14:41:52 +03:00
|
|
|
|
2016-04-25 16:26:07 +03:00
|
|
|
extern Verbosity verbosity; /* suppress msgs > this */
|
|
|
|
|
2016-09-21 17:00:03 +03:00
|
|
|
/* 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...) \
|
2016-04-25 16:26:07 +03:00
|
|
|
do { \
|
|
|
|
if (level <= nix::verbosity) { \
|
2016-09-21 17:00:03 +03:00
|
|
|
logger->log(level, fmt(args)); \
|
2016-04-25 16:26:07 +03:00
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2016-09-21 17:00:03 +03:00
|
|
|
#define printError(args...) printMsg(lvlError, args)
|
|
|
|
#define printInfo(args...) printMsg(lvlInfo, args)
|
2017-02-14 15:20:00 +02:00
|
|
|
#define printTalkative(args...) printMsg(lvlTalkative, args)
|
2016-09-21 17:00:03 +03:00
|
|
|
#define debug(args...) printMsg(lvlDebug, args)
|
2016-12-06 22:58:04 +02:00
|
|
|
#define vomit(args...) printMsg(lvlVomit, args)
|
2016-04-25 16:26:07 +03:00
|
|
|
|
2017-04-12 15:53:10 +03:00
|
|
|
template<typename... Args>
|
|
|
|
inline void warn(const std::string & fs, Args... args)
|
|
|
|
{
|
|
|
|
boost::format f(fs);
|
2017-05-11 18:06:07 +03:00
|
|
|
nop{boost::io::detail::feed(f, args)...};
|
2017-04-12 15:53:10 +03:00
|
|
|
logger->warn(f.str());
|
|
|
|
}
|
|
|
|
|
2016-04-25 16:26:07 +03:00
|
|
|
void warnOnce(bool & haveWarned, const FormatOrString & fs);
|
|
|
|
|
|
|
|
void writeToStderr(const string & s);
|
|
|
|
|
|
|
|
}
|