New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a settings option for log-format #3961
Conversation
This appears to break the
no longer prints any JSON messages. |
I'm unsure why this is, as of now. I'll get back to this a little later |
I tried debugging the issue where Seeing that flags like (BTW: |
e830b11
to
9dc53a2
Compare
It works! Though I ended up juggling around more things than would have been ideal... |
Applying the following patch allows both EDIT: Do note, however, that this means libstore depends on libmain (for access to |
18188ad
to
fa311d1
Compare
So its ready to be merged? Would need this for one of my prs. |
b1600b3
to
b024a78
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EDIT: Do note, however, that this means libstore depends on libmain (for access to createDefaultLogger()). I don't know if this is desirable
or not (or even extremely undesirable), but I can't see any other way.
That's a bit annoying imho. IIRC there was a good reason to keep the progress bar in libmain, but a good (?) way to break this would be to mak
e the logger pluggable like we do for the stores. Something like
// Somewhere in libutil
struct LoggerBuilder {
std::string name;
std::function<(Logger*) void*> builder;
};
static std::vector<std::shared_ptr<LoggerBuilder>> registeredLoggers;
void registerLogger(std::string name, std::function<(Logger*) void> builder) {
LoggerBuilder lBuilder{ .name = name, .builder = builder };
registeredLoggers.push_back(std::shared_ptr<LoggerBuilder>(lBuilder));
}
Logger* makeDefaultLogger() {
for (auto & builder : registeredLoggers) {
if (builder.name == settings.logFormat) {
return builder.builder();
}
}
throw Error("Unknown logger %s", settings.logFormat);
}
// Can be called in the file defining the logger
registerLogger("bar", []() -> Logger* { makeProgressBar(false); });
registerLogger("bar-with-logs", []() -> Logger* { makeProgressBar(true); });
registerLogger("json", []() -> Logger* { makeJSONLogger(); });
And then we can recover the list of values for the logger option by introspecting the value of registeredLoggers
:
std::string listLogFormats()
{
std::string res;
for (auto & builder : registeredLoggers) {
if (res) res += ", ";
res += builder.name;
}
return res;
}
Setting<LogFormat> logFormat{this, LogFormat::bar, "log-format",
format("Default build output logging format; %s.", listLogFormats()};
src/libstore/globals.cc
Outdated
else abort(); | ||
} | ||
|
||
template<> nlohmann::json BaseSetting<LogFormat>::toJSON() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't correct anymore in master (toJSON()
isn't expected to be equal to toString()
anymore). You can get the templated definition by including abstractsettingtojson.hh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, abstractsettingtojson.hh
is already included by globals.hh
, so there was no need to include it in globals.cc
as well.
|
||
template<> void BaseSetting<LogFormat>::convertToArg(Args & args, const std::string & category) | ||
{ | ||
args.addFlag({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a way to define custom completers for the cli, you could use that so that the autocompletion suggest the different log formats
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done so (based on the completion function for hashTypes
), but I don't know how to test if it really works (nor can I, AFAIK, as I use fish rather than bash or zsh).
Thanks @regnat for the help! Following your advice (both here and on IRC), I refactored the loggers stuff to be pluggable (letting us drop the libmain <- libstore dependency). There's one thing I'm still unhappy with, however: the fact that One idea I just had would be to create a new log format type that's really just a string (as done with |
src/libstore/globals.hh
Outdated
@@ -12,6 +13,8 @@ | |||
|
|||
namespace nix { | |||
|
|||
std::string listLogFormats(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really like that this is outside the Settings
class, but putting it anywhere inside gives undefined references errors (due to its use in the logFormat
description). Happy to hear alternatives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're allowed to make it a static member of the Settings
class if you want to
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With @LnL7's help, I created a new type for LogFormatSetting
, which lets me remove listLogFormats
from publicity and instead just call it in the constructor for that setting.
(Your static
idea didn't seem to work.)
Thanks @cole-h , I like that a lot!
That sounds definitely a good thing (The static enum doesn't really make sense now that the thing is pluggable imho). Regarding your IRC message:
I think I found the reason why: both |
99f6976
to
1422880
Compare
Because @LnL7 showed me how to get the json library to specialize enum conversion, the string wrapper is no longer necessary. I also moved progress-bar.{hh,cc} and names.{hh,cc} to libutil, which allows all the loggers to be registered in libutil (so they all show up in the manpage). I think this is ready for merge (or at least "final review"). Thanks everyone for your help (especially @regnat)! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice 👍 I don't have the commit rights for the repo, but it looks all good on my side
(I'm not utterly fond of having both a static list of known loggers and a registration mechanism, but it's definitely not a blocker for me).
cbc9f1d
to
8f4c71e
Compare
Ping @edolstra -- would appreciate another review (or, even better, a merge) on this, when you get a chance. |
This is really cool! I'm especially excited because I think it might make it easier for hydra alternatives to stream logs per derivation? Hope to see this land soon :). |
@edolstra ping, have you had a chance to look over this? |
6cc4cd9
to
a67a66f
Compare
Co-authored-by: Cole Helbling <cole.e.helbling@outlook.com>
Thanks to some precision guidance by regnat, we can remove libstore's dependency on libmain by just making the logging mechanisms pluggable. This: * moves loggers.{hh,cc} from libmain to libutil * removes the now-unnecessary (and incorrect) `toJSON` specialization * moves LogFormat from types.hh to loggers.hh * adds a completer (untested) To add another logger, the following steps should be all that's necessary: 1) Add enum variant in libutil/loggers.hh and name to the `std::set` in loggers.cc 2) Modify the specialized `set` and `to_string` methods to include the new variant 3) Use the `OnStartup` class to `registerLogger` the new logger method Co-authored-by: regnat <rg@regnat.ovh>
It is no longer necessary to add the logger name to the `logFormats` set when adding a new logger (due to its removal). Additionally, the manpage now displays the string "bar" as the default, rather than an unhelpfully opaque integer. Co-authored-by: regnat <rg@regnat.ovh> Co-authored-by: Daiderd Jordan <daiderd@gmail.com>
This fixes manpage generation excluding the `bar` and `bar-with-logs` log formats that were registered outside libutil; now all formats appear. Note that any loggers registered outside of libutil might not appear in the manpage -- probably due to the fact that C++ doesn't define the order in which static variables are initialized (as regnat noted). This also removes the unused store-api.hh include in progress-bar.cc.
Seems eelco was ignoring this because he has other plans 490861e |
Close in favor of #4296 |
This removes the need to pass --log-format to every nix invocation for your log-format of choice