OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
ias_logging.c
Go to the documentation of this file.
1 /*************************************************************************
2 
3 NAME: ias_logging.c
4 
5 PURPOSE: Implements the standard message logging interface
6 
7 **************************************************************************/
8 
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #include <string.h>
12 #include <time.h>
13 #include <unistd.h>
14 
15 #define LOGGING_C
16 #include "ias_logging.h"
17 #include "ias_const.h"
18 
19 #define CHANNELS_LENGTH 500
20 
21 /*************************************************************************/
22 enum IAS_LOG_MESSAGE_LEVEL ias_log_message_level; /* Log meeasge level value */
23 static FILE *file_ptr = NULL; /* Output file pointer */
24 static char program_name[40]; /* Current running program
25  name */
26 static pid_t pid; /* Current running processor
27  id */
28 static char ias_log_channels[CHANNELS_LENGTH+3]; /* List of channels to
29  log (3 additional chars:
30  start/stop commas and
31  null character */
32 static int channels_on = 0; /* Flag set if channels
33  are enabled */
34 static int use_blacklist = 0; /* Flag indicates if the
35  channel list contains
36  disabled channels */
37 
38 /*************************************************************************/
39 
40 /*************************************************************************
41 
42 NAME: ias_log_initialize
43 
44 PURPOSE: Initilizes the logging library call
45 
46 Algorithm References: None
47 
48 RETURNS: SUCCESS -- successfully initialized
49  ERROR -- error in initialization
50 
51 NOTES:
52 
53 **************************************************************************/
55 (
56  const char *log_program_name /* I: name to output with each log message */
57 )
58 {
59  const char *log_level;
60  const char *log_channels;
61 
62  /* set the program name */
63  strncpy(program_name, log_program_name, sizeof(program_name));
64  program_name[sizeof(program_name) - 1] = '\0';
65 
66  if (file_ptr == NULL)
67  file_ptr = stdout; /* set the output pointer to stdout */
68  pid = getpid(); /* get current process id */
69 
70  log_level = getenv("IAS_LOG_LEVEL");
71  if ( log_level != NULL)
72  {
73  if (strcmp(log_level,"DEBUG") == 0)
75  else if (strcmp(log_level,"INFO") == 0)
77  else if (strcmp(log_level,"WARN") == 0)
79  else if (strcmp(log_level,"ERROR") == 0)
81  else
82  {
83  IAS_LOG_ERROR("Environment Variable IAS_LOG_LEVEL needs "
84  "to be 'DEBUG', 'INFO', 'WARN', or 'ERROR'");
85  return ERROR;
86  }
87  }
88  else
89  {
91  }
92 
93  log_channels = getenv("IAS_LOG_CHANNELS");
94  if ( log_channels != NULL )
95  {
96  if ( strlen(log_channels) > CHANNELS_LENGTH )
97  {
98  IAS_LOG_ERROR("Environment variable IAS_LOG_CHANNELS exceeds max "
99  "length of %d", CHANNELS_LENGTH);
100  return ERROR;
101  }
102 
103  /* if channel list starts with '-' treat the list as a black list
104  rather than a white list */
105  if (strlen(log_channels) > 0 && log_channels[0] == '-')
106  use_blacklist = 1;
107 
108  /* The value of IAS_LOG_CHANNELS should be a comma delimited list. By
109  appending a comma to the start and end of the value, code can check
110  if a channel is enabled by searching for ',channel,'. */
111  if ( use_blacklist )
112  {
113  /* don't copy the '-' character */
114  sprintf(ias_log_channels, ",%s,", (log_channels+1));
115  }
116  else
117  sprintf(ias_log_channels, ",%s,", log_channels);
118  channels_on = 1;
119  }
120  else
121  {
122  ias_log_channels[0] = '\0';
123  }
124 
125  /* line based buffering to the output file to prevent delay */
126  if (setvbuf(file_ptr, NULL, _IOLBF, 0) !=0)
127  {
128  IAS_LOG_WARNING("Incorrect type or size of buffer for file_ptr");
129  }
130 
131  return SUCCESS;
132 }
133 
134 /*************************************************************************
135 
136 NAME: ias_log_set_output_level
137 
138 PURPOSE: Sets the logging level to the new level
139 
140 RETURNS: None
141 
142 **************************************************************************/
144 (
145  int new_level /* I: minimum logging level to output */
146 )
147 {
148  IAS_LOG_MESSAGE_LEVEL old_level;
149 
150  old_level = ias_log_message_level;
151  ias_log_message_level = new_level;
152 
153  return old_level;
154 }
155 
156 /*************************************************************************
157 
158 NAME: ias_log_set_output_target
159 
160 PURPOSE: Sets the output file pointer to the new value
161 
162 RETURNS: SUCCESS -- successfully setting target
163  ERROR -- error in setting target
164 
165 **************************************************************************/
167 (
168  FILE *new_fp /* I: File pointer for output message */
169 )
170 {
171  file_ptr = new_fp;
172 
173  /* Line based buffering to the output file to prevent delay */
174  if (setvbuf(new_fp, NULL, _IOLBF, 0) !=0)
175  {
176  IAS_LOG_WARNING("Incorrect type or size of buffer for new_fp");
177  }
178 
179  return SUCCESS;
180 }
181 
182 /*************************************************************************
183 
184 NAME: format_time
185 
186 PURPOSE: Gets current timestamp
187 
188 RETURNS: SUCCESS -- successfully getting time
189  ERROR -- error in getting time
190 
191 **************************************************************************/
192 static int format_time
193 (
194  char *stamp, /* O: timestamp for output */
195  int stampsize, /* I: size of timestamp for input */
196  const char *format /* I: format of output timestamp */
197 )
198 {
199  time_t ptime; /* Time in seconds */
200  struct tm *ltime; /* Time in local time */
201 
202  /* Get the current time */
203  ptime = time((time_t *) 0);
204  if (ptime == ((time_t) - 1))
205  {
206  stamp[0] = '\0';
207  return ERROR;
208  }
209 
210  /* Convert the current time to local time */
211  ltime = localtime(&ptime);
212  if (ltime == NULL)
213  {
214  stamp[0] = '\0';
215  return ERROR;
216  }
217 
218  /* Generate the timestamp */
219  if (strftime(stamp, stampsize, format, ltime) == 0)
220  {
221  stamp[0] = '\0';
222  return ERROR;
223  }
224 
225  return SUCCESS;
226 }
227 
228 /*************************************************************************
229 
230 NAME: channel_enabled
231 
232 PURPOSE: Checks if the specified channel is enabled.
233 
234 RETURNS: FALSE -- channel disabled
235  TRUE -- channel enabled
236 
237 **************************************************************************/
238 static int is_channel_enabled
239 (
240  const char *channel
241 )
242 {
243  /* if no channels are defined all are enabled */
244  if ( strlen(ias_log_channels) == 0 )
245  return TRUE;
246 
247  /* build the search string (prepend/append commas) */
248  char search_str[strlen(channel) + 3];
249  sprintf(search_str, ",%s,", channel);
250 
251  /* return true if the channel is found in the channel list */
252  if ( strstr(ias_log_channels, search_str) != NULL )
253  {
254  if ( use_blacklist )
255  return FALSE;
256  else
257  return TRUE;
258  }
259 
260  if ( use_blacklist )
261  return TRUE;
262  else
263  return FALSE;
264 }
265 
266 /*************************************************************************
267 
268 NAME: log_message
269 
270 PURPOSE: Outputs logging message to the output file pointer
271 
272 RETURNS: None
273 
274 **************************************************************************/
275 static void log_message
276 (
277  int log_level, /* I: message level for input */
278  const char *filename, /* I: source code file name for input */
279  int line_number, /* I: source code line number for input */
280  const char *format, /* I: format string for message */
281  va_list ap /* I: format string variables */
282 )
283 {
284  char time_stamp[20];
285  char temp_string[500];
286  static const char *log_level_message[] = {"DEBUG", "INFO", "WARN", "ERROR"};
287 
288  /* if file_ptr is not set (ias_log_message is not called), stdout is used */
289  if (file_ptr == NULL)
290  file_ptr = stdout;
291 
292  /* if pid is not set (ias_log_message is not called), getpid is called to
293  get the current processor id */
294  if (pid == 0)
295  pid = getpid();
296 
297  /* if log_level is out of range, log_level is set to be
298  IAS_LOG_LEVEL_ERROR */
299  if (log_level < IAS_LOG_LEVEL_DEBUG || log_level > IAS_LOG_LEVEL_ERROR)
300  {
301  log_level = IAS_LOG_LEVEL_ERROR;
302  IAS_LOG_WARNING("Log_level is out of range, should be one of "
303  "IAS_LOG_LEVEL_DEBUG, IAS_LOG_LEVEL_INFO, "
304  "IAS_LOG_LEVEL_WARN, and IAS_LOG_LEVEL_ERROR");
305  }
306 
307  /* if log_level is high enough, output the message */
308  if (log_level >= ias_log_message_level)
309  {
310  /* Set arg_ptr to beginning of list of optional arguments */
311  vsnprintf(temp_string, sizeof(temp_string), format, ap);
312 
313  format_time(time_stamp, sizeof(time_stamp),"%F %H:%M:%S");
314  fprintf(file_ptr, "%19s %s %7d %-20s %6d %s %s\n",
315  time_stamp, program_name, pid, filename,
316  line_number, log_level_message[log_level], temp_string);
317  }
318 }
319 
320 /*************************************************************************
321 
322 NAME: ias_log_message
323 
324 PURPOSE: Outputs logging message to the output file pointer
325 
326 RETURNS: None
327 
328 **************************************************************************/
329 void ias_log_message
330 (
331  int log_level, /* I: message level for input */
332  const char *filename, /* I: source code file name for input */
333  int line_number, /* I: source code line number for input */
334  const char *format, ... /* I: format string for message */
335 )
336 {
337  /* If channels are enabled, ignore non-channel debug messages */
338  if (channels_on && log_level == IAS_LOG_LEVEL_DEBUG)
339  return;
340  va_list arglist;
341  va_start(arglist, format);
342  log_message(log_level, filename, line_number, format, arglist);
343  va_end(arglist);
344 }
345 
346 /*************************************************************************
347 
348 NAME: ias_log_message_with_channel
349 
350 PURPOSE: Outputs logging message to the output file pointer if logging is
351  enabled for the specified channel
352 
353 RETURNS: None
354 
355 **************************************************************************/
357 (
358  int log_level, /* I: message level for input */
359  const char *channel, /* I: channel name */
360  const char *filename, /* I: source code file name for input */
361  int line_number, /* I: source code line number for input */
362  const char *format, ... /* I: format string for message */
363 )
364 {
365  if (is_channel_enabled(channel))
366  {
367  va_list arglist;
368  va_start(arglist, format);
369  log_message(log_level, filename, line_number, format, arglist);
370  va_end(arglist);
371  }
372 }
373 
374 /*************************************************************************/
375 
#define IAS_LOG_WARNING(format,...)
Definition: ias_logging.h:100
#define SUCCESS
Definition: ObpgReadGrid.h:15
#define IAS_LOG_ERROR(format,...)
Definition: ias_logging.h:96
#define CHANNELS_LENGTH
Definition: ias_logging.c:19
#define FALSE
Definition: rice.h:164
#define NULL
Definition: decode_rs.h:63
IAS_LOG_MESSAGE_LEVEL ias_log_set_output_level(int new_level)
Definition: ias_logging.c:144
#define TRUE
Definition: rice.h:165
float tm[MODELMAX]
@ IAS_LOG_LEVEL_WARN
Definition: ias_logging.h:48
@ IAS_LOG_LEVEL_ERROR
Definition: ias_logging.h:49
@ IAS_LOG_LEVEL_DEBUG
Definition: ias_logging.h:46
int ias_log_initialize(const char *log_program_name)
Definition: ias_logging.c:55
char filename[FILENAME_MAX]
Definition: atrem_corl1.h:122
char * format_time(double usec)
Definition: printindx.c:22
void ias_log_message(int log_level, const char *filename, int line_number, const char *format,...)
Definition: ias_logging.c:330
IAS_LOG_MESSAGE_LEVEL
Definition: ias_logging.h:45
this program makes no use of any feature of the SDP Toolkit that could generate such a then geolocation is calculated at that and then aggregated up to Resolved feature request Bug by adding three new int8 SDSs for each high resolution offsets between the high resolution geolocation and a bi linear interpolation extrapolation of the positions This can be used to reconstruct the high resolution geolocation Resolved Bug by delaying cumulation of gflags until after validation of derived products Resolved Bug by setting Latitude and Longitude to the correct fill resolving to support Near Real Time because they may be unnecessary if use of entrained ephemeris and attitude data is turned resolving bug report Corrected to filter out Aqua attitude records with missing status helping resolve bug MOD_PR03 will still correctly write scan and pixel data that does not depend upon the start time
Definition: HISTORY.txt:248
@ IAS_LOG_LEVEL_INFO
Definition: ias_logging.h:47
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second and prod_ix set to PARAM_TYPE_INT name_prefix is compared with the beginning of the product name If name_suffix is not empty the it must match the end of the product name The characters right after the prefix are read as an integer and prod_ix is set to that number strncpy(l2prod->name_prefix, "myprod", UNITLEN)
void ias_log_message_with_channel(int log_level, const char *channel, const char *filename, int line_number, const char *format,...)
Definition: ias_logging.c:357
int ias_log_set_output_target(FILE *new_fp)
Definition: ias_logging.c:167
#define ERROR
Definition: ancil.h:24
enum IAS_LOG_MESSAGE_LEVEL ias_log_message_level
Definition: ias_logging.c:22