I have implemented my own logger based pimpl idiom. As a third party lib, I used spd log. My focus is to provide an interface to the end user who wants to print multiple parameters at once. I also used fold expression and ostringstream to streamline any primitive type of parameter. I would be grateful if you could provide me with your feedback.
//main.cpp
#include <logger.hpp>
int main() {
    logger _logger(logger::trace);
    _logger.LOG(logger::debug, "test1", "test2", 1, 2, 3.1, 'X');
    return 0;
}
//logger.hpp
#pragma once
#include <memory>
#include <sstream>
class logger {
public:
    enum level_enum : int {
        trace = 0,
        debug = 1,
        info = 2,
        warn = 3,
        err = 4,
        critical = 5,
        off = 6,
        n_levels
    };
    explicit logger(logger::level_enum level);
    ~logger();
    template <typename... T>
    void LOG(level_enum level, T... msg) {
        auto stream = dump(std::forward<T>(msg)...);
        print(level, stream);
    }
    template <typename... T>
    std::ostringstream dump(T... msg) {
        std::ostringstream stream;
        ((stream << msg << ' '), ...);
        return stream;
    }
    void print(level_enum level, std::ostringstream& stream);
private:
    class Impl;
    std::unique_ptr<Impl> pImpl;
};
//spd_logger.cpp
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/stdout_color_sinks.h"
#include "spdlog/spdlog.h"
#include <logger.hpp>
#include <memory>
class logger::Impl {
    std::shared_ptr<spdlog::logger> logger;
public:
    explicit Impl(spdlog::level::level_enum level) {
        logger = std::make_shared<spdlog::logger>("LOG");
        logger->sinks().push_back(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
        logger->sinks().push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>("logs/basic_sink.txt"));
        logger->set_level(level);
    }
    void log(logger::level_enum level, std::ostringstream& msg) {
        logger->log(static_cast<spdlog::level::level_enum>(level), msg.str());
    }
};
logger::logger(logger::level_enum level)
        : pImpl(std::make_unique<Impl>(static_cast<spdlog::level::level_enum>(level))) {}
logger::~logger() = default;
void logger::print(level_enum level, std::ostringstream& msg) {
    this->pImpl->log(level, msg);
}