2016-04-25 15:26:07 +02:00
|
|
|
#pragma once
|
2023-03-31 23:18:41 -04:00
|
|
|
///@file
|
2016-04-25 15:26:07 +02:00
|
|
|
|
|
|
|
#include "types.hh"
|
2020-05-11 15:52:15 -06:00
|
|
|
#include "error.hh"
|
2020-07-02 09:04:31 -06:00
|
|
|
#include "config.hh"
|
2016-04-25 15:26:07 +02:00
|
|
|
|
2022-02-28 16:05:21 +01:00
|
|
|
#include <nlohmann/json_fwd.hpp>
|
2022-02-19 22:34:50 +01:00
|
|
|
|
2016-04-25 15:26:07 +02:00
|
|
|
namespace nix {
|
|
|
|
|
2017-08-14 15:28:16 +02:00
|
|
|
typedef enum {
|
2017-08-14 19:00:03 +02:00
|
|
|
actUnknown = 0,
|
2017-08-14 15:28:16 +02:00
|
|
|
actCopyPath = 100,
|
2020-04-06 23:43:43 +02:00
|
|
|
actFileTransfer = 101,
|
2017-08-14 20:14:55 +02:00
|
|
|
actRealise = 102,
|
2017-08-14 22:12:36 +02:00
|
|
|
actCopyPaths = 103,
|
2017-08-15 15:31:59 +02:00
|
|
|
actBuilds = 104,
|
|
|
|
actBuild = 105,
|
2017-08-16 17:00:24 +02:00
|
|
|
actOptimiseStore = 106,
|
2017-08-16 19:23:46 +02:00
|
|
|
actVerifyPaths = 107,
|
2017-08-25 17:49:40 +02:00
|
|
|
actSubstitute = 108,
|
2017-08-31 15:25:58 +02:00
|
|
|
actQueryPathInfo = 109,
|
2019-07-11 20:23:03 +02:00
|
|
|
actPostBuildHook = 110,
|
2020-06-15 16:03:29 +02:00
|
|
|
actBuildWaiting = 111,
|
2023-11-15 13:57:20 +01:00
|
|
|
actFetchTree = 112,
|
2017-08-14 15:28:16 +02:00
|
|
|
} ActivityType;
|
|
|
|
|
2017-08-16 17:32:18 +02:00
|
|
|
typedef enum {
|
|
|
|
resFileLinked = 100,
|
|
|
|
resBuildLogLine = 101,
|
2017-08-16 19:23:46 +02:00
|
|
|
resUntrustedPath = 102,
|
|
|
|
resCorruptedPath = 103,
|
2017-08-25 18:04:05 +02:00
|
|
|
resSetPhase = 104,
|
2017-08-25 21:26:37 +02:00
|
|
|
resProgress = 105,
|
2017-08-28 14:30:35 +02:00
|
|
|
resSetExpected = 106,
|
2019-07-11 20:23:03 +02:00
|
|
|
resPostBuildLogLine = 107,
|
2023-11-15 13:57:20 +01:00
|
|
|
resFetchStatus = 108,
|
2017-08-16 17:32:18 +02:00
|
|
|
} ResultType;
|
|
|
|
|
2017-08-16 16:38:23 +02:00
|
|
|
typedef uint64_t ActivityId;
|
2016-04-25 15:26:07 +02:00
|
|
|
|
2020-07-02 09:04:31 -06:00
|
|
|
struct LoggerSettings : Config
|
|
|
|
{
|
2020-08-19 18:28:04 +02:00
|
|
|
Setting<bool> showTrace{
|
|
|
|
this, false, "show-trace",
|
|
|
|
R"(
|
2022-01-11 11:57:45 +01:00
|
|
|
Whether Nix should print out a stack trace in case of Nix
|
2020-08-19 18:28:04 +02:00
|
|
|
expression evaluation errors.
|
|
|
|
)"};
|
2020-07-02 09:04:31 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
extern LoggerSettings loggerSettings;
|
|
|
|
|
2016-04-25 15:26:07 +02:00
|
|
|
class Logger
|
|
|
|
{
|
2017-08-31 11:04:52 +02:00
|
|
|
friend struct Activity;
|
2016-04-25 15:26:07 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2017-08-25 14:53:50 +02:00
|
|
|
struct Field
|
|
|
|
{
|
|
|
|
// FIXME: use std::variant.
|
2017-08-28 18:49:42 +02:00
|
|
|
enum { tInt = 0, tString = 1 } type;
|
2017-08-25 14:53:50 +02: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 15:26:07 +02:00
|
|
|
virtual ~Logger() { }
|
|
|
|
|
2020-06-05 17:01:02 +02:00
|
|
|
virtual void stop() { };
|
|
|
|
|
2023-03-09 18:11:01 +04:00
|
|
|
virtual void pause() { };
|
|
|
|
virtual void resume() { };
|
|
|
|
|
2020-06-05 18:20:11 +02:00
|
|
|
// Whether the logger prints the whole build log
|
|
|
|
virtual bool isVerbose() { return false; }
|
|
|
|
|
2023-03-02 15:44:19 +01:00
|
|
|
virtual void log(Verbosity lvl, std::string_view s) = 0;
|
2016-04-25 15:26:07 +02:00
|
|
|
|
2023-03-02 15:44:19 +01:00
|
|
|
void log(std::string_view s)
|
2016-04-25 15:26:07 +02:00
|
|
|
{
|
2023-03-02 15:44:19 +01:00
|
|
|
log(lvlInfo, s);
|
2016-04-25 15:26:07 +02:00
|
|
|
}
|
|
|
|
|
2022-12-07 12:58:58 +01:00
|
|
|
virtual void logEI(const ErrorInfo & ei) = 0;
|
2020-04-17 15:07:44 -06:00
|
|
|
|
2020-04-29 10:14:32 -06:00
|
|
|
void logEI(Verbosity lvl, ErrorInfo ei)
|
2020-04-24 12:44:23 -06:00
|
|
|
{
|
|
|
|
ei.level = lvl;
|
|
|
|
logEI(ei);
|
2020-04-17 15:07:44 -06:00
|
|
|
}
|
2020-04-29 10:14:32 -06:00
|
|
|
|
2017-04-12 14:53:10 +02:00
|
|
|
virtual void warn(const std::string & msg);
|
|
|
|
|
2017-08-28 19:13:24 +02:00
|
|
|
virtual void startActivity(ActivityId act, Verbosity lvl, ActivityType type,
|
2017-08-25 17:49:40 +02:00
|
|
|
const std::string & s, const Fields & fields, ActivityId parent) { };
|
2017-08-16 16:38:23 +02:00
|
|
|
|
|
|
|
virtual void stopActivity(ActivityId act) { };
|
|
|
|
|
2017-08-25 14:53:50 +02:00
|
|
|
virtual void result(ActivityId act, ResultType type, const Fields & fields) { };
|
2020-04-16 13:12:58 +02:00
|
|
|
|
|
|
|
virtual void writeToStdout(std::string_view s);
|
|
|
|
|
|
|
|
template<typename... Args>
|
2023-03-02 14:52:37 +01:00
|
|
|
inline void cout(const Args & ... args)
|
2020-04-16 13:12:58 +02:00
|
|
|
{
|
2023-03-02 14:52:37 +01:00
|
|
|
writeToStdout(fmt(args...));
|
2020-04-16 13:12:58 +02:00
|
|
|
}
|
2020-11-26 12:34:43 +01:00
|
|
|
|
|
|
|
virtual std::optional<char> ask(std::string_view s)
|
|
|
|
{ return {}; }
|
2022-08-24 22:36:40 +02:00
|
|
|
|
|
|
|
virtual void setPrintBuildLogs(bool printBuildLogs)
|
|
|
|
{ }
|
2017-08-16 16:38:23 +02:00
|
|
|
};
|
|
|
|
|
2024-02-03 19:16:30 -08:00
|
|
|
/**
|
|
|
|
* A variadic template that does nothing.
|
|
|
|
*
|
|
|
|
* Useful to call a function with each argument in a parameter pack.
|
|
|
|
*/
|
|
|
|
struct nop
|
|
|
|
{
|
|
|
|
template<typename... T> nop(T...)
|
|
|
|
{ }
|
|
|
|
};
|
|
|
|
|
2018-03-12 00:56:41 -04:00
|
|
|
ActivityId getCurActivity();
|
|
|
|
void setCurActivity(const ActivityId activityId);
|
2017-08-25 17:49:40 +02:00
|
|
|
|
2017-08-16 16:38:23 +02:00
|
|
|
struct Activity
|
|
|
|
{
|
|
|
|
Logger & logger;
|
|
|
|
|
|
|
|
const ActivityId id;
|
|
|
|
|
2017-08-28 19:13:24 +02:00
|
|
|
Activity(Logger & logger, Verbosity lvl, ActivityType type, const std::string & s = "",
|
2018-03-12 00:56:41 -04:00
|
|
|
const Logger::Fields & fields = {}, ActivityId parent = getCurActivity());
|
2017-08-16 16:38:23 +02:00
|
|
|
|
2017-08-28 19:13:24 +02:00
|
|
|
Activity(Logger & logger, ActivityType type,
|
2018-03-12 00:56:41 -04:00
|
|
|
const Logger::Fields & fields = {}, ActivityId parent = getCurActivity())
|
2017-08-28 19:13:24 +02:00
|
|
|
: Activity(logger, lvlError, type, "", fields, parent) { };
|
|
|
|
|
2017-08-21 12:00:41 +02:00
|
|
|
Activity(const Activity & act) = delete;
|
|
|
|
|
2018-03-03 14:39:04 -06:00
|
|
|
~Activity();
|
2017-08-16 16:38:23 +02:00
|
|
|
|
|
|
|
void progress(uint64_t done = 0, uint64_t expected = 0, uint64_t running = 0, uint64_t failed = 0) const
|
2017-08-25 21:26:37 +02:00
|
|
|
{ result(resProgress, done, expected, running, failed); }
|
2017-08-16 16:38:23 +02:00
|
|
|
|
|
|
|
void setExpected(ActivityType type2, uint64_t expected) const
|
2017-08-28 14:30:35 +02:00
|
|
|
{ result(resSetExpected, type2, expected); }
|
2016-04-25 15:26:07 +02:00
|
|
|
|
2017-08-16 17:32:18 +02:00
|
|
|
template<typename... Args>
|
2017-08-25 21:26:37 +02:00
|
|
|
void result(ResultType type, const Args & ... args) const
|
2017-08-16 17:32:18 +02:00
|
|
|
{
|
2017-08-25 14:53:50 +02:00
|
|
|
Logger::Fields fields;
|
2017-08-16 17:32:18 +02:00
|
|
|
nop{(fields.emplace_back(Logger::Field(args)), 1)...};
|
2017-08-25 21:26:37 +02:00
|
|
|
result(type, fields);
|
|
|
|
}
|
|
|
|
|
|
|
|
void result(ResultType type, const Logger::Fields & fields) const
|
|
|
|
{
|
2017-08-16 17:32:18 +02:00
|
|
|
logger.result(id, type, fields);
|
|
|
|
}
|
|
|
|
|
2017-08-16 16:38:23 +02:00
|
|
|
friend class Logger;
|
2016-04-25 15:26:07 +02:00
|
|
|
};
|
|
|
|
|
2017-08-25 17:49:40 +02:00
|
|
|
struct PushActivity
|
|
|
|
{
|
|
|
|
const ActivityId prevAct;
|
2018-03-12 00:56:41 -04:00
|
|
|
PushActivity(ActivityId act) : prevAct(getCurActivity()) { setCurActivity(act); }
|
|
|
|
~PushActivity() { setCurActivity(prevAct); }
|
2017-08-25 17:49:40 +02:00
|
|
|
};
|
|
|
|
|
2016-04-25 15:26:07 +02:00
|
|
|
extern Logger * logger;
|
|
|
|
|
2020-06-05 18:20:11 +02:00
|
|
|
Logger * makeSimpleLogger(bool printBuildLogs = true);
|
2016-04-25 15:26:07 +02:00
|
|
|
|
2017-10-24 13:41:52 +02:00
|
|
|
Logger * makeJSONLogger(Logger & prevLogger);
|
|
|
|
|
2022-02-19 22:34:50 +01:00
|
|
|
std::optional<nlohmann::json> parseJSONMessage(const std::string & msg);
|
|
|
|
|
|
|
|
bool handleJSONLogMessage(nlohmann::json & json,
|
|
|
|
const Activity & act, std::map<ActivityId, Activity> & activities,
|
|
|
|
bool trusted);
|
|
|
|
|
2017-10-24 13:41:52 +02:00
|
|
|
bool handleJSONLogMessage(const std::string & msg,
|
2017-10-24 14:47:23 +02:00
|
|
|
const Activity & act, std::map<ActivityId, Activity> & activities,
|
|
|
|
bool trusted);
|
2017-10-24 13:41:52 +02:00
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* suppress msgs > this
|
|
|
|
*/
|
|
|
|
extern Verbosity verbosity;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Print a message with the standard ErrorInfo format.
|
|
|
|
* In general, use these 'log' macros for reporting problems that may require user
|
|
|
|
* intervention or that need more explanation. Use the 'print' macros for more
|
|
|
|
* lightweight status messages.
|
|
|
|
*/
|
2020-06-04 11:53:19 -06:00
|
|
|
#define logErrorInfo(level, errorInfo...) \
|
|
|
|
do { \
|
2020-11-09 14:14:11 +01:00
|
|
|
if ((level) <= nix::verbosity) { \
|
|
|
|
logger->logEI((level), errorInfo); \
|
2020-06-04 11:53:19 -06:00
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define logError(errorInfo...) logErrorInfo(lvlError, errorInfo)
|
|
|
|
#define logWarning(errorInfo...) logErrorInfo(lvlWarn, errorInfo)
|
|
|
|
|
2023-04-07 09:55:28 -04:00
|
|
|
/**
|
|
|
|
* Print a string 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.
|
|
|
|
*/
|
2021-11-30 20:23:13 +00:00
|
|
|
#define printMsgUsing(loggerParam, level, args...) \
|
2016-04-25 15:26:07 +02:00
|
|
|
do { \
|
2020-11-27 12:17:07 +01:00
|
|
|
auto __lvl = level; \
|
|
|
|
if (__lvl <= nix::verbosity) { \
|
2021-11-30 20:23:13 +00:00
|
|
|
loggerParam->log(__lvl, fmt(args)); \
|
2016-04-25 15:26:07 +02:00
|
|
|
} \
|
|
|
|
} while (0)
|
2021-11-30 20:23:13 +00:00
|
|
|
#define printMsg(level, args...) printMsgUsing(logger, level, args)
|
2016-04-25 15:26:07 +02:00
|
|
|
|
2016-09-21 16:00:03 +02:00
|
|
|
#define printError(args...) printMsg(lvlError, args)
|
2020-11-27 11:19:36 +01:00
|
|
|
#define notice(args...) printMsg(lvlNotice, args)
|
2016-09-21 16:00:03 +02:00
|
|
|
#define printInfo(args...) printMsg(lvlInfo, args)
|
2017-02-14 14:20:00 +01:00
|
|
|
#define printTalkative(args...) printMsg(lvlTalkative, args)
|
2016-09-21 16:00:03 +02:00
|
|
|
#define debug(args...) printMsg(lvlDebug, args)
|
2016-12-06 21:58:04 +01:00
|
|
|
#define vomit(args...) printMsg(lvlVomit, args)
|
2016-04-25 15:26:07 +02:00
|
|
|
|
2023-03-26 21:12:25 -04:00
|
|
|
/**
|
|
|
|
* if verbosity >= lvlWarn, print a message with a yellow 'warning:' prefix.
|
|
|
|
*/
|
2017-04-12 14:53:10 +02:00
|
|
|
template<typename... Args>
|
2019-12-05 17:39:11 +01:00
|
|
|
inline void warn(const std::string & fs, const Args & ... args)
|
2017-04-12 14:53:10 +02:00
|
|
|
{
|
|
|
|
boost::format f(fs);
|
2019-12-05 17:48:16 +01:00
|
|
|
formatHelper(f, args...);
|
2017-04-12 14:53:10 +02:00
|
|
|
logger->warn(f.str());
|
|
|
|
}
|
|
|
|
|
2022-12-07 12:58:58 +01:00
|
|
|
#define warnOnce(haveWarned, args...) \
|
|
|
|
if (!haveWarned) { \
|
|
|
|
haveWarned = true; \
|
|
|
|
warn(args); \
|
|
|
|
}
|
2016-04-25 15:26:07 +02:00
|
|
|
|
2022-02-25 16:00:00 +01:00
|
|
|
void writeToStderr(std::string_view s);
|
2016-04-25 15:26:07 +02:00
|
|
|
|
|
|
|
}
|