[Lldb-commits] [PATCH] D27459: Straw-man proposal for new logging syntax
Zachary Turner via Phabricator via lldb-commits
lldb-commits at lists.llvm.org
Tue Dec 6 09:47:00 PST 2016
zturner added a comment.
In https://reviews.llvm.org/D27459#614670, @clayborg wrote:
> Part of the reason I like the current "if (log) log->Printf()" is that it doesn't cost you much if logging isn't enabled. So if you have a log line like:
>
> if (log)
> log->Printf("%s %s %s", myStringRef1.str().c_str(), myStringRef2.str().c_str(), myStringRef3.str().c_str());
>
>
> And switch over to using:
>
> LLDB_LOG() << myStringRef1 << " " << myStringRef2 << " " << myStringRef2;
>
>
> You end up doing some work with all of the types regardless of wether the logging is enabled. We tend to do pretty heavy logging in places and I really don't want performance impacted (the expression parser emits a full novel worth of information when logging is enabled), nor would I want people to log less because they are worried about affecting performance.
>
> So any solution should have very minimal cost if logging isn't enabled. We also do log channels, so any design will need to include the ability to log to a channel, any channel, or only if all channels are enabled.
>
> The other thing I don't like about streams is they are harder to read over a printf style log string. I wrote all of dwarfdump and used the full power off C++ streams and I regret doing this as all of the code is really hard to read. I also didn't like the fact that streams maintain state and can affect things down the line. If we adopt LLVM style streams I believe they don't suffer from the C++ streams having state issue. But with C++ you can do this:
Take a look at `llvm::formatv`. I wrote this in LLVM specifically to be the best of both worlds. You get all the flexibility and conciseness of printf with all the type safety of streams. Example:
// Printf style
log->Printf("%d %s %z", 12, "test", (size_t)7);
// Stream style
*log << 12 << "test" << (size_t)7;
// formatv style
*log << llvm::formatv("{0} {1} {2}", 12, "test", (size_t)7);
// alternative formatv sytle
log->Formatv("{0} {1} {2}", 12, "test", (size_t)7);
As you can see, you don't have to specify the type. All the ugliness about `PRIx64`, compiler inconsistencies, platform-dependent sizes, etc all disappear because it deduces the type. And it's even better than this, because you can write custom formatters for your own types. For examples, LLDB has a class called `AddressRange`. With printf you would have to write this `log->Printf("%llu - %llu", range.first(), range.second())', but with `formatv` you can write this: `log->Formatv("{0}", range);` as long as it can find a formatter somewhere. And formatters can define arbitrary style options too, so you could write something like `log->Formatv("{0:abc}", range);` and this string "abc" would get passed to the formatter's format function. This is useful when a type is often formatted different ways (precision, optional fields, etc).
I strongly recommend moving to this for all printf style formatting moving forward.
https://reviews.llvm.org/D27459
More information about the lldb-commits
mailing list