NeoMutt  2022-04-29-145-g9b6a0e
Teaching an old dog new tricks
DOXYGEN
logging.c File Reference

Logging Dispatcher. More...

#include "config.h"
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "logging.h"
#include "date.h"
#include "file.h"
#include "memory.h"
#include "message.h"
#include "queue.h"
#include "string2.h"
+ Include dependency graph for logging.c:

Go to the source code of this file.

Functions

static const char * timestamp (time_t stamp)
 Create a YYYY-MM-DD HH:MM:SS timestamp. More...
 
void log_file_close (bool verbose)
 Close the log file. More...
 
int log_file_open (bool verbose)
 Start logging to a file. More...
 
int log_file_set_filename (const char *file, bool verbose)
 Set the filename for the log. More...
 
int log_file_set_level (enum LogLevel level, bool verbose)
 Set the logging level. More...
 
void log_file_set_version (const char *version)
 Set the program's version number. More...
 
bool log_file_running (void)
 Is the log file running? More...
 
int log_disp_file (time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
 Save a log line to a file - Implements log_dispatcher_t -. More...
 
int log_queue_add (struct LogLine *ll)
 Add a LogLine to the queue. More...
 
void log_queue_set_max_size (int size)
 Set a upper limit for the queue length. More...
 
void log_queue_empty (void)
 Free the contents of the queue. More...
 
void log_queue_flush (log_dispatcher_t disp)
 Replay the log queue. More...
 
int log_queue_save (FILE *fp)
 Save the contents of the queue to a temporary file. More...
 
int log_disp_queue (time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
 Save a log line to an internal queue - Implements log_dispatcher_t -. More...
 
int log_disp_terminal (time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
 Save a log line to the terminal - Implements log_dispatcher_t -. More...
 
int log_disp_null (time_t stamp, const char *file, int line, const char *function, enum LogLevel level,...)
 Discard log lines - Implements log_dispatcher_t -. More...
 

Variables

const char * LevelAbbr = "PEWM12345N"
 Abbreviations of logging level names. More...
 
log_dispatcher_t MuttLogger = log_disp_terminal
 The log dispatcher -. More...
 
FILE * LogFileFP = NULL
 Log file handle. More...
 
char * LogFileName = NULL
 Log file name. More...
 
int LogFileLevel = 0
 Log file level. More...
 
char * LogFileVersion = NULL
 Program version. More...
 
static struct LogLineList LogQueue = STAILQ_HEAD_INITIALIZER(LogQueue)
 In-memory list of log lines. More...
 
int LogQueueCount = 0
 Number of entries currently in the log queue. More...
 
int LogQueueMax = 0
 Maximum number of entries in the log queue. More...
 

Detailed Description

Logging Dispatcher.

Authors
  • Richard Russon

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, see http://www.gnu.org/licenses/.

Definition in file logging.c.

Function Documentation

◆ timestamp()

static const char* timestamp ( time_t  stamp)
static

Create a YYYY-MM-DD HH:MM:SS timestamp.

Parameters
stampUnix time
Return values
ptrTimestamp string

If stamp is 0, then the current time will be used.

Note
This function returns a pointer to a static buffer. Do not free it.

Definition at line 77 of file logging.c.

78 {
79  static char buf[23] = { 0 };
80  static time_t last = 0;
81 
82  if (stamp == 0)
83  stamp = mutt_date_epoch();
84 
85  if (stamp != last)
86  {
87  mutt_date_localtime_format(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", stamp);
88  last = stamp;
89  }
90 
91  return buf;
92 }
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:691
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:427
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log_file_close()

void log_file_close ( bool  verbose)

Close the log file.

Parameters
verboseIf true, then log the event

Definition at line 98 of file logging.c.

99 {
100  if (!LogFileFP)
101  return;
102 
103  fprintf(LogFileFP, "[%s] Closing log.\n", timestamp(0));
104  fprintf(LogFileFP, "# vim: syntax=neomuttlog\n");
106  if (verbose)
107  mutt_message(_("Closed log file: %s"), LogFileName);
108 }
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
#define mutt_message(...)
Definition: logging.h:86
FILE * LogFileFP
Log file handle.
Definition: logging.c:54
char * LogFileName
Log file name.
Definition: logging.c:55
static const char * timestamp(time_t stamp)
Create a YYYY-MM-DD HH:MM:SS timestamp.
Definition: logging.c:77
#define _(a)
Definition: message.h:28
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log_file_open()

int log_file_open ( bool  verbose)

Start logging to a file.

Parameters
verboseIf true, then log the event
Return values
0Success
-1Error, see errno

Before opening a log file, call log_file_set_version(), log_file_set_level() and log_file_set_filename().

Definition at line 119 of file logging.c.

120 {
121  if (!LogFileName)
122  return -1;
123 
124  if (LogFileFP)
125  log_file_close(false);
126 
127  if (LogFileLevel < LL_DEBUG1)
128  return -1;
129 
131  if (!LogFileFP)
132  return -1;
133  setvbuf(LogFileFP, NULL, _IOLBF, 0);
134 
135  fprintf(LogFileFP, "[%s] NeoMutt%s debugging at level %d\n", timestamp(0),
137  if (verbose)
138  mutt_message(_("Debugging at level %d to file '%s'"), LogFileLevel, LogFileName);
139  return 0;
140 }
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:618
char * LogFileVersion
Program version.
Definition: logging.c:57
int LogFileLevel
Log file level.
Definition: logging.c:56
void log_file_close(bool verbose)
Close the log file.
Definition: logging.c:98
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
#define NONULL(x)
Definition: string2.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log_file_set_filename()

int log_file_set_filename ( const char *  file,
bool  verbose 
)

Set the filename for the log.

Parameters
fileName to use
verboseIf true, then log the event
Return values
0Success, file opened
-1Error, see errno

Definition at line 149 of file logging.c.

150 {
151  if (!file)
152  return -1;
153 
154  /* also handles both being NULL */
155  if (mutt_str_equal(LogFileName, file))
156  return 0;
157 
159 
160  if (!LogFileName)
161  log_file_close(verbose);
162 
163  return log_file_open(verbose);
164 }
int log_file_open(bool verbose)
Start logging to a file.
Definition: logging.c:119
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:784
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:326
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log_file_set_level()

int log_file_set_level ( enum LogLevel  level,
bool  verbose 
)

Set the logging level.

Parameters
levelLogging level
verboseIf true, then log the event
Return values
0Success
-1Error, level is out of range

The level should be: LL_MESSAGE <= level < LL_MAX.

Definition at line 175 of file logging.c.

176 {
177  if ((level < LL_MESSAGE) || (level >= LL_MAX))
178  return -1;
179 
180  if (level == LogFileLevel)
181  return 0;
182 
183  LogFileLevel = level;
184 
185  if (level == LL_MESSAGE)
186  {
187  log_file_close(verbose);
188  }
189  else if (LogFileFP)
190  {
191  if (verbose)
192  mutt_message(_("Logging at level %d to file '%s'"), LogFileLevel, LogFileName);
193  fprintf(LogFileFP, "[%s] NeoMutt%s debugging at level %d\n", timestamp(0),
195  }
196  else
197  {
198  log_file_open(verbose);
199  }
200 
201  if (LogFileLevel >= LL_DEBUG5)
202  {
203  fprintf(LogFileFP, "\n"
204  "WARNING:\n"
205  " Logging at this level can reveal personal information.\n"
206  " Review the log carefully before posting in bug reports.\n"
207  "\n");
208  }
209 
210  return 0;
211 }
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
@ LL_MESSAGE
Log informational message.
Definition: logging.h:39
@ LL_MAX
Definition: logging.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log_file_set_version()

void log_file_set_version ( const char *  version)

Set the program's version number.

Parameters
versionVersion number

The string will be appended directly to 'NeoMutt', so it should begin with a hyphen.

Definition at line 220 of file logging.c.

221 {
222  mutt_str_replace(&LogFileVersion, version);
223 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log_file_running()

bool log_file_running ( void  )

Is the log file running?

Return values
trueThe log file is running

Definition at line 229 of file logging.c.

230 {
231  return LogFileFP;
232 }
+ Here is the caller graph for this function:

◆ log_queue_add()

int log_queue_add ( struct LogLine ll)

Add a LogLine to the queue.

Parameters
llLogLine to add
Return values
numEntries in the queue

If LogQueueMax is non-zero, the queue will be limited to this many items.

Definition at line 285 of file logging.c.

286 {
287  if (!ll)
288  return -1;
289 
290  STAILQ_INSERT_TAIL(&LogQueue, ll, entries);
291 
292  if ((LogQueueMax > 0) && (LogQueueCount >= LogQueueMax))
293  {
294  ll = STAILQ_FIRST(&LogQueue);
295  STAILQ_REMOVE_HEAD(&LogQueue, entries);
296  FREE(&ll->message);
297  FREE(&ll);
298  }
299  else
300  {
301  LogQueueCount++;
302  }
303  return LogQueueCount;
304 }
static struct LogLineList LogQueue
In-memory list of log lines.
Definition: logging.c:62
int LogQueueMax
Maximum number of entries in the log queue.
Definition: logging.c:65
int LogQueueCount
Number of entries currently in the log queue.
Definition: logging.c:64
#define FREE(x)
Definition: memory.h:43
#define STAILQ_REMOVE_HEAD(head, field)
Definition: queue.h:422
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define STAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:389
char * message
Message to be logged.
Definition: logging.h:79
+ Here is the caller graph for this function:

◆ log_queue_set_max_size()

void log_queue_set_max_size ( int  size)

Set a upper limit for the queue length.

Parameters
sizeNew maximum queue length
Note
size of 0 means unlimited

Definition at line 312 of file logging.c.

313 {
314  if (size < 0)
315  size = 0;
316  LogQueueMax = size;
317 }
+ Here is the caller graph for this function:

◆ log_queue_empty()

void log_queue_empty ( void  )

Free the contents of the queue.

Free any log lines in the queue.

Definition at line 324 of file logging.c.

325 {
326  struct LogLine *ll = NULL;
327  struct LogLine *tmp = NULL;
328 
329  STAILQ_FOREACH_SAFE(ll, &LogQueue, entries, tmp)
330  {
331  STAILQ_REMOVE(&LogQueue, ll, LogLine, entries);
332  FREE(&ll->message);
333  FREE(&ll);
334  }
335 
336  LogQueueCount = 0;
337 }
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
A Log line.
Definition: logging.h:73
+ Here is the caller graph for this function:

◆ log_queue_flush()

void log_queue_flush ( log_dispatcher_t  disp)

Replay the log queue.

Parameters
dispLog dispatcher - Implements log_dispatcher_t

Pass all of the log entries in the queue to the log dispatcher provided. The queue will be emptied afterwards.

Definition at line 346 of file logging.c.

347 {
348  struct LogLine *ll = NULL;
349  STAILQ_FOREACH(ll, &LogQueue, entries)
350  {
351  disp(ll->time, ll->file, ll->line, ll->function, ll->level, "%s", ll->message);
352  }
353 
354  log_queue_empty();
355 }
void log_queue_empty(void)
Free the contents of the queue.
Definition: logging.c:324
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
const char * file
Source file.
Definition: logging.h:75
const char * function
C function.
Definition: logging.h:77
int line
Line number in source file.
Definition: logging.h:76
enum LogLevel level
Log level, e.g. LL_DEBUG1.
Definition: logging.h:78
time_t time
Timestamp of the message.
Definition: logging.h:74
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ log_queue_save()

int log_queue_save ( FILE *  fp)

Save the contents of the queue to a temporary file.

Parameters
fpOpen file handle
Return values
numLines written to the file

The queue is written to a temporary file. The format is:

  • [HH:MM:SS]<LEVEL> FORMATTED-MESSAGE
Note
The caller should delete the file

Definition at line 367 of file logging.c.

368 {
369  if (!fp)
370  return 0;
371 
372  char buf[32];
373  int count = 0;
374  struct LogLine *ll = NULL;
375  STAILQ_FOREACH(ll, &LogQueue, entries)
376  {
377  mutt_date_localtime_format(buf, sizeof(buf), "%H:%M:%S", ll->time);
378  fprintf(fp, "[%s]<%c> %s", buf, LevelAbbr[ll->level + 3], ll->message);
379  if (ll->level <= LL_MESSAGE)
380  fputs("\n", fp);
381  count++;
382  }
383 
384  return count;
385 }
const char * LevelAbbr
Abbreviations of logging level names.
Definition: logging.c:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ LevelAbbr

const char* LevelAbbr = "PEWM12345N"

Abbreviations of logging level names.

Definition at line 45 of file logging.c.

◆ LogFileFP

FILE* LogFileFP = NULL

Log file handle.

Definition at line 54 of file logging.c.

◆ LogFileName

char* LogFileName = NULL

Log file name.

Definition at line 55 of file logging.c.

◆ LogFileLevel

int LogFileLevel = 0

Log file level.

Definition at line 56 of file logging.c.

◆ LogFileVersion

char* LogFileVersion = NULL

Program version.

Definition at line 57 of file logging.c.

◆ LogQueue

struct LogLineList LogQueue = STAILQ_HEAD_INITIALIZER(LogQueue)
static

In-memory list of log lines.

Definition at line 57 of file logging.c.

◆ LogQueueCount

int LogQueueCount = 0

Number of entries currently in the log queue.

Definition at line 64 of file logging.c.

◆ LogQueueMax

int LogQueueMax = 0

Maximum number of entries in the log queue.

Definition at line 65 of file logging.c.