- Thread safe logger.
- Supports multiple log levels.
- Supports custom sinks.
- Supports appending multiple sinks to the logger.
- Supports custom loggers.
- Supports setting runtime log levels.
- Well documented code.
- Can easily extend to support file rotation.
- Write a simple logger which can be used to log messages in a multi threaded environment and demonstrate my understanding of C++.
- Write a logger which is extendable and can be used in production code bases.
- Learn about different design patterns and their use cases.
- Enjoy the process of writing code and learning new things.
Initially I thought of implementing the logger with singleton design pattern but later I realized that it is not a good idea to use singleton in production code bases. So I used dependency injection to write my logger and corresponding sink. It was very fun to write the logger and sink using dependency injection. I'm very happy with the way this project turned out!
- Singleton vs Dependency Injection. Singleton seems like a bad idea for production code bases and has some limitations. So I used dependency injection to write my logging module and corresponding user oddeven service
- Write policies: I have demonstarted two custom sink write policies in my project
- Non blocking lazy writing using two queues in consoleSink
- Synchronous Blocking in fileSink. (Writing to file is faster than console so I chose these policies for the corresponding sinks
- (TODO) Asynchronous writing using a thread pool. If the target I/O (Disk, Remote Storage, Network) is very fast we can go ahead with blocking but if writing to our target is slow we shouldn't block applications for logging. So in that case lazy writing gives optimal performance as the user applications are no longer blocked by I/O.
- Need better string handling. I have used std::string for now. But I need to use a better string library with less copying and better performance.
Tested on Mac OS 13.2.1
#!/bin/bash
make clean
make run
#include <config.hpp>
int main()
{
// You can update custom loggers and custom sinks in config store
std::shared_ptr<IVCLogger> logger = Config().getLogger();
logger->log(VCLogLevel::VCInfo, "First good log");
return 0;
}
.
├── bin # Compiled files (alternatively `dist`)
├── src # Source files application logic oddeven service
├── test # [TODO] Unit Testing. For now I have written a simple test program
├── include # Header files for logger
├── include/interface # Interface files for logger and sink
├── include/sinks # Custom sink implementations
├── include/loggers # Custom logger implementations
├── include/config.hpp # Helps to modify logger configurations and keep source application code clean
├── README.md # This file
├── vcloggerdemo.log # Demo Log file generated by fileSink