in src/log.c [536:683]
QD_EXPORT qd_error_t qd_log_entity(qd_entity_t *entity)
{
qd_error_clear();
char* module = 0;
char *outputFile = 0;
char *enable = 0;
int include_timestamp = 0;
int include_source = 0;
bool has_enable = false;
bool has_output_file = false;
bool has_include_timestamp = false;
bool has_include_source = false;
bool is_sink_syslog = false;
bool trace_enabled = false;
bool error_in_output = false;
bool error_in_enable = false;
do {
//
// A module attribute MUST be specified for a log entity.
// Every other attribute is optional.
//
module = qd_entity_get_string(entity, "module");
//
// If the module is not specified, there is nothing to do, just log an
// error and break out of this do loop.
//
QD_ERROR_BREAK();
//
// Obtain all attributes from the entity before obtaining the log_source_lock.
// We do this because functions like qd_entity_get_string and qd_entity_get_bool ultimately call qd_vlog_impl() which
// also holds the log_source_lock when calling write_log().
//
if (qd_entity_has(entity, "outputFile")) {
has_output_file = true;
outputFile = qd_entity_get_string(entity, "outputFile");
QD_ERROR_BREAK();
}
if (qd_entity_has(entity, "enable")) {
has_enable = true;
enable = qd_entity_get_string(entity, "enable");
QD_ERROR_BREAK();
}
if (qd_entity_has(entity, "includeTimestamp")) {
has_include_timestamp = true;
include_timestamp = qd_entity_get_bool(entity, "includeTimestamp");
QD_ERROR_BREAK();
}
if (qd_entity_has(entity, "includeSource")) {
has_include_source = true;
include_source = qd_entity_get_bool(entity, "includeSource");
QD_ERROR_BREAK();
}
//
// Obtain the log_source_lock lock. This lock is also used when write_log() is called.
//
sys_mutex_lock(log_source_lock);
qd_log_source_t *src = qd_log_source_lh(module); /* The original(already existing) log source */
if (has_output_file) {
log_sink_t* sink = log_sink_lh(outputFile);
if (!sink) {
error_in_output = true;
sys_mutex_unlock(log_source_lock);
break;
}
// DEFAULT source may already have a sink, so free the old sink first
if (src->sink) {
log_sink_free_lh(src->sink);
}
// Assign the new sink
src->sink = sink;
if (src->sink->syslog) {
// Timestamp should be off for syslog.
is_sink_syslog = true;
src->includeTimestamp = 0;
}
}
if (has_enable) {
int mask = enable_mask(enable);
if (mask < -1) {
error_in_enable = true;
sys_mutex_unlock(log_source_lock);
break;
}
else {
src->mask = mask;
}
if (qd_log_enabled(src, QD_LOG_TRACE)) {
trace_enabled = true;
}
}
if (has_include_timestamp && !is_sink_syslog) {
// Timestamp should be off for syslog.
src->includeTimestamp = include_timestamp;
}
if (has_include_source) {
src->includeSource = include_source;
}
sys_mutex_unlock(log_source_lock);
} while(0);
if (error_in_output) {
char msg[TEXT_MAX];
snprintf(msg, sizeof(msg), "Failed to open log file '%s'", outputFile);
qd_error(QD_ERROR_CONFIG, "%s", msg);
}
if (error_in_enable) {
qd_error(QD_ERROR_CONFIG, "'%s' is not a valid log level. Should be one of {%s}.", enable, level_names);
}
if (module)
free(module);
if (outputFile)
free(outputFile);
if (enable)
free(enable);
//
// If trace logging is enabled, loop thru all connections in the router and call the pn_transport_set_tracer callback
// so proton frame trace can be output as part of the router trace log.
//
if (trace_enabled) {
qd_server_trace_all_connections();
}
return qd_error_code();
}