forked from lix-project/lix
c36467ad2e
E.g. $ nix build --store local?root=/tmp/nix nixpkgs.firefox-unwrapped [0/1 built, 1/97/98 fetched, 65.8/92.8 MiB DL, 203.2/309.2 MiB copied] downloading 'https://cache.nixos.org/nar/1czm9fk0svacy4h6a3fzkpafi4f7a9gml36kk8cq1igaghbspg3k.nar.xz'
165 lines
3.5 KiB
C++
165 lines
3.5 KiB
C++
#pragma once
|
|
|
|
#include "types.hh"
|
|
|
|
namespace nix {
|
|
|
|
typedef enum {
|
|
lvlError = 0,
|
|
lvlInfo,
|
|
lvlTalkative,
|
|
lvlChatty,
|
|
lvlDebug,
|
|
lvlVomit
|
|
} Verbosity;
|
|
|
|
typedef enum {
|
|
actUnknown = 0,
|
|
actCopyPath = 100,
|
|
actDownload = 101,
|
|
actRealise = 102,
|
|
} ActivityType;
|
|
|
|
class Activity
|
|
{
|
|
public:
|
|
typedef uint64_t t;
|
|
const t id;
|
|
Activity();
|
|
Activity(const Activity & act) : id(act.id) { };
|
|
Activity(uint64_t id) : id(id) { };
|
|
Activity(ActivityType type, std::string msg = "");
|
|
~Activity();
|
|
|
|
template<typename... Args>
|
|
void progress(const Args & ... args);
|
|
};
|
|
|
|
typedef enum {
|
|
evBuildCreated = 0,
|
|
evBuildStarted = 1,
|
|
evBuildOutput = 2,
|
|
evBuildFinished = 3,
|
|
evSubstitutionCreated = 8,
|
|
evSubstitutionStarted = 9,
|
|
evSubstitutionFinished = 10,
|
|
|
|
evCopyStarted = 100,
|
|
evCopyProgress = 101,
|
|
|
|
evStartActivity = 1000,
|
|
evStopActivity = 1001,
|
|
evProgress = 1002,
|
|
evSetExpected = 1003,
|
|
|
|
} EventType;
|
|
|
|
struct Event
|
|
{
|
|
struct Field
|
|
{
|
|
// FIXME: use std::variant.
|
|
enum { tInt, tString } 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) { }
|
|
Field(const Activity & act) : type(tInt), i(act.id) { }
|
|
};
|
|
|
|
typedef std::vector<Field> Fields;
|
|
|
|
EventType type;
|
|
Fields fields;
|
|
|
|
std::string getS(size_t n) const
|
|
{
|
|
assert(n < fields.size());
|
|
assert(fields[n].type == Field::tString);
|
|
return fields[n].s;
|
|
}
|
|
|
|
uint64_t getI(size_t n) const
|
|
{
|
|
assert(n < fields.size());
|
|
assert(fields[n].type == Field::tInt);
|
|
return fields[n].i;
|
|
}
|
|
};
|
|
|
|
class Logger
|
|
{
|
|
friend class Activity;
|
|
|
|
public:
|
|
|
|
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);
|
|
|
|
template<typename... Args>
|
|
void event(EventType type, const Args & ... args)
|
|
{
|
|
Event ev;
|
|
ev.type = type;
|
|
nop{(ev.fields.emplace_back(Event::Field(args)), 1)...};
|
|
event(ev);
|
|
}
|
|
|
|
virtual void event(const Event & ev) = 0;
|
|
};
|
|
|
|
extern Logger * logger;
|
|
|
|
Logger * makeDefaultLogger();
|
|
|
|
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);
|
|
|
|
template<typename... Args>
|
|
void Activity::progress(const Args & ... args)
|
|
{
|
|
Event ev;
|
|
ev.type = evProgress;
|
|
ev.fields.emplace_back(id);
|
|
nop{(ev.fields.emplace_back(Event::Field(args)), 1)...};
|
|
logger->event(ev);
|
|
}
|
|
|
|
}
|