Select Git revision
scheduler.py
logging.c 8.73 KiB
/*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* logging.c
*
* Copyright (C) 2011-2022, University of Vienna and Vienna Institute for Nature Conservation & Analyses, Andreas Gattringer.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include "logging.h"
#include "memory/cats_memory.h"
#include "cats_time/cats_time.h"
#include "misc/misc.h"
enum cats_log_level internal_current_log_level = LOG_INFO;
int32_t logging_mpi_rank = -1;
struct cats_time cats_logging_start_time;
FILE *cats_log_file = NULL;
char *cats_log_file_name = NULL;
const char *logging_module_name = NULL;
bool time_initialized = false;
bool logging_quiet = false;
const char *get_log_level_name(enum cats_log_level level)
{
switch (level) {
case LOG_DEBUG:
return " DBG";
case LOG_INFO:
return "INFO";
case LOG_RAW:
case LOG_EMPTY:
return "";
case LOG_MARK:
return "";
case LOG_IMPORTANT:
return "IMPT";
case LOG_WARNING:
return "WARN";
case LOG_ERROR:
return " ERR";
case LOG_MPI:
return " MPI";
case LOG_UNIMPLEMENTED:
return "NOT IMPLEMENTED";
case LOG_UNKNOWN:
return "UNKN";
}
return "UNKN";
}
const char *get_log_level_color(enum cats_log_level level)
{
switch (level) {
case LOG_RAW:
case LOG_DEBUG:
return C_RESET;
case LOG_INFO:
return C_RESET;
case LOG_EMPTY:
return C_RESET;
case LOG_MARK:
return C_RESET;
case LOG_IMPORTANT:
return C_YELLOW;
case LOG_WARNING:
return C_YELLOW;
case LOG_ERROR:
return C_RED;
case LOG_MPI:
return C_RED;
case LOG_UNIMPLEMENTED:
return C_RED;
case LOG_UNKNOWN:
return C_RED;
}
return C_RESET;
}
void set_log_level(enum cats_log_level new_level)
{
internal_current_log_level = new_level;
}
// - mpi world rank can be added later
// FIXME: if start_time is NULL, generate
void logging_initialize(enum cats_log_level level, const struct cats_time *start_time, const char *log_file_name, bool quiet)
{
set_log_level(level);
logging_quiet = quiet;
if (start_time != NULL) {
cats_logging_start_time = *start_time;
time_initialized = true;
}
if (log_file_name != NULL) {
cats_log_file_name = strdup(log_file_name);
cats_log_file = fopen(log_file_name, "w");
ENSURE_FILE_OPENED(cats_log_file, cats_log_file_name)
}
}
void logging_set_module_name(const char *name)
{
logging_module_name = name;
}
void logging_set_mpi_rank(int mpi_world_rank)
{
logging_mpi_rank = mpi_world_rank;
}
// actual logging function(s), only to be called from log_message
void log_msg(const char *msg, enum cats_log_level loglevel);
void log_msg_simple(const char *msg, enum cats_log_level loglevel);
// logging wrapper function
__attribute__ ((__format__ (__printf__, 2, 3)))
void log_message(enum cats_log_level level, const char *fmt, ...)
{
if (level < internal_current_log_level) return;
char *message = NULL;
va_list arg_p;
va_start(arg_p, fmt);
int count = vsnprintf(NULL, 0, fmt, arg_p) + 1;
va_end(arg_p);
message = malloc_or_die(count);
va_start(arg_p, fmt);
vsnprintf(message, count, fmt, arg_p);
va_end(arg_p);
log_msg(message, level);
free(message);
}
enum cats_log_level get_log_level(void)
{
return internal_current_log_level;
}
void log_message_simple(enum cats_log_level level, const char *fmt, ...)
{
if (level < internal_current_log_level) return;
char *message = NULL;
va_list arg_p;
va_start(arg_p, fmt);
int count = vsnprintf(NULL, 0, fmt, arg_p) + 1;
va_end(arg_p);
message = malloc_or_die(count);
va_start(arg_p, fmt);
vsnprintf(message, count, fmt, arg_p);
va_end(arg_p);
log_msg_simple(message, level);
free(message);
}
void log_msg(const char *msg, enum cats_log_level loglevel)
{
if (loglevel < internal_current_log_level) return;
if (loglevel == LOG_RAW) {
if (! logging_quiet) fprintf(stdout, "%s", msg);
if (cats_log_file != NULL) fprintf(cats_log_file, "%s", msg);
return;
}
if (loglevel == LOG_EMPTY) {
if (! logging_quiet) fprintf(stdout, "\n");
if (cats_log_file != NULL) fprintf(cats_log_file, "\n");
return;
}
const char *color = get_log_level_color(loglevel);
if (loglevel == LOG_MARK) {
if (! logging_quiet) fprintf(stdout, "%s%s%s\n", color, msg, C_RESET);
if (cats_log_file != NULL) fprintf(cats_log_file, "%s%s%s\n", color, msg, C_RESET);
return;
}
const char *log_default = "unknown";
const char *loglevel_name = log_default;
if (loglevel <= LOG_UNKNOWN && loglevel >= LOG_DEBUG) {
loglevel_name = get_log_level_name(loglevel);
}
if (logging_mpi_rank >= 0) {
if (! logging_quiet) fprintf(stdout, "(%02d)::", logging_mpi_rank);
if (cats_log_file != NULL) fprintf(cats_log_file, "(%02d)::", logging_mpi_rank);
}
if (time_initialized) {
double secs = seconds_monotonic_since(&cats_logging_start_time);
if (cats_log_file != NULL) {
fprintf(cats_log_file, "% 16.4f::", secs);
}
if (! logging_quiet) fprintf(stdout, "% 16.4f::", secs);
} else {
if (cats_log_file != NULL) {
fprintf(cats_log_file, " ::");
}
if (! logging_quiet) fprintf(stdout, " ::");
}
if (logging_module_name != NULL) {
if (! logging_quiet) fprintf(stdout, "%s%s::[%s] %s%s\n", color, loglevel_name, logging_module_name, msg, C_RESET);
if (cats_log_file) fprintf(cats_log_file, "%s%s::[%s] %s%s\n", color, loglevel_name, logging_module_name, msg, C_RESET);
} else {
if (! logging_quiet) fprintf(stdout, "%s%s::%s%s\n", color, loglevel_name, msg, C_RESET);
if (cats_log_file) fprintf(cats_log_file, "%s%s::%s%s\n", color, loglevel_name, msg, C_RESET);
}
}
void log_msg_simple(const char *msg, enum cats_log_level loglevel)
{
if (loglevel < internal_current_log_level) return;
const char *log_default = "unknown";
const char *loglevel_name = log_default;
if (loglevel <= LOG_UNKNOWN && loglevel >= LOG_DEBUG) {
loglevel_name = get_log_level_name(loglevel);
}
const char *color = get_log_level_color(loglevel);
if (logging_mpi_rank >= 0) {
if (! logging_quiet) fprintf(stdout, "(%02d)%s%s: %s%s", logging_mpi_rank, color, loglevel_name, msg, C_RESET);
if (cats_log_file != NULL) fprintf(cats_log_file, "(%02d)%s%s: %s%s", logging_mpi_rank, color, loglevel_name, msg, C_RESET);
} else {
if (! logging_quiet) fprintf(stdout, "%s%s::%s%s\n", color, loglevel_name, msg, C_RESET);
if (cats_log_file != NULL) fprintf(cats_log_file, "%s%s::%s%s\n", color, loglevel_name, msg, C_RESET);
}
}