Add a +editor flag to YABRIDGE_DEBUG_LEVEL

This commit is contained in:
Robbert van der Helm
2021-07-20 02:48:12 +02:00
parent 9fcf91dc72
commit a1cb3b614b
4 changed files with 80 additions and 34 deletions
+4
View File
@@ -16,6 +16,10 @@ Versioning](https://semver.org/spec/v2.0.0.html).
shared memory for processing audio in plugins with a lot of inputs or outputs. shared memory for processing audio in plugins with a lot of inputs or outputs.
- Also added a warning for thisq in the initialization message if yabridge - Also added a warning for thisq in the initialization message if yabridge
detects a low value for `RLIMIT_MEMLOCK`. detects a low value for `RLIMIT_MEMLOCK`.
- Added a `+editor` flag to the `YABRIDGE_DEBUG_LEVEL` environment variable that
can be combined with any debug level to also print debug tracing information
about the plugin editor window. This can be useful for diagnosing DAW or
window manager specific issues.
### Fixed ### Fixed
+4 -2
View File
@@ -784,8 +784,10 @@ offers these two environment variables to control yabridge's logging facilities:
`env YABRIDGE_DEBUG_FILE=/tmp/yabridge.log <daw>`, and then use `env YABRIDGE_DEBUG_FILE=/tmp/yabridge.log <daw>`, and then use
`tail -F /tmp/yabridge.log` to keep track of the output. If this option is not `tail -F /tmp/yabridge.log` to keep track of the output. If this option is not
present then yabridge will write all of its debug output to STDERR instead. present then yabridge will write all of its debug output to STDERR instead.
- `YABRIDGE_DEBUG_LEVEL={0,1,2}` allows you to set the verbosity of the debug - `YABRIDGE_DEBUG_LEVEL={0,1,2}{,+editor}` allows you to set the verbosity of
information. Each level increases the amount of debug information printed: the debug information. You can set a debug level, optionally followed by
`+editor` to also get more debug output related to the editor window handling.
Each level increases the amount of debug information printed:
- A value of `0` (the default) means that yabridge will only log the output - A value of `0` (the default) means that yabridge will only log the output
from the Wine process and some basic information about the from the Wine process and some basic information about the
+37 -25
View File
@@ -41,21 +41,39 @@ constexpr char logging_file_environment_variable[] = "YABRIDGE_DEBUG_FILE";
constexpr char logging_verbosity_environment_variable[] = constexpr char logging_verbosity_environment_variable[] =
"YABRIDGE_DEBUG_LEVEL"; "YABRIDGE_DEBUG_LEVEL";
/**
* The `YABRIDGE_DEBUG_LEVEL` flag for enabling editor tracing.
*/
constexpr char editor_tracing_flag[] = "+editor";
Logger::Logger(std::shared_ptr<std::ostream> stream, Logger::Logger(std::shared_ptr<std::ostream> stream,
Verbosity verbosity_level, Verbosity verbosity_level,
bool editor_tracing,
std::string prefix, std::string prefix,
bool prefix_timestamp) bool prefix_timestamp)
: verbosity(verbosity_level), : verbosity(verbosity_level),
editor_tracing(editor_tracing),
stream(stream), stream(stream),
prefix(prefix), prefix(prefix),
prefix_timestamp(prefix_timestamp) {} prefix_timestamp(prefix_timestamp) {}
Logger Logger::create_from_environment(std::string prefix) { Logger Logger::create_from_environment(std::string prefix,
std::shared_ptr<std::ostream> stream) {
bp::environment env = boost::this_process::environment(); bp::environment env = boost::this_process::environment();
std::string file_path = env[logging_file_environment_variable].to_string(); const std::string file_path =
env[logging_file_environment_variable].to_string();
std::string verbosity = std::string verbosity =
env[logging_verbosity_environment_variable].to_string(); env[logging_verbosity_environment_variable].to_string();
// Editor debug tracing is an optional flag that can be added to any debug
// level (and technically it will also work fine if it's the only option,
// but you're not supposed to do that ;))
const bool editor_tracing = verbosity.ends_with(editor_tracing_flag);
if (editor_tracing) {
verbosity =
verbosity.substr(0, verbosity.size() - strlen(editor_tracing_flag));
}
// Default to `Verbosity::basic` if the environment variable has not // Default to `Verbosity::basic` if the environment variable has not
// been set or if it is not an integer. // been set or if it is not an integer.
Verbosity verbosity_level; Verbosity verbosity_level;
@@ -65,41 +83,35 @@ Logger Logger::create_from_environment(std::string prefix) {
verbosity_level = Verbosity::basic; verbosity_level = Verbosity::basic;
} }
if (!stream) {
// If `file` points to a valid location then use create/truncate the // If `file` points to a valid location then use create/truncate the
// file and write all of the logs there, otherwise use STDERR // file and write all of the logs there, otherwise use STDERR
auto log_file = std::make_shared<std::ofstream>( const auto log_file = std::make_shared<std::ofstream>(
file_path, std::fstream::out | std::fstream::app); file_path, std::fstream::out | std::fstream::app);
if (log_file->is_open()) { if (log_file->is_open()) {
return Logger(log_file, verbosity_level, prefix); stream = log_file;
return Logger(log_file, verbosity_level, editor_tracing, prefix);
} else { } else {
// For STDERR we sadly can't just use `std::cerr`. In the group process // For STDERR we sadly can't just use `std::cerr`. In the group
// we need to capture all output generated by the process itself, and // process we need to capture all output generated by the process
// the only way to do this is by reopening the STDERR and STDOUT streams // itself, and the only way to do this is by reopening the STDERR
// to a pipe. Luckily `/dev/stderr` stays unaffected, so we can still // and STDOUT streams to a pipe. Luckily `/dev/stderr` stays
// write there without causing infinite loops. // unaffected, so we can still write there without causing infinite
return Logger(std::make_shared<std::ofstream>( // loops.
"/dev/stderr", std::fstream::out | std::fstream::app), stream = std::make_shared<std::ofstream>(
verbosity_level, prefix); "/dev/stderr", std::fstream::out | std::fstream::app);
} }
} }
return Logger(stream, verbosity_level, editor_tracing, prefix);
}
Logger Logger::create_wine_stderr() { Logger Logger::create_wine_stderr() {
bp::environment env = boost::this_process::environment();
std::string verbosity =
env[logging_verbosity_environment_variable].to_string();
Verbosity verbosity_level;
try {
verbosity_level = static_cast<Verbosity>(std::stoi(verbosity));
} catch (const std::invalid_argument&) {
verbosity_level = Verbosity::basic;
}
// We're logging directly to `std::cerr` instead of to `/dev/stderr` because // We're logging directly to `std::cerr` instead of to `/dev/stderr` because
// we want the STDERR redirection from the group host processes to still // we want the STDERR redirection from the group host processes to still
// function here // function here
return Logger(std::shared_ptr<std::ostream>(&std::cerr, [](auto*) {}), return create_from_environment(
verbosity_level, "", false); "", std::shared_ptr<std::ostream>(&std::cerr, [](auto*) {}));
} }
void Logger::log(const std::string& message) { void Logger::log(const std::string& message) {
+30 -2
View File
@@ -96,6 +96,9 @@ class Logger {
* @param verbosity_level The verbosity of the logging, see the * @param verbosity_level The verbosity of the logging, see the
* `Logger::Verbosity` constants above for a description of the verbosity * `Logger::Verbosity` constants above for a description of the verbosity
* levels. * levels.
* @param editor_tracing Whether we should enable debug tracing for the
* editor window handling. If we end up adding more of these options, we
* should move to a bitfield or something.
* @param prefix An optional prefix for the logger. Useful for differentiate * @param prefix An optional prefix for the logger. Useful for differentiate
* messages coming from the Wine VST host. Should end with a single space * messages coming from the Wine VST host. Should end with a single space
* character. * character.
@@ -107,6 +110,7 @@ class Logger {
*/ */
Logger(std::shared_ptr<std::ostream> stream, Logger(std::shared_ptr<std::ostream> stream,
Verbosity verbosity_level, Verbosity verbosity_level,
bool editor_tracing,
std::string prefix = "", std::string prefix = "",
bool prefix_timestamp = true); bool prefix_timestamp = true);
@@ -116,8 +120,12 @@ class Logger {
* *
* @param prefix A message to prepend for every log message, useful to * @param prefix A message to prepend for every log message, useful to
* differentiate between the Wine process and the Linux VST plugin. * differentiate between the Wine process and the Linux VST plugin.
* @param stream If specified, disregard `YABRIDGE_DEBUG_FILE` and output
* the log to this stream isntead.
*/ */
static Logger create_from_environment(std::string prefix = ""); static Logger create_from_environment(
std::string prefix = "",
std::shared_ptr<std::ostream> stream = nullptr);
/** /**
* Create a special logger instance that outputs directly to STDERR without * Create a special logger instance that outputs directly to STDERR without
@@ -173,7 +181,21 @@ class Logger {
*/ */
template <invocable_returning<std::string> F> template <invocable_returning<std::string> F>
void log_trace(F&& fn) { void log_trace(F&& fn) {
if (verbosity >= Verbosity::all_events) { if (verbosity >= Verbosity::all_events) [[unlikely]] {
log(fn());
}
}
/**
* Log a message that should only be printed when the `editor_tracing`
* option is enabled. This can be useful to provide debugging information
* for weird setup-specific bugs.
*
* @param message A lambda producing a string that should be written.
*/
template <invocable_returning<std::string> F>
void log_editor_trace(F&& fn) {
if (editor_tracing) [[unlikely]] {
log(fn()); log(fn());
} }
} }
@@ -184,6 +206,12 @@ class Logger {
*/ */
const Verbosity verbosity; const Verbosity verbosity;
/**
* If this is set to true, then we'll print debug traces for the plugin
* editor.
*/
const bool editor_tracing;
private: private:
/** /**
* The output stream to write the log messages to. Typically either STDERR * The output stream to write the log messages to. Typically either STDERR