Rate This Document
Findability
Accuracy
Completeness
Readability

Examples of Using the Tracer

This section demonstrates how to use the Tracer. See Figure 1.

Figure 1 Overall process

File directory structure:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/home/tracelog/ 
├── user.ini
├── user_demo.c  
├── logger_device
   ├── lib 
       ├──libkperf.so              # Performance data collection library.
       ├──libloggerdevice.a        # Function library (static library), which provides log serialization and deserialization capabilities.
       ├──libloggerdevice.so       # Function library (dynamic library), which provides log serialization and deserialization capabilities.
       ├──libsym.so                # Symbol parsing library.
   ├── include
       ├──dev_trace_log.h          # Provides Tracer APIs.
       ├──dev_trace_log.metadata   # Provides the metadata parsing file corresponding to dev_trace_log.h.
       ├──logger_device.h          # External API header file, which provides serialization and deserialization APIs.
       ├──user.h
   ├── bin                          
       ├──tracelog                 # Tracelog command lines, which generate header files and parse log files based on the .ini file.
       ├──example.ini              # Input .ini file template for code generation, which is used to configure logs

Code Generation Example

  1. After decompressing the tool package, set the environment variable.
    1
    2
    cd /home/tracelog/bin     # Decompress the tool package in this path.
    export LD_LIBRARY_PATH=/home/tracelog/logger_device/lib:$LD_LIBRARY_PATH
    
  2. The following uses the /home/tracelog/user.ini configuration file as an example to describe how to generate code. A user.h file is generated in the path specified by the -o parameter.
    1
    ./tracelog generator -i /home/tracelog/user.ini -o /home/tracelog/logger_device/include
    

    Command output:

    1
    [INFO] The basic code has been generated to /home/tracelog/logger_device/include/user.h.
    

    Content of the user.ini file:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    memoryKBs=5120
    tracelog="/var/log/trace.log"
    
    [normal_example]
    name=char*
    id=int
    charactor=char
    
    [callstack_example]
    key=int
    callstack=3
    
    [pmu_example]
    key=int
    enablepmu=true
    

    The metadata file and header file are generated in the same directory.

  3. View the generated header file.
    1
    vim /home/tracelog/logger_device/include/user.h
    

    Content of the generated user.h file:

      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
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    #ifndef USER_H
    #define USER_H
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdbool.h>
    #include "logger_device.h"
    #define dev_tracepoint(module,event,...) dev_tracepoint_##module##_##event(__VA_ARGS__)
    #define MEMORY_KILOBYTES 5120
    #define TRACELOG_FILENAME "/var/log/trace.log"
    static inline __attribute__((always_inline)) int ConvertToCTFStr(DataStream *pDataStream, const char *str, size_t strLen)
    {
        char *buffer = (char *)pDataStream->log + pDataStream->consumeSize;
        memcpy(buffer, str, strLen);
        pDataStream->consumeSize += strLen;
        return 0;
    }
    static inline __attribute__((always_inline)) int ConvertToCTFChar(DataStream *pDataStream, char c)
    {
        char *buffer = (char *)pDataStream->log + pDataStream->consumeSize;
        *buffer = c;
        pDataStream->consumeSize += 1;
        return 0;
    }
    static inline __attribute__((always_inline)) int ConvertToCTFInt(DataStream *pDataStream, int i)
    {
        int *buffer = (int *)((char *)pDataStream->log + pDataStream->consumeSize);
        *buffer = i;
        pDataStream->consumeSize += sizeof(int);
        return 0;
    }
    static inline __attribute__((always_inline)) int GetStrLenLineNum(int lineNum)
    {
        int len = 1;
        int i = lineNum;
        while (i >= 10) {
            ++len;
            i = i / 10;
        }
        return len;
    }
    static int dev_tracepoint_user_normal_example(const char *name, int id, char charactor) 
    {
        int ret = InitLoggerDevice(TRACELOG_FILENAME, MEMORY_KILOBYTES, 1, NULL);
        if (ret != 0) {
            return ret;
        }
        size_t strLen_1 = strlen(name) + 1;
        size_t bodyLength = strLen_1 + 4 + 1;
        if (bodyLength > LOG_LENGTH) {
            return ERROR_LOG_TOO_LONG_FAIL;
        }
        size_t totalLength = (bodyLength + 40) * 8;
        DataStream dataStream = {0xC1FC1FC1, 0, totalLength, totalLength, 0, 0, {0}, 0};
        ConvertToCTFStr(&dataStream, name, strLen_1);
        ConvertToCTFInt(&dataStream, id);
        ConvertToCTFChar(&dataStream, charactor);
        return LoggerDeviceWriter(1, &dataStream);
    }
    static int dev_tracepoint_user_callstack_example_callstack(int key) 
    {
        int ret = InitLoggerDevice(TRACELOG_FILENAME, MEMORY_KILOBYTES, 1, NULL);
        if (ret != 0) {
            return ret;
        }
        CallStackResult cr = Backtrace(3);
        size_t bodyLength = 4;
        bodyLength += sizeof(cr);
        if (bodyLength > LOG_LENGTH) {
            return ERROR_LOG_TOO_LONG_FAIL;
        }
        size_t totalLength = (bodyLength + 40) * 8;
        DataStream dataStream = {0xC1FC1FC1, 1, totalLength, totalLength, 0, 0, {0}, 0};
        memcpy(dataStream.log + bodyLength - sizeof(cr), &cr, sizeof(cr));
        ConvertToCTFInt(&dataStream, key);
        return LoggerDeviceWriter(1, &dataStream);
    }
    static int dev_tracepoint_user_callstack_example(int key) 
    {
        int ret = InitLoggerDevice(TRACELOG_FILENAME, MEMORY_KILOBYTES, 1, NULL);
        if (ret != 0) {
            return ret;
        }
        size_t bodyLength = 4;
        if (bodyLength > LOG_LENGTH) {
            return ERROR_LOG_TOO_LONG_FAIL;
        }
        size_t totalLength = (bodyLength + 40) * 8;
        DataStream dataStream = {0xC1FC1FC1, 2, totalLength, totalLength, 0, 0, {0}, 0};
        ConvertToCTFInt(&dataStream, key);
        return LoggerDeviceWriter(1, &dataStream);
    }
    static int dev_tracepoint_user_pmu_example_enablepmu(int key) 
    {
        int ret = InitLoggerDevice(TRACELOG_FILENAME, MEMORY_KILOBYTES, 1, NULL);
        if (ret != 0) {
            return ret;
        }
        PmuResult pmuData = GetPmuData();
        size_t bodyLength = 4;
        bodyLength += sizeof(pmuData);
        if (bodyLength > LOG_LENGTH) {
            return ERROR_LOG_TOO_LONG_FAIL;
        }
        size_t totalLength = (bodyLength + 40) * 8;
        DataStream dataStream = {0xC1FC1FC1, 3, totalLength, totalLength, 0, 0, {0}, 0};
        memcpy(dataStream.log + bodyLength - sizeof(pmuData), &pmuData, sizeof(pmuData));
        ConvertToCTFInt(&dataStream, key);
        return LoggerDeviceWriter(1, &dataStream);
    }
    static int dev_tracepoint_user_pmu_example(int key) 
    {
        int ret = InitLoggerDevice(TRACELOG_FILENAME, MEMORY_KILOBYTES, 1, NULL);
        if (ret != 0) {
            return ret;
        }
        size_t bodyLength = 4;
        if (bodyLength > LOG_LENGTH) {
            return ERROR_LOG_TOO_LONG_FAIL;
        }
        size_t totalLength = (bodyLength + 40) * 8;
        DataStream dataStream = {0xC1FC1FC1, 4, totalLength, totalLength, 0, 0, {0}, 0};
        ConvertToCTFInt(&dataStream, key);
        return LoggerDeviceWriter(1, &dataStream);
    }
    #endif
    
  4. Re-specify the size of the cache used by the Tracer. You can change the value of the macro definition MEMORY_KILOBYTES in the user.h file.
    1
    #define MEMORY_KILOBYTES 6120
    
  5. Modify the paths to the trace.log and ProcMaps files. You can modify the value of the macro definition TRACELOG_FILENAME in the user.h file.
    1
    #define TRACELOG_FILENAME "/home/tracelog/custom.log"
    

Function Library Usage Example

  1. Prepare the demo file in advance. The demo file has referenced the generated user.h file.
    View the /home/tracelog/user_demo.c file.
    1
    vim /home/tracelog/user_demo.c
    

    File content:

    1
    2
    3
    4
    5
    6
    7
    8
    #include <stdio.h>
    #include "user.h"
    int main(){
        dev_tracepoint(user, normal_example, "hello", 18, 'a');
        dev_tracepoint(user, callstack_example_callstack, 4);  // The API that records callstack data is invoked.
        dev_tracepoint(user, pmu_example_enablepmu, 5);  // The API that records PMU data is invoked.
        DestroyLoggerDevice();
    }
    
    • dev_tracepoint(user, normal_example, "hello", 18, 'a'): calls the dev_tracepoint log API in the parameter type sequence defined in the .ini configuration file.
    • dev_tracepoint(user, callstack_example_callstack, 4): calls the log API of the callstack type.
    • dev_tracepoint(user, pmu_example_enablepmu, 5): calls the log API of the PMU type.
    • DestroyLoggerDevice(): stops the function library before the service application stops running.
  2. Compile user_demo.c.
    1
    gcc /home/tracelog/user_demo.c -I /home/tracelog/logger_device/include/ -l loggerdevice -L /home/tracelog/logger_device/lib -o /home/tracelog/user_demo -g -O0
    
    • -I: header file path.
    • -l: function library name.
    • -L: function library path.
    • -o: generated binary file.
  3. Append the LoggerDevice library path to the LD_LIBRARY_PATH environment variable.
    1
    export LD_LIBRARY_PATH=/home/tracelog/logger_device/lib:$LD_LIBRARY_PATH
    
  4. Run user_demo.
    1
    /home/tracelog/user_demo
    
    The custom.log1740206079754882 and ProcMaps files are generated in the /home/tracelog/ path specified in user.h.

    You can modify the macro definition in the generated header file to specify the log path. A log file name contains a timestamp and does not overwrite the system file. It contains service logs of the current user but does not contain Tracer logs. The file permission for log files is 600. Each log file is less than 100 MB and there is no log injection risk.

    • /home/tracelog/: path to the generated log file.
    • custom.log740206079754882: log file name.
    • ProcMaps: memory mapping information file. The metadata, ProcMaps, and log files are generated in the same directory.

Log Parsing Example

  1. For example, after users call the dev_tracepoint API in the user_demo.c file to compile and run an application, the custom.log1740467391374218 and ProcMaps files are generated in the /home/tracelog/ directory.

    dev_tracepoint API information:

    dev_tracepoint(user, normal_example, "hello", 18, 'a');
    dev_tracepoint(user, callstack_example, 4);
    dev_tracepoint(user, pmu_example, 5);
  2. Run the log parsing command.
    1
    2
    cd /home/tracelog/bin
    ./tracelog parser -md /home/tracelog/logger_device/include/metadata -tl /home/tracelog/custom.log1740467391374218 -mf /home/tracelog/ProcMaps
    

    Command output:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    [2025-05-15 16:06:29] str1 = "hello", i1 = 18, c1 = a
    [2025-05-15 16:06:29] i1 = 4, callstack = "Thread ID: 2533516
    Frame #00: [0x400bd0]
            dev_tracepoint_user_callstack_example at /home/tracelog/logger_device/include/user.h:69
    Frame #01: [0x400e18]
            main at /home/tracelog/user_demo.c:5
    Frame #02: [0xffff8059763c]
            UNKNOWN at (null):0
    "
    [2025-05-15 16:06:29] i1 = 5, Pmudata: tid = 2533320  cycles = 0