Changing LoadRunner/VuGen log options at runtime

expert IT support

LoadRunner has a whole bunch of logging options. These can be specified in your script's runtime settings, or specified in your script's code with lr_set_debug_message(). There are some gotchas when changing your logging options with a C function call, so I have written some functions that will be helpful.

VuGen log options

The LoadRunner/Vugen functions that allow you to read and change the logging level at runtime are:

  • lr_get_debug_message - Returns the current log settings. The returned value returned can be saved and passed into lr_set_debug_message to restore log settings after changes have been made.
  • lr_set_debug_message - Sets the log level for the script execution. This determines whether logging is enabled, what information gets logged, and in how much detail. Logs are written to {group name}_{vuser id}.log when run from the Controller, and are written to the Replay Log (mdrv.log) when run from VuGen.

Each logging option has a C-constant that is a binary value with a 1 in the position that corresponds to the log option.

Log Level C Constant Value Binary Value
Disabled LR_MSG_CLASS_DISABLE_LOG 0 00000000 00000000
Brief LR_MSG_CLASS_BRIEF_LOG 1 00000000 00000001
Extended Log LR_MSG_CLASS_EXTENDED_LOG 16 00000000 00010000
Result Data LR_MSG_CLASS_RESULT_DATA 2 00000000 00000010
Parameter Substitution LR_MSG_CLASS_PARAMETERS 4 00000000 00000100
Full Run-Time Trace LR_MSG_CLASS_FULL_TRACE 8 00000000 00001000
Log on Error LR_MSG_CLASS_JIT_LOG_ON_ERROR 512 00000010 00000000

These binary values can be combined (using the bitwise OR operator) to turn on several logging options at once. The following line of code would set logging levels to those in the screenshot above (as long as logging was completely disabled in the runtime settings).

lr_set_debug_message(LR_MSG_CLASS_JIT_LOG_ON_ERROR | LR_MSG_CLASS_EXTENDED_LOG | LR_MSG_CLASS_PARAMETERS | LR_MSG_CLASS_RESULT_DATA | LR_MSG_CLASS_FULL_TRACE, LR_SWITCH_ON);

This corresponds to an integer value of 542 or 00000010 00011110 in binary.

The problem is that before setting your new log options, you must clear the bits for any of the log options that you do not want (by using lr_set_debug_message with the LR_SWITCH_OFF agument, and the correct binary pattern). This is easy if you know exactly which options will be enabled when your script runs, but trickier if you want to write code that will work, no matter what log options are initially selected.

Here is a function that will clear all the log options (so you can easily set new options).

// Turn off all logging options (this is the same as having logging disabled).
void jds_clear_log_options(void) {
	unsigned int log_options = lr_get_debug_message();
	lr_set_debug_message(log_options, LR_SWITCH_OFF); 
	return;
}
// This function allows you to set log options using the same C constants as lr_set_debug_message (LR_MSG_CLASS_EXTENDED_LOG etc).
// Note tht you should call jds_clear_log_options first, or you new log options will be added to any existing log options.
void jds_set_log_options(unsigned int new_log_options) {
	unsigned int original_log_options = lr_get_debug_message();

	lr_set_debug_message(new_log_options, LR_SWITCH_ON);	

	// The lr_set_debug_message() function has a non-intuitive (i.e. stupid) behaviour, where
	// it will automatically set LR_MSG_CLASS_JIT_LOG_ON_ERROR if your runtime settings have 
	// this option enabled.
	// This means that it is necessary to un-set this option (LR_SWITCH_OFF) if it was not already 
	// enabled, and it was not requested to be enabled.
	if (lr_get_debug_message() & LR_MSG_CLASS_JIT_LOG_ON_ERROR) {
		if ( !( (original_log_options & LR_MSG_CLASS_JIT_LOG_ON_ERROR) || (new_log_options & LR_MSG_CLASS_JIT_LOG_ON_ERROR) ) ) {
			lr_set_debug_message(LR_MSG_CLASS_JIT_LOG_ON_ERROR, LR_SWITCH_OFF);
		}
	}

	return;
}
// Prints the current log options to the output log (even if logging is disabled)
// Example: jds_print_log_options(lr_get_debug_message());
void jds_print_log_options(unsigned int log_options_to_print) {
	char buf[(4 * 8) + 1]; // sizeof(unsigned int) is always 4 bytes in LoadRunner.
	unsigned int original_log_options = lr_get_debug_message();

	jds_clear_log_options();
	jds_set_log_options(LR_MSG_CLASS_BRIEF_LOG);

	// Print the bit pattern for the current log options.
	itoa(log_options_to_print, buf, 2);
	lr_output_message("Log options bit pattern: %032.32s", buf);

	lr_output_message("Log options selected:");

	if (log_options_to_print == 0) {
		lr_output_message("* Disabled (LR_MSG_CLASS_DISABLE_LOG)");
	} else {

		if (log_options_to_print & LR_MSG_CLASS_JIT_LOG_ON_ERROR) {
			lr_output_message("* Send messages only when an error occurs (LR_MSG_CLASS_JIT_LOG_ON_ERROR)");
		} else {
			lr_output_message("* Always send messages");
		}
	
		if (log_options_to_print & LR_MSG_CLASS_BRIEF_LOG) {
			lr_output_message("* Log messages at the detail level of \"Standard log\" (LR_MSG_CLASS_BRIEF_LOG)");
		}
	
		if (log_options_to_print & LR_MSG_CLASS_EXTENDED_LOG) {
			lr_output_message("* Log messages at the detail level of \"Extended log\" (LR_MSG_CLASS_EXTENDED_LOG)");
		}
	
		if (log_options_to_print & LR_MSG_CLASS_PARAMETERS) {
			lr_output_message("* Parameter substitution (LR_MSG_CLASS_PARAMETERS)");
		}
		
		if (log_options_to_print & LR_MSG_CLASS_RESULT_DATA) {
			lr_output_message("* Data returned by server (LR_MSG_CLASS_RESULT_DATA)");
		}
	
		if (log_options_to_print & LR_MSG_CLASS_FULL_TRACE) {
			lr_output_message("* Advanced trace (LR_MSG_CLASS_FULL_TRACE)");
		}
	}

	jds_clear_log_options();
	jds_set_log_options(original_log_options);

	return;
}
/*
Output looks like this:
globals.h(26): Log options bit pattern: 00000000000000000000001000011110
globals.h(28): Log options selected:
globals.h(35): * Send messages only when an error occurs (LR_MSG_CLASS_JIT_LOG_ON_ERROR)
globals.h(45): * Log messages at the detail level of "Extended log" (LR_MSG_CLASS_EXTENDED_LOG)
globals.h(49): * Parameter substitution (LR_MSG_CLASS_PARAMETERS)
globals.h(53): * Data returned by server (LR_MSG_CLASS_RESULT_DATA)
globals.h(57): * Advanced trace (LR_MSG_CLASS_FULL_TRACE)
*/

Putting it all together...

So if you wanted to write a message to the output log, even though your runtime settings were set to log on error, you could do the following:

Action()
{
	// Save current options.
	unsigned int original_log_options = lr_get_debug_message();

	// Set new (minimal) log options
	jds_clear_log_options();
	jds_set_log_options(LR_MSG_CLASS_BRIEF_LOG);

	// Do whatever you want to do with the new log options.
	// In this case, I am just writing a simple message to the log.
	lr_output_message("Username: %s, IP address: %s", lr_eval_string("{UserName}"), lr_get_vuser_ip());

	// Restore the log options to their original values.
	jds_clear_log_options();
	jds_set_log_options(original_log_options);

	return 0;
}

Tech tips from JDS