RocketLogger  2.0.1
log.c
Go to the documentation of this file.
1 
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <time.h>
36 
37 #include "log.h"
38 
42 static char log_filename[RL_LOG_PATH_LENGTH_MAX] = RL_LOG_DEFAULT_FILE;
43 
47 static rl_log_level_t log_verbosity = RL_LOG_VERBOSE;
48 
49 int rl_log_init(char const *const log_file, rl_log_level_t verbosity) {
50  // update log configuration
51  rl_log_verbosity(verbosity);
52  strncpy(log_filename, log_file, sizeof(log_filename) - 1);
53 
54  // open log file (create inexistent) to check for max file size
55  FILE *log_fp = fopen(log_filename, "a");
56  if (log_fp == NULL) {
57  printf("Error: failed to open log file\n");
58  return -1;
59  }
60 
61  // reset the log file if it is getting large
62  if (ftell(log_fp) > RL_LOG_FILE_SIZE_MAX) {
63  log_fp = freopen(log_filename, "w", log_fp);
64  if (log_fp == NULL) {
65  printf("Error: failed to reset log file size\n");
66  return -1;
67  }
68  }
69 
70  // write header for new (empty) file, or empty line for existing file
71  if (ftell(log_fp) == 0) {
72  fprintf(log_fp, "# RocketLogger Log File\n");
73  }
74 
75  // close log file
76  fclose(log_fp);
77  return 0;
78 }
79 
80 void rl_log_verbosity(rl_log_level_t verbosity) { log_verbosity = verbosity; }
81 
82 int rl_log(rl_log_level_t log_level, char const *const format, ...) {
83  // do not handle ignore log level
84  if (log_level == RL_LOG_IGNORE) {
85  return 0;
86  }
87 
88  // log only if log level is equal or higher than configured verbosity
89  if (log_level > log_verbosity) {
90  return 0;
91  }
92 
93  // get arguments
94  va_list args;
95  va_start(args, format);
96 
97  // get current time
98  time_t time_raw;
99  struct tm *time_info;
100  char time_str[24];
101 
102  time(&time_raw);
103  time_info = gmtime(&time_raw);
104  strftime(time_str, sizeof(time_str), "%F %T\t", time_info);
105 
106  // open log file
107  FILE *log_fp = fopen(log_filename, "a");
108  if (log_fp == NULL) {
109  printf("Error: failed to open log file\n");
110  return -1;
111  }
112 
113  // write time, log level, and message to log file
114  fprintf(log_fp, "%s", time_str);
115  switch (log_level) {
116  case RL_LOG_ERROR:
117  fprintf(log_fp, "ERROR\t");
118  break;
119  case RL_LOG_WARNING:
120  fprintf(log_fp, "WARN\t");
121  break;
122  case RL_LOG_INFO:
123  fprintf(log_fp, "INFO\t");
124  break;
125  case RL_LOG_VERBOSE:
126  fprintf(log_fp, "VERB\t");
127  break;
128  default:
129  // for debugging purposes
130  fprintf(log_fp, "N/A\t");
131  printf("Error: unsupported log level with message:\n ");
132  break;
133  }
134  vfprintf(log_fp, format, args);
135  fprintf(log_fp, "\n");
136 
137  // close file
138  fclose(log_fp);
139 
140  // output to terminal
141  switch (log_level) {
142  case RL_LOG_ERROR:
143  printf("Error: ");
144  break;
145  case RL_LOG_WARNING:
146  printf("Warning: ");
147  break;
148  case RL_LOG_INFO:
149  printf("Info: ");
150  break;
151  case RL_LOG_VERBOSE:
152  printf("Verbose: ");
153  break;
154  default:
155  // skip handled above
156  break;
157  }
158  vprintf(format, args);
159  printf("\n");
160 
161  // facilitate return
162  va_end(args);
163 
164  return 0;
165 }
void rl_log_verbosity(rl_log_level_t verbosity)
Definition: log.c:80
int rl_log(rl_log_level_t log_level, char const *const format,...)
Definition: log.c:82
int rl_log_init(char const *const log_file, rl_log_level_t verbosity)
Definition: log.c:49
#define RL_LOG_FILE_SIZE_MAX
Maximum log file size in bytes.
Definition: log.h:42
#define RL_LOG_DEFAULT_FILE
Default log file name.
Definition: log.h:36
#define RL_LOG_PATH_LENGTH_MAX
Maximum log file name path length.
Definition: log.h:39
enum rl_log_level rl_log_level_t
Definition: log.h:58
@ RL_LOG_ERROR
Error.
Definition: log.h:49
@ RL_LOG_WARNING
Warning.
Definition: log.h:50
@ RL_LOG_VERBOSE
Verbose.
Definition: log.h:52
@ RL_LOG_INFO
Information.
Definition: log.h:51
@ RL_LOG_IGNORE
Ignore log (only for verbosity configuration)
Definition: log.h:48