Format log with a small macro logger The goal of this code is to format any log to STDOUT and STDERR with the file and the line of where the call is made. I took inspiration from different C loggers that I found on the internet. I want it to be small and efficient while using C++17.

I'm a bit suspicious about the call to std::data at line 30 not being null-terminated.

#include &lt;iostream&gt;
#include &lt;string_view&gt;
#include &lt;array&gt;

enum Log_level
{
    L_SILENT = 0,
    L_ERROR = 1,
    L_INFO = 2,
    L_DEBUG = 3,
};

static Log_level log_level = L_ERROR;

static constexpr std::array log_colors 
{
    "",
    "\x1B[1;31m",
    "\x1B[1;34m",
    "\x1B[1;30m"
};

template&lt;typename... Args&gt;
void vlk_log_internal(const Log_level level, const std::string_view s, Args... args)
{
    std::FILE* output = (level == L_ERROR ? stderr : stdout);
    if (level &lt;= log_level)
    {
        std::fprintf(output, "%s", log_colors[level]);
        std::fprintf(output, std::data(s), args...);
        std::fprintf(output, "\x1B[0m");
        std::fprintf(output, "\n");
    }
}

#define vlk_log(lvl, msg, ...) { vlk_log_internal(lvl, "[%s:%d] " msg, __FILE__, __LINE__, ##__VA_ARGS__); } (void)0

int main()
{
    log_level = L_SILENT;

    vlk_log(L_ERROR, "Error will not show");

    log_level = L_ERROR;

    vlk_log(L_ERROR, "Error %s", "msg");
    vlk_log(L_INFO, "Info will not show");

    log_level = L_INFO;

    vlk_log(L_INFO, "Info %s", "msg");
    vlk_log(L_DEBUG, "Debug will not show");

    log_level = L_DEBUG;

    vlk_log(L_DEBUG, "Debug %s", "msg");

    return 0;   
}


Compiler Explorer link
Looking at the code, it is clear that you took a part from existing C code.
Overal the code is acceptable, although when I should accept it, I would recommend some changes.

As already indicated in another answer, you could use scoped enums. This would remove the L_ prefix, unfortunately if you would use &lt;windows.h&gt;, you have to find a new name for ERROR.

The log_colors variable uses some strings to color the terminal. A comment about the actual colors would be nice.  Separate variables with clear names even better.

vlk_log_internal accepts variadic arguments, which is really good. You could use forwarding references to prevent expensive copies.

The output variable looks strange outside of the if-statement, you could move it in or introduce early return instead.

std::fprintf, is strange in C++ code, I mostly try to get rid of it. This because you have to know the ugly syntax of format strings and it is easy to make mistakes as passing an std::string instead of the char-ptr.
This even leaks into your API.

Next up, you have a define which has to hide the function.
You even nicely put something at the end to allow a semicolon. I don't like, however the other constants force you.

PS: I don't see std::data