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).

1
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).

1
2
3
4
5
6
// 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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 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;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;
}

4 comments on “Changing LoadRunner/VuGen log options at runtime

  1. Hi

    RE: Changing LoadRunner/VuGen log options at runtime

    I found (several versions ago) that writing logging statements gave different and often undesirable results, depending on the start position of logging – particularly if I switched to log on error (my default). I often like to switch extended logging on to record a specific (e.g. an order number). The code below relies on your log level table but always works.

    int rc;

    rc=lr_get_debug_message();
    lr_set_debug_message(rc, LR_SWITCH_OFF);
    lr_set_debug_message(18, LR_SWITCH_ON);
    lr_log_message(“***** Order Number: %s”, lr_eval_string(“{cOrdNo}”));
    lr_set_debug_message(18, LR_SWITCH_OFF);
    lr_set_debug_message(rc, LR_SWITCH_ON);

    1. Can u explain me how this flow works. It is very helpful for my scripting. But i want to know how this works and also why we are using numeric 18 in lr_set_debug_message(18, LR_SWITCH_ON);

      1. Also using this code we are albe to write data only into output file. But the data is not getting written into log file. Can you please suggest me on this also?

  2. Hi

    I have a functionlibrary in vbscript developed in QTP for oracle forms login with 16 instances.Each instance has it’s own id and password.Now I want to reuse it with LoadRunner.
    I have the following options:
    1.Convert VBscript Function library to C userdefined function library for LoadRunner

    2. Using VBscript as the language in LoadRunner to reuse the scripts developed in QTP directly.

    3. Develop new C function library (I am a bit afraid to invest time here to do the same task again,So not considering this option

    Could you please give me tips on using VBscript as the language in LoadRunner to record

    or

    how to use efficiently the QTP Script developed in LoadRunner

    or code conversion from VBscript to C language

    Thanks
    Suresh

Leave a Reply