You're doing printf and fprintf twice for the same arguments.
So, it's replicating code.
*printf is somewhat heavyweight. So, I'd do sprintf [or snprintf] to a buffer (e.g):
len = sprintf(buf,...);
And then do:
fwrite(buf,1,len,stdout);
if (__log_filestream)
fwrite(buf,1,len,__log_filestream);
The overhead of using the buffer is less than calling a printf function twice. I'd repeat the same buffering for the vprintf/vfprintf
Or, better yet, just keep concatenating to the buffer and do a single [pair of] fwrite at the end. This is [yet] better performance.
And, this is especially helpful if there are multiple threads doing logging because the given log message will come out on a single line (e.g.):
threadA timestamp | threadA message
threadB timestamp | threadB message
With two separate writes to a stream, two threads could intersperse partial parts of their message [not nearly as nice]:
threadA timestamp
threadB timestamp
threadA message
threadB message
If this function is the only function writing to the logfile and/or stdout, you might get even better performance by using write instead of fwrite [YMMV]
Here's how I would refactor the code [and, if you're paranoid, you could use snprintf]:
// The function
void
log(int lvl,const char *format,...)
{
va_list args;
char buf[1000];
char *cur = buf;
// If lvl < 0 the prefix will not be used
if (lvl >= lINFO) {
time_t now = time(NULL);
struct tm tm = *localtime(&now);
// timestamp message common for both streams
cur += sprintf(cur,"[%d-%02d-%02d %02d:%02d:%02d %s] [%s] : ",
tm.tm_year + 1900,tm.tm_mon + 1,tm.tm_mday,
tm.tm_hour,tm.tm_min,tm.tm_sec,
__log_name,parse_lvl(lvl));
}
va_start(args,format);
cur += vsprintf(cur,format,args);
va_end(args);
*cur++ = '\n';
*cur = 0;
size_t len = cur - buf;
// Printing to the console
fwrite(buf,1,len,stdout);
// Printing into the file
if (__log_filestream)
fwrite(buf,1,len,__log_filestream);
}