Y-lib
Loadrunner libraries
y_logging.c
Go to the documentation of this file.
1 /*
2  * Ylib Loadrunner function library.
3  * Copyright (C) 2005-2014 Floris Kraak <randakar@gmail.com> | <fkraak@ymor.nl>
4  * Copyright (C) 2009 Raymond de Jongh <ferretproof@gmail.com> | <rdjongh@ymor.nl>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
27 #ifndef _Y_LOGGING_C_
28 #define _Y_LOGGING_C_
30 
32 #include "y_core.c"
33 #include "y_loadrunner_utils.c"
34 
35 // Todo: Figure out whether we want to keep this one.
36 // const unsigned int Y_ALL_LOG_FLAGS = LR_MSG_CLASS_BRIEF_LOG | LR_MSG_CLASS_EXTENDED_LOG | LR_MSG_CLASS_RESULT_DATA | LR_MSG_CLASS_PARAMETERS | LR_MSG_CLASS_FULL_TRACE | LR_MSG_CLASS_JIT_LOG_ON_ERROR | LR_MSG_CLASS_AUTO_LOG;
37 
39 int _y_extra_logging = 0; // client specific logging code on/off switch; 0 = off, 1 = on
41 
42 // Previous loglevel, saved with and restored by log toggle functions.
43 // Not documented because people really should not be using this directly.
44 //
46 unsigned int _y_log_level = LR_MSG_CLASS_DISABLE_LOG;
48 
60 char* y_make_datetimestamp(time_t time, unsigned short millitm)
61 {
62  struct tm *resulttime;
63  static char YMDHMSm[24]; // moet static zijn om te gebruiken als returnwaarde
64 
65  // _tzset(); // The tzset function initializes the tzname variable from the value of the TZ environment variable. It is not usually necessary for your program to call this function, because it is called automatically when you use the other time conversion functions that depend on the time zone.
66  resulttime = (struct tm *)localtime(&time);
67 
68  snprintf(YMDHMSm, sizeof YMDHMSm, "%04u-%02u-%02u %02u:%02u:%02u.%03u",
69  resulttime->tm_year + 1900,
70  resulttime->tm_mon + 1,
71  resulttime->tm_mday,
72  resulttime->tm_hour,
73  resulttime->tm_min,
74  resulttime->tm_sec,
75  millitm);
76  return YMDHMSm;
77 }
78 
88 {
89  struct _timeb timebuffer;
90  // _tzset(); // The tzset function initializes the tzname variable from the value of the TZ environment variable. It is not usually necessary for your program to call this function, because it is called automatically when you use the other time conversion functions that depend on the time zone.
91  ftime( &timebuffer );
92  return y_make_datetimestamp( timebuffer.time, timebuffer.millitm);
93 }
94 
96 #define y_timestamp 0_y_timestamp_no_longer_exists_please_use_y_get_current_time
97 
99 
111 {
112  y_setup();
113 
114  // Make the extra logging facility available to the user.
115  _y_extra_logging = 1;
116 }
117 
128 void y_log_to_report(char *message)
129 {
130  char *logLine = "%s: VUserId: %d, Host: %s, %s";
131 
132  // Only add extra logging if it has been turned on.
133  if( _y_extra_logging )
134  {
135  int log_level = lr_get_debug_message();
136 
137  lr_set_debug_message(LR_MSG_CLASS_DISABLE_LOG | LR_MSG_CLASS_AUTO_LOG, LR_SWITCH_OFF);
138  lr_set_debug_message(
139  LR_MSG_CLASS_EXTENDED_LOG | LR_MSG_CLASS_RESULT_DATA | LR_MSG_CLASS_PARAMETERS | LR_MSG_CLASS_FULL_TRACE,
140  LR_SWITCH_ON);
141  lr_log_message(logLine, y_get_datetimestamp(), y_virtual_user_id, lr_get_host_name(), lr_eval_string(message));
142  lr_set_debug_message(log_level, LR_SWITCH_ON);
143  //lr_set_debug_message((log_level ^ -1), LR_SWITCH_OFF);
144  }
145 }
146 
153 void y_log_error(char *message)
154 {
155  char *msg = lr_eval_string(message);
156  y_log_to_report(msg);
157  //lr_error_message(msg);
158  lr_fail_trans_with_error(msg);
159 }
160 
167 void y_log_warning(char *message)
168 {
169  char *msg;
170  lr_save_string(lr_eval_string(message), "_log_msg");
171  msg = lr_eval_string("Warning: {_log_msg}");
172 
173  y_log_to_report(msg);
174 }
175 
183 {
184  // Save the previous loglevel.
185  _y_log_level = lr_get_debug_message();
186  //lr_error_message("Saved loglevel %d", _y_log_level);
187 }
188 
196 {
197  // Good grief, this debug message interface is terrible.
198 
199  // Turn all logging off. Which has the really weird side effect of turning auto logging on again.
200  lr_set_debug_message(LR_MSG_CLASS_DISABLE_LOG, LR_SWITCH_ON);
201 
202  // Disable the auto logging again, but using a different bit flag.
203  lr_set_debug_message(LR_MSG_CLASS_AUTO_LOG, LR_SWITCH_OFF);
204  //lr_error_message("All logging turned off, log level now %d", lr_get_debug_message() );
205 }
206 
207 
214 {
215  y_log_save();
217 }
218 
229 {
231  y_log_save(); // make sure it is never accidentally enabled again through y_log_restore()
232 }
233 
242 {
243  //lr_log_message("Log level set to BRIEF.\n");
244  y_log_turn_off();
245  lr_set_debug_message(LR_MSG_CLASS_BRIEF_LOG, LR_SWITCH_ON);
246  //lr_log_message("Log level set to brief, from %d to %d", _y_log_level, lr_get_debug_message() );
247 }
248 
257 {
258  //lr_log_message("Log level set to EXTENDED.\n");
259  y_log_turn_off();
260  lr_set_debug_message(
261  LR_MSG_CLASS_EXTENDED_LOG | LR_MSG_CLASS_RESULT_DATA | LR_MSG_CLASS_PARAMETERS | LR_MSG_CLASS_FULL_TRACE,
262  LR_SWITCH_ON);
263  //lr_log_message("Log level extended from %d to %d", _y_log_level, lr_get_debug_message() );
264 }
265 
266 
275 {
276  //lr_log_message("Restoring log level to %d, current level %d.", _y_log_level, lr_get_debug_message());
277 
279 
280  lr_set_debug_message(_y_log_level, LR_SWITCH_ON);
281 
282  // None of this debug code does what we want. Only y_log_turn_off_without_saving() (above) seems to work ..
283  //lr_set_debug_message(~Y_ALL_LOG_FLAGS, LR_SWITCH_OFF);
284  //lr_set_debug_message(~_y_log_level, LR_SWITCH_OFF);
285  //lr_set_debug_message(~_y_log_level & Y_ALL_LOG_FLAGS, LR_SWITCH_OFF);
286 
287  //lr_error_message("Attempted to restore loglevel to %d, now it is %d", _y_log_level, lr_get_debug_message());
288  // Of course if the previous state was "OFF" the user will never see this either ;-)
289 }
290 
303 {
304  if(_y_log_level == LR_MSG_CLASS_DISABLE_LOG)
305  {
307  }
308  else
309  {
310  y_log_restore();
311  }
312 }
313 
328 void y_log_force_message(char *message)
329 {
331  lr_log_message( message );
332  y_log_restore();
333 }
334 
354 int y_write_to_log(char *filename, char *content)
355 {
356  size_t string_length;
357  char* log;
358  int result;
359 
360  y_setup();
361 
362  string_length = strlen(content)
363  + 15 // y_datetime() is altijd 15 chars lang.
365  + 9 // y_virtual_user_id
366  + 6 // scid
367  + 1; // null byte (end of line)
368 
369  log = y_mem_alloc(string_length);
370  y_datetime();
371  snprintf(log, string_length, "%.15s,%s,%d,%d,%s",
372  lr_eval_string("{DATE_TIME_STRING}"),
374  abs(y_virtual_user_id) % 1000000000,
375  abs(y_scid) % 1000000,
376  content);
377 
378  result = y_write_to_file(filename, log);
379  free(log);
380 
381  return result;
382 }
383 
401 void y_disk_space_guard(double max_free_percentage)
402 {
403  char* hostname;
404  static int disk_space_warning_given = 0;
405  double free_space_percentage;
406  char* log_folder = lr_get_attrib_string("out");
407 
408  // check already fired once before.
409  if( disk_space_warning_given )
410  {
411  // guard against accidental re-enablement of the logs by turning them off explicitly.
413  return;
414  }
415 
416  free_space_percentage = y_get_free_disk_space_percentage(log_folder);
417 
418  // data point
419  hostname = lr_get_host_name();
420  lr_save_string(hostname, "y_hostname_generator");
421  lr_user_data_point( lr_eval_string("disk_space_{y_hostname_generator}_free_percentage"), free_space_percentage);
422 
423  if( free_space_percentage < max_free_percentage )
424  {
425  y_setup();
426  lr_set_transaction(lr_eval_string("---DISK SPACE LOW IN LOG FOLDER FOR {y_hostname_generator}---"), 0, LR_FAIL);
427  lr_error_message("Diskspace low on %s in folder %s. %.2lf%% remaining, exceeding the limit of %.21f%% Logging turned off for user id %d for the remainder of the test!",
428  hostname, log_folder, free_space_percentage, max_free_percentage, y_virtual_user_id);
429  disk_space_warning_given = 1; // turn off further warnings.
431  }
432 }
433 
434 
456 void y_disk_space_usage_guard(double limit_mebibytes_used)
457 {
458  char* hostname;
459  char* log_folder = lr_get_attrib_string("out");
460  double free_mebibytes;
461  static double max_free_mebibytes = -1;
462  double mebibytes_used;
463  static int disk_space_warning_given = 0;
464 
465  // check already fired once before.
466  if( disk_space_warning_given )
467  {
468  // guard against accidental re-enablement of the logs by turning them off explicitly.
470  return;
471  }
472 
473  free_mebibytes = y_get_free_disk_space_in_mebibytes(log_folder);
474  lr_log_message("y_disk_space_usage_guard: current free: %f MB, max free: %f MB, limit: %f MB used in folder: %s",
475  free_mebibytes, max_free_mebibytes, limit_mebibytes_used, log_folder);
476 
477  if(max_free_mebibytes < 0)
478  {
479  lr_log_message("Storing free space as detected maximum");
480  max_free_mebibytes = free_mebibytes;
481  return;
482  }
483  else if(max_free_mebibytes < free_mebibytes)
484  {
485  lr_output_message("Warning: Free disk space increased from %f to %f, test disk space usage measurements may have become unreliable.", max_free_mebibytes, free_mebibytes);
486  max_free_mebibytes = free_mebibytes;
487  return;
488  }
489 
490  // Ok, so we used *something*. Now let's see if it exceeds our limit.
491  mebibytes_used = max_free_mebibytes - free_mebibytes;
492 
493  // data points
494  hostname = lr_get_host_name();
495  lr_save_string(hostname, "y_hostname_generator");
496  lr_user_data_point( lr_eval_string("disk_space_{y_hostname_generator}_free_mebibytes"), free_mebibytes);
497  lr_user_data_point( lr_eval_string("disk_space_{y_hostname_generator}_used_mebibytes"), mebibytes_used);
498 
499  if( mebibytes_used >= limit_mebibytes_used )
500  {
501  y_setup();
502  lr_set_transaction(lr_eval_string("---DISKSPACE USAGE TOO HIGH IN LOG FOLDER FOR {y_hostname_generator}---"), 0, LR_FAIL);
503  lr_output_message("Disk space used on host %s in folder %s was %f mebibytes, reaching the limit of %f. Logging turned off for user id %d for the remainder of the test!",
504  hostname, log_folder, mebibytes_used, limit_mebibytes_used, y_virtual_user_id);
505  disk_space_warning_given = 1; // turn off further warnings.
507  }
508 }
509 
510 #endif // _Y_LOGGING_C_
void ftime(struct _timeb *time)
Documented at http://www.qnx.com/developers/docs/6.5.0/topic/com.qnx.doc.neutrino_lib_ref/f/ftime.html .
void y_setup()
Ylib setup - determines and stores the identity of the virtual user.
Definition: y_core.c:85
void y_log_force_message(char *message)
Log a message forcefully, bypassing the current log settings.
Definition: y_logging.c:328
int tm_min
minutes after the hour - [0,59]
Definition: vugen.h:182
void y_disk_space_usage_guard(double limit_mebibytes_used)
Detect excessive disk usage by the test and turn all further logging off if more than a specific limi...
Definition: y_logging.c:456
double y_get_free_disk_space_in_mebibytes(const char *folder_name)
Get the amount of free disk space in the target folder in mebibytes (SI unit)
int tm_mday
day of the month - [1,31]
Definition: vugen.h:186
void y_log_restore()
Restore the loglevel to previous state. To be exact, it will restore it to the state it was in before...
Definition: y_logging.c:274
void y_log_set_extended()
Set the log level to show all messages, including extended result data, parameters, and tracing information.
Definition: y_logging.c:256
int y_write_to_file(char *filename, char *content)
Write a string to a file.
int tm_year
years since 1900
Definition: vugen.h:190
int y_write_to_log(char *filename, char *content)
Write a string prepended with date and time to the specified (log)file.
Definition: y_logging.c:354
char * y_make_datetimestamp(time_t time, unsigned short millitm)
Convert a unixtime style timestamp to a date and time represented as YYYY-MM-DD HH:MM:SS.mmm.
Definition: y_logging.c:60
int y_scid
The virtual user scid, as reported by lr_whoami().
Definition: y_core.c:44
char * y_mem_alloc(size_t size)
Ylib wrapper for malloc()
Definition: y_core.c:221
void y_log_save()
Save the loglevel for later restoration through y_log_restore().
Definition: y_logging.c:182
Contains core ylib support functions needed for the functioning of the library.
void y_log_to_report(char *message)
If extra logging was enabled force a line to be logged to the logfile - even if regular logging was t...
Definition: y_logging.c:128
struct tm * localtime(const time_t *timer)
Documented at http://www.cplusplus.com/reference/ctime/localtime/.
void y_log_error(char *message)
Log an error message, with a timestamp, if extra logging is enabled.
Definition: y_logging.c:153
int y_virtual_user_id
The virtual user id, as reported by lr_whoami().
Definition: y_core.c:40
int tm_mon
months since January - [0,11]
Definition: vugen.h:188
void y_log_turn_off_permanently()
Turn all logging off and make sure it stays that way.
Definition: y_logging.c:228
char * y_get_datetimestamp()
Returns the current time converted represented as YYYY-MM-DD HH:MM:SS.mmm.
Definition: y_logging.c:87
int abs(int n)
Documented at http://www.cplusplus.com/reference/cstdlib/abs/.
long time_t
Type time_t can hold a Unix timestamp.
Definition: vugen.h:174
void y_datetime()
Saves the current date/time into a LR-parameter.
void y_setup_logging()
Turn on &#39;extra logging&#39;, when available.
Definition: y_logging.c:110
void y_log_turn_off()
Save the current loglevel and turn off logging.
Definition: y_logging.c:213
void y_log_turn_on()
Turn logging on.
Definition: y_logging.c:302
Documented at http://www.cplusplus.com/reference/ctime/tm/. Values outside of valid ranges can be us...
Definition: vugen.h:178
size_t strlen(const char *string)
Documented at http://www.cplusplus.com/reference/cstring/strlen/.
Collection of miscellaneous support functions.
void y_disk_space_guard(double max_free_percentage)
Detect low disk space situations on the generator and turn all logging off if not enough space is lef...
Definition: y_logging.c:401
unsigned short millitm
Milliseconds. Actual accuracy may be lower.
Definition: vugen.h:226
void y_log_set_brief()
Set the log level to "brief" messages only.
Definition: y_logging.c:241
int snprintf(char *buffer, size_t n, const char *format_string,...)
Documented at http://www.cplusplus.com/reference/cstdio/snprintf/. This function was introduced by t...
void y_log_turn_off_without_saving()
Force all logging off unconditionally, without saving the old state.
Definition: y_logging.c:195
char * y_virtual_user_group
The virtual user group, as reported by lr_whoami().
Definition: y_core.c:42
double log(double x)
Documented at http://www.cplusplus.com/reference/cmath/log/.
int tm_sec
seconds after the minute - [0,61] (or [0,59] when leap seconds are not supported) ...
Definition: vugen.h:180
void y_log_warning(char *message)
Log a warning, with a timestamp, if extra logging is enabled.
Definition: y_logging.c:167
int tm_hour
hours since midnight - [0,23]
Definition: vugen.h:184
double y_get_free_disk_space_percentage(const char *folder_name)
Get the free disk space percentage on the target folder on the load generator.
time_t time(time_t *timeptr)
Documented at http://www.cplusplus.com/reference/ctime/time/.
void free(void *mem_address)
Documented at http://www.cplusplus.com/reference/cstdlib/free/.
time_t time
Time, in seconds, since the Unix Epoch, 1 January 1970 00:00:00 Coordinated Universal Time (UTC)...
Definition: vugen.h:224
Used by ftime. Defined as _timeb (instead of timeb) just as in the on-line Help.
Definition: vugen.h:222