From RTSC-Pedia

Jump to: navigation, search
revision tip
—— LANDSCAPE orientation
[printable version]  offline version generated on 11-Jun-2009 18:06 UTC  

Using xdc.runtime Logging/Example 3

Adding logging to existing code bases

Contents

Adding Logging to Existing Code Bases

The simplest way to add logging is to simply #include the xdc.runtime.Log and xdc.runtime.Diags headers and insert appropriate Log_print statements into your existing code base.

 
 
 
 
 
 
#include <xdc/runtime/Log.h>
#include <xdc/runtime/Diags.h>
    :
Log_print2(Diags_ENTRY, "entering myFunc(0x%x, %d)", (IArg)handle, arg2);
    :
Log_print1(Diags_EXIT, "myFunc returned: %d", result);

This by itself allows clients of your code to get visibility into their use of your code in real-time, even in deployed systems.

Why do we have casts around some of the arguments to Log_print()? Unlike printf(), the Log_write() and Log_print() methods are not vararg functions; they are macros - which, prior to C99, are not allowed to take a variable number of arguments - that pass the specified arguments to an ILogger function whose arguments are of type IArg. The IArg type, while large enough to hold a pointer, is not a pointer type and many compilers emit a warning when passing a pointer argument to either Log_print() or Log_write(); the cast to IArg suppresses these warnings.

Format strings, while very convenient, are a well known source of portability problems: each format specification must precisely match the types of the arguments passed. Underlying "printf" functions use the format string to determine how far to advance through their argument list. For targets where pointer types and integers are the same size there are no problems; each argument has the same size after the normal C promotions.

Suppose a target's pointer type is larger than its integer type. In this case, because integer arguments are widened to be of type IArg, a format specification of "%d" causes an underlying printf() implementation to read the extended part of the integer argument as part of the next argument(!). To get around this problem and still allow the use "natural" format specifications (e.g., %d and %x with optional width specifications), System_printf() supports a special format conversion operator that specifies that all subsequent arguments have been widened to be of type IArg: all arguments after the sequence "%$A" are treated as though they have been widened.

You may want to allow clients of your code to independently configure and control your Log statements independent of other content producers. If all content producers rely on xdc.runtime.Main as the source of their Log events, system integrators are not able to easily separate events coming from different parts of their application. The next section shows how, with very little extra effort, you can enable your users with this level of configurability.

Enabling Custom ILogger Configuration

This section outlines a simple technique that enables content producers make it appear to integrators that their content is, from a logging perspective, composed of one or more RTSC modules. The "trick" is to create a RTSC module without any types or methods and then #include this module's generated header wherever you use the Log APIs. By including the generated header in your existing code base, any Log API calls will be associated with this new module rather than xdc.runtime.Main.

Suppose, for example, that you name your module Cool and it's part of a package named org.optimal. To add logging configurable under the name org.optimal.Cool, you modify your existing code base as shown above with only one difference: add a #include of the org.optimal.Cool module's internal header.

 
 
 
 
 
 
 
 
 
#include <xdc/runtime/Log.h>
#include <xdc/runtime/Diags.h>
 
#include <org/optimal/package/internal/Cool.xdc.h>
 
    :
Log_print2(Diags_ENTRY, "entering myFunc(0x%x, %d)", (IArg)arg1, arg2);
    :
Log_print1(Diags_EXIT, "myFunc returned: %d", result);

Doing this enables system integrators to configure a unique ILogger for your code and enable (or disable) events for just your codebase. In addition, you can even declare Log events in the Cool module which can be referenced in you code base via Log_write; this allows the integrator to minimize the the string space required in her final application.

You can avoid having to add Log statements throughout your code base by simply "wrapping" your selected APIs in a RTSC module. Since all module methods are automatically instrumented by the configuration tool, you don't need to obfuscate your code with logging statements and users can completely eliminate the runtime overhead of these statements without requiring your sources for recompilation.

Creating the Cool Module

To create the Cool module (and its headers) described above:

  • create a directory named org/optimal and add the files package.xdc, package.bld, and Cool.xdc (shown below); and
  • run the xdc command from within this directory

Cool.xdc
 
 
module Cool {
}
package.xdc
 
 
 
package org.optimal { 
    module Cool; 
}
package.bld
 
/* intentionally empty */

When you run the xdc command, it should complete without error and you should see output similar to the following.

% xdc
 
 
 
 
making package.mak (because of package.bld) ...
generating interfaces for package org.optimal (because package/package.xdc.xml is older than package.xdc) ...
    translating Cool
all files complete.

To use the Cool module's headers in your existing code, simply add the directory containing org/optimal to your package path. For more information about integrating RTSC modules into an existing C/C++ code base see Integrating RTSC Modules.

See also

Using xdc.runtime Logging/Example 1 Classic "hello world" using Log
Using xdc.runtime Logging/Example 2 Events provided by all RTSC target modules
Using xdc.runtime Logging/Example 4 Adding Logging to RTSC Modules

[printable version]  offline version generated on 11-Jun-2009 18:06 UTC  
Copyright © 2008 The Eclipse Foundation. All Rights Reserved
Views
Personal tools
package reference