Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

logger: Use thread_local, move config into a function-level static variable #6639

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 89 additions & 48 deletions pdns/logger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,34 @@ extern StatBag S;
#include "lock.hh"
#include "namespaces.hh"

pthread_once_t Logger::s_once;
pthread_key_t Logger::g_loggerKey;

Logger g_log("", LOG_DAEMON);
thread_local Logger::PerThread Logger::t_perThread;

static Logger::Config& getLoggerConfig()
{
/* Since the Logger can be called very early, we need to make sure
that the relevant parts are initialized no matter what, which is tricky
because we can't easily control the initialization order, especially with
built-in backends.
t_perThread is thread_local, so it will be initialized when first accessed,
but we need to make sure that the rest of the config is too, and making
it a function-level static variable achieves that, because it will be
initialized the first time we enter this function at the very last.
*/
static Logger::Config config;
return config;
}

void Logger::log(const string &msg, Urgency u)
{
#ifndef RECURSOR
bool mustAccount(false);
#endif
if(u<=consoleUrgency) {
const auto& config = getLoggerConfig();

if(u <= config.consoleUrgency) {
char buffer[50] = "";
if (d_timestamps) {
if (config.d_timestamps) {
struct tm tm;
time_t t;
time(&t);
Expand All @@ -52,7 +67,7 @@ void Logger::log(const string &msg, Urgency u)
}

string prefix;
if (d_prefixed) {
if (config.d_prefixed) {
switch(u) {
case All:
prefix = "[all] ";
Expand Down Expand Up @@ -91,7 +106,7 @@ void Logger::log(const string &msg, Urgency u)
mustAccount=true;
#endif
}
if( u <= d_loglevel && !d_disableSyslog ) {
if( u <= config.d_loglevel && !config.d_disableSyslog ) {
syslog(u,"%s",msg.c_str());
#ifndef RECURSOR
mustAccount=true;
Expand All @@ -106,75 +121,101 @@ void Logger::log(const string &msg, Urgency u)

void Logger::setLoglevel( Urgency u )
{
d_loglevel = u;
auto& config = getLoggerConfig();
config.d_loglevel = u;
}

void Logger::setFacility(int f)
{
auto& config = getLoggerConfig();

void Logger::toConsole(Urgency u)
config.d_facility = f;
open();
}

void Logger::setFlag(int f)
{
consoleUrgency=u;
auto& config = getLoggerConfig();
config. flags |= f;
open();
}

void Logger::open()
void Logger::disableSyslog(bool d)
{
if(opened)
closelog();
openlog(name.c_str(),flags,d_facility);
opened=true;
auto& config = getLoggerConfig();

config.d_disableSyslog = d;
}

void Logger::setName(const string &_name)
void Logger::setTimestamps(bool t)
{
name=_name;
open();
auto& config = getLoggerConfig();
config.d_timestamps = t;
}

void Logger::initKey()
void Logger::setPrefixed(bool p)
{
if(pthread_key_create(&g_loggerKey, perThreadDestructor))
unixDie("Creating thread key for logger");
auto& config = getLoggerConfig();
config.d_prefixed = p;
}

Logger::Logger(const string &n, int facility) :
name(n), flags(LOG_PID|LOG_NDELAY), d_facility(facility), d_loglevel(Logger::None),
consoleUrgency(Error), opened(false), d_disableSyslog(false)
void Logger::resetFlags()
{
if(pthread_once(&s_once, initKey))
unixDie("Creating thread key for logger");
auto& config = getLoggerConfig();

config.flags = 0;
open();
}

void Logger::toConsole(Urgency u)
{
auto& config = getLoggerConfig();
config.consoleUrgency = u;
}

void Logger::open()
{
auto& config = getLoggerConfig();
if(config.opened) {
closelog();
}

openlog(config.name.c_str(), config.flags, config.d_facility);
config.opened = true;
}

Logger& Logger::operator<<(Urgency u)
void Logger::setName(const string &_name)
{
getPerThread()->d_urgency=u;
return *this;
auto& config = getLoggerConfig();
config.name = _name;
open();
}

void Logger::perThreadDestructor(void* buf)
Logger::Logger(const string &n, int facility)
{
PerThread* pt = (PerThread*) buf;
delete pt;
auto& config = getLoggerConfig();
config.name = n;
config.flags = LOG_PID|LOG_NDELAY;
config.d_facility = facility;

open();
}

Logger::PerThread* Logger::getPerThread()
Logger& Logger::operator<<(Urgency u)
{
void *buf=pthread_getspecific(g_loggerKey);
PerThread* ret;
if(buf)
ret = (PerThread*) buf;
else {
ret = new PerThread();
pthread_setspecific(g_loggerKey, (void*)ret);
}
return ret;
getPerThread().d_urgency = u;
return *this;
}

Logger::PerThread& Logger::getPerThread()
{
return t_perThread;
}

Logger& Logger::operator<<(const string &s)
{
PerThread* pt =getPerThread();
pt->d_output.append(s);
PerThread& pt = getPerThread();
pt.d_output.append(s);
return *this;
}

Expand Down Expand Up @@ -244,11 +285,11 @@ Logger& Logger::operator<<(long i)

Logger& Logger::operator<<(ostream & (&)(ostream &))
{
PerThread* pt =getPerThread();
PerThread& pt = getPerThread();

log(pt->d_output, pt->d_urgency);
pt->d_output.clear();
pt->d_urgency=Info;
log(pt.d_output, pt.d_urgency);
pt.d_output.clear();
pt.d_urgency=Info;
return *this;
}

Expand Down
49 changes: 22 additions & 27 deletions pdns/logger.hh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include <iostream>
#include <sstream>
#include <syslog.h>
#include <pthread.h>

#include "namespaces.hh"
#include "dnsname.hh"
Expand All @@ -42,36 +41,44 @@ public:
enum Urgency {All=32767,Alert=LOG_ALERT, Critical=LOG_CRIT, Error=LOG_ERR, Warning=LOG_WARNING,
Notice=LOG_NOTICE,Info=LOG_INFO, Debug=LOG_DEBUG, None=-1};

struct Config
{
string name;
int flags;
int d_facility;
Urgency d_loglevel{None};
Urgency consoleUrgency{Error};
bool opened{false};
bool d_disableSyslog{false};
bool d_timestamps{true};
bool d_prefixed{false};
};

/** Log a message.
\param msg Message you wish to log
\param u Urgency of the message you wish to log
*/
void log(const string &msg, Urgency u=Notice);

void setFacility(int f){d_facility=f;open();} //!< Choose logging facility
void setFlag(int f){flags|=f;open();} //!< set a syslog flag
void setFacility(int f); //!< Choose logging facility
void setFlag(int f); //!< set a syslog flag
void setName(const string &);

//! set lower limit of urgency needed for console display. Messages of this urgency, and higher, will be displayed
void toConsole(Urgency);
void setLoglevel( Urgency );

void disableSyslog(bool d) {
d_disableSyslog = d;
}
void disableSyslog(bool d);

void setTimestamps(bool t) {
d_timestamps = t;
}
void setTimestamps(bool t);

void setPrefixed(bool p) {
d_prefixed = p;
}
void setPrefixed(bool p);

//! Log to a file.
void toFile( const string & filename );

void resetFlags(){flags=0;open();} //!< zero the flags
void resetFlags(); //!< zero the flags

/** Use this to stream to your log, like this:
\code
g_log<<"This is an informational message"<<endl; // logged at default loglevel (Info)
Expand Down Expand Up @@ -101,22 +108,10 @@ private:
string d_output;
Urgency d_urgency;
};
static void initKey();
static void perThreadDestructor(void *);
PerThread* getPerThread();
PerThread& getPerThread();
void open();

string name;
int flags;
int d_facility;
Urgency d_loglevel;
Urgency consoleUrgency;
bool opened;
bool d_disableSyslog;
bool d_timestamps{true};
bool d_prefixed{false};
static pthread_once_t s_once;
static pthread_key_t g_loggerKey;
static thread_local PerThread t_perThread;
};

extern Logger g_log;
Expand Down