Skip to content

Commit

Permalink
refactor file handlers API and add new RotatingFileHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
odygrd committed Jul 23, 2023
1 parent cc6914d commit e5a3b82
Show file tree
Hide file tree
Showing 42 changed files with 3,432 additions and 969 deletions.
45 changes: 45 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@

## v3.3.0

- Added a get_handler(handler_name) function in Quill.h that allows easy lookup of an existing Handler by name. This
function proves helpful when you want to retrieve a handler and pass it to a new logger.


- Added support for specifying a runtime log level, allowing dynamic log level configuration at runtime.
The new runtime log level feature provides flexibility when needed, with a minor overhead cost.
It is recommended to continue using the existing static log level macros for optimal
Expand Down Expand Up @@ -113,6 +117,47 @@
}
```
- Simplified file handler configuration. Now, instead of passing multiple arguments to the constructor,
you only need to provide a single `FileHandlerOptions` object. This change makes creating file handlers objects
much easier and more flexible.
For example
```c++
quill::FileHandlerConfig file_handler_cfg;
file_handler_cfg.set_open_mode('w');
file_handler_cfg.set_append_to_filename(quill::FilenameAppend::StartDateTime);
std::shared_ptr<quill::Handler> file_handler = quill::file_handler("application.log", file_handler_cfg);
quill::Logger* logger_foo = quill::create_logger("my_logger", std::move(file_handler));
LOG_INFO(my_logger, "Hello from {}", "application");
```

- Combined the functionalities of `RotatingFileHandler` (rotating based on file size) and `TimeRotatingFileHandler`
(rotating on a time interval) into a single, more versatile `RotatingFileHandler`. Users can now conveniently rotate
logs based on both file size and time intervals simultaneously. The updated `RotatingFileHandler` offers a variety of
customization options for improved flexibility. For more information on available configurations,
refer to the `RotatingFileHandlerConfig` documentation.

For example

```c++
// Create a rotating file handler which rotates daily at 18:30 or when the file size reaches 2GB
std::shared_ptr<quill::Handler> file_handler =
quill::rotating_file_handler(filename,
[]()
{
quill::RotatingFileHandlerConfig cfg;
cfg.set_rotation_time_daily("18:30");
cfg.set_rotation_max_file_size(2'000'000'000);
return cfg;
}());

// Create a logger using this handler
quill::Logger* logger_bar = quill::create_logger("daily_logger", std::move(file_handler));
```

## v3.2.0

- Addition of std::is_trivially_copyable<T> to default copy loggable
Expand Down
9 changes: 7 additions & 2 deletions benchmarks/backend_throughput/quill_backend_throughput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,13 @@ int main()
std::this_thread::sleep_for(std::chrono::milliseconds{100});

// Create a file handler to write to a file
std::shared_ptr<quill::Handler> file_handler =
quill::file_handler("quill_backend_total_time.log", "w");
std::shared_ptr<quill::Handler> file_handler = quill::file_handler("quill_backend_total_time.log",
[]()
{
quill::FileHandlerConfig cfg;
cfg.set_open_mode('w');
return cfg;
}());
file_handler->set_pattern("%(ascii_time) [%(thread)] %(fileline) %(level_name) %(message)");
quill::Logger* logger = quill::create_logger("bench_logger", std::move(file_handler));
quill::preallocate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,13 @@ int main()
std::this_thread::sleep_for(std::chrono::milliseconds{100});

// Create a file handler to write to a file
std::shared_ptr<quill::Handler> file_handler =
quill::file_handler("quill_backend_total_time.log", "w");
std::shared_ptr<quill::Handler> file_handler = quill::file_handler("quill_backend_total_time.log",
[]()
{
quill::FileHandlerConfig cfg;
cfg.set_open_mode('w');
return cfg;
}());
file_handler->set_pattern("%(ascii_time) [%(thread)] %(fileline) %(level_name) %(message)");
quill::Logger* logger = quill::create_logger("bench_logger", std::move(file_handler));
quill::preallocate();
Expand Down
8 changes: 7 additions & 1 deletion benchmarks/hot_path_latency/quill_hot_path_rdtsc_clock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ void quill_benchmark(std::vector<int32_t> const& thread_count_array,

// Create a file handler to write to a file
std::shared_ptr<quill::Handler> file_handler =
quill::file_handler("quill_hot_path_rdtsc_clock.log", "w");
quill::file_handler("quill_hot_path_rdtsc_clock.log",
[]()
{
quill::FileHandlerConfig cfg;
cfg.set_open_mode('w');
return cfg;
}());

quill::Logger* logger = quill::create_logger("bench_logger", std::move(file_handler));

Expand Down
8 changes: 7 additions & 1 deletion benchmarks/hot_path_latency/quill_hot_path_system_clock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ void quill_benchmark(std::vector<int32_t> const& thread_count_array,

// Create a file handler to write to a file
std::shared_ptr<quill::Handler> file_handler =
quill::file_handler("quill_hot_path_system_clock.log", "w");
quill::file_handler("quill_hot_path_system_clock.log",
[]()
{
quill::FileHandlerConfig cfg;
cfg.set_open_mode('w');
return cfg;
}());

quill::Logger* logger = quill::create_logger("bench_logger", std::move(file_handler));

Expand Down
15 changes: 11 additions & 4 deletions examples/example_daily_file_rotation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ int main()
{
// Start the backend logging thread
quill::start();

// Create a rotating file handler which rotates daily at 02:00
std::shared_ptr<quill::Handler> file_handler = quill::time_rotating_file_handler(
filename, "w", quill::FilenameAppend::None, "daily", 1, 10, quill::Timezone::LocalTime, "18:30");

// Create a rotating file handler which rotates daily at 18:30 or when the file size reaches 2GB
std::shared_ptr<quill::Handler> file_handler =
quill::rotating_file_handler(filename,
[]()
{
quill::RotatingFileHandlerConfig cfg;
cfg.set_rotation_time_daily("18:30");
cfg.set_rotation_max_file_size(2'000'000'000);
return cfg;
}());

// Create a logger using this handler
quill::Logger* logger_bar = quill::create_logger("daily_logger", std::move(file_handler));
Expand Down
11 changes: 9 additions & 2 deletions examples/example_file_callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,15 @@ class Session
{ std::cout << "after closing " << filename << std::endl; };

// Create a new log file for this session
std::shared_ptr<quill::Handler> file_handler =
quill::file_handler(unique_name + ".log", "a", quill::FilenameAppend::None, std::move(fen));
std::shared_ptr<quill::Handler> file_handler = quill::file_handler(
unique_name + ".log",
[]()
{
quill::FileHandlerConfig cfg;
cfg.set_open_mode('a');
return cfg;
}(),
std::move(fen));

// Create a logger for the current session
_logger = quill::create_logger(unique_name, std::move(file_handler));
Expand Down
12 changes: 10 additions & 2 deletions examples/example_file_rotation.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "quill/Quill.h"

static char const* base_filename = "logfile.log";
static char const* filename = "logfile.log";

int main()
{
Expand All @@ -9,7 +9,15 @@ int main()

// Create a rotating file handler with a max file size per log file and maximum rotation up to 5 times
std::shared_ptr<quill::Handler> file_handler =
quill::rotating_file_handler(base_filename, "w", quill::FilenameAppend::None, 1024, 5);
quill::rotating_file_handler(filename,
[]()
{
quill::RotatingFileHandlerConfig cfg;
cfg.set_rotation_max_file_size(1024);
cfg.set_max_backup_files(5);
cfg.set_overwrite_rolled_files(true);
return cfg;
}());

// Create a logger using this handler
quill::Logger* logger_bar = quill::create_logger("rotating", std::move(file_handler));
Expand Down
8 changes: 7 additions & 1 deletion examples/example_filters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@ int main()
// Get a handler to the file
// The first time this function is called a file handler is created for this filename.
// Calling the function with the same filename will return the existing handler
std::shared_ptr<quill::Handler> file_handler = quill::file_handler("example_filters.log", "w");
std::shared_ptr<quill::Handler> file_handler = quill::file_handler("example_filters.log",
[]()
{
quill::FileHandlerConfig cfg;
cfg.set_open_mode('w');
return cfg;
}());

// Create and add the filter to our handler
file_handler->add_filter(std::make_unique<FileFilter>());
Expand Down
8 changes: 7 additions & 1 deletion examples/example_handler_log_levels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ int main()
// The first time this function is called a file handler is created for this filename.
// Calling the function with the same filename will return the existing handler
std::shared_ptr<quill::Handler> file_handler =
quill::file_handler("example_handler_log_levels.log", "w");
quill::file_handler("example_handler_log_levels.log",
[]()
{
quill::FileHandlerConfig cfg;
cfg.set_open_mode('w');
return cfg;
}());

// Everything is logged in the file
file_handler->set_log_level(quill::LogLevel::TraceL3);
Expand Down
9 changes: 8 additions & 1 deletion examples/example_json_structured_log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,14 @@ int main()

// use the json handler
std::shared_ptr<quill::Handler> json_handler =
quill::json_file_handler("json_output.log", "w", quill::FilenameAppend::DateTime);
quill::json_file_handler("json_output.log",
[]()
{
quill::JsonFileHandlerConfig cfg;
cfg.set_open_mode('w');
cfg.set_append_to_filename(quill::FilenameAppend::StartDateTime);
return cfg;
}());

// Change how the date is formatted in the structured log.
// JsonFileHandler must always have an empty pattern "" as the first argument.
Expand Down
16 changes: 14 additions & 2 deletions examples/example_logging_to_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ void library_foo_create_logger_and_log()
// Get a handler to the file
// The first time this function is called a file handler is created for this filename.
// Calling the function with the same filename will return the existing handler
std::shared_ptr<quill::Handler> file_handler = quill::file_handler(filename, "w");
std::shared_ptr<quill::Handler> file_handler = quill::file_handler(filename,
[]()
{
quill::FileHandlerConfig cfg;
cfg.set_open_mode('w');
return cfg;
}());

// Create a logger using this handler
quill::Logger* logger_foo = quill::create_logger("logger_foo", std::move(file_handler));
Expand All @@ -22,7 +28,13 @@ void library_foo_create_logger_and_log()
void library_bar_create_logger_and_log()
{
// Because foo already created the handler we will get a pointer to the existing handler
std::shared_ptr<quill::Handler> file_handler = quill::file_handler(filename, "w");
std::shared_ptr<quill::Handler> file_handler = quill::file_handler(filename,
[]()
{
quill::FileHandlerConfig cfg;
cfg.set_open_mode('w');
return cfg;
}());

// Create a logger using this handler
quill::Logger* logger_bar = quill::create_logger("logger_bar", std::move(file_handler));
Expand Down
9 changes: 7 additions & 2 deletions examples/example_multiple_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,13 @@ int main()
quill::start();

// Get a handler to the file
std::shared_ptr<quill::Handler> file_handler = quill::file_handler("app.log", "w");
std::shared_ptr<quill::Handler> file_handler = quill::file_handler("app.log",
[]()
{
quill::FileHandlerConfig cfg;
cfg.set_open_mode('w');
return cfg;
}());

// Get the handler to console
std::shared_ptr<quill::Handler> console_handler = quill::stdout_handler();
Expand All @@ -59,5 +65,4 @@ int main()

LOG_INFO(logger_foo, "Hello from {}", "quill");
LOG_DEBUG(logger_foo, "Multiple handlers {}", "example");

}
9 changes: 8 additions & 1 deletion examples/example_trivial_file_logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ int main()
// Get or create a handler to the file
// quill::FilenameAppend::DateTime will append the start date and time to the provided filename
std::shared_ptr<quill::Handler> file_handler =
quill::file_handler("example_trivial.log", "w", quill::FilenameAppend::DateTime);
quill::file_handler("example_trivial.log",
[]()
{
quill::FileHandlerConfig cfg;
cfg.set_open_mode('w');
cfg.set_append_to_filename(quill::FilenameAppend::StartDateTime);
return cfg;
}());

// Optional - Set a custom formatter for this handler, or skip this line to use the default one
file_handler->set_pattern("%(ascii_time) [%(process)] [%(thread)] %(logger_name) - %(message)", // format
Expand Down
2 changes: 0 additions & 2 deletions quill/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ set(HEADER_FILES
include/quill/handlers/NullHandler.h
include/quill/handlers/RotatingFileHandler.h
include/quill/handlers/StreamHandler.h
include/quill/handlers/TimeRotatingFileHandler.h

include/quill/Config.h
include/quill/Fmt.h
Expand Down Expand Up @@ -81,7 +80,6 @@ set(SOURCE_FILES
src/handlers/JsonFileHandler.cpp
src/handlers/RotatingFileHandler.cpp
src/handlers/StreamHandler.cpp
src/handlers/TimeRotatingFileHandler.cpp

src/LogLevel.cpp
src/PatternFormatter.cpp
Expand Down
4 changes: 3 additions & 1 deletion quill/include/quill/Logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,9 @@ class alignas(detail::CACHE_LINE_ALIGNED) Logger
std::addressof(_logger_details),
(_logger_details.timestamp_clock_type() == TimestampClockType::Tsc) ? quill::detail::rdtsc()
: (_logger_details.timestamp_clock_type() == TimestampClockType::System)
? static_cast<uint64_t>(std::chrono::system_clock::now().time_since_epoch().count())
? static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count())
: _custom_timestamp_clock->now());

write_buffer += sizeof(detail::Header);
Expand Down
Loading

0 comments on commit e5a3b82

Please sign in to comment.