Skip to content

Commit b3567ec

Browse files
authored
Update the tracing of APIs in the validation layer with params (#404)
Signed-off-by: Neil R. Spruit <neil.r.spruit@intel.com>
1 parent b9dd43c commit b3567ec

14 files changed

Lines changed: 16220 additions & 2217 deletions

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,33 @@ validation layer is enabled. Following variables need to be set to enable API lo
8484
By default logs will be written to the log file, as described above. To print the logs
8585
to stderr instead, `ZEL_LOADER_LOG_CONSOLE=1` needs to be set.
8686

87+
The API logging output format includes both function entry and exit information, showing parameter names on entry and parameter values with the result code on exit. Each log entry is timestamped and includes the logger name and log level. Example output:
88+
89+
```
90+
[2026-01-14 09:01:38.951] [ze_loader] [trace] zeContextCreate(hDriver, desc, phContext)
91+
[2026-01-14 09:01:38.951] [ze_loader] [trace] SUCCESS (ZE_RESULT_SUCCESS) in zeContextCreate(hDriver=0x5b261fa70588, desc={stype=0x7ffdd20fe1e0, flags=0}, phContext=0x7ffdd20fe148)
92+
[2026-01-14 09:01:38.951] [ze_loader] [trace] zeCommandListCreateImmediate(hContext, hDevice, altdesc, phCommandList)
93+
[2026-01-14 09:01:38.951] [ze_loader] [trace] SUCCESS (ZE_RESULT_SUCCESS) in zeCommandListCreateImmediate(hContext=0x5b261fa74228, hDevice=0x5b261fa708b8, altdesc={stype=0x7ffdd20fe240, ordinal=0, index=0, flags=0, mode=0x7ffdd20fe25c, priority=0x7ffdd20fe260}, phCommandList=0x7ffdd20fe150)
94+
[2026-01-14 09:01:38.951] [ze_loader] [trace] zeEventPoolCreate(hContext, desc, numDevices, phDevicesLocal, phEventPool)
95+
[2026-01-14 09:01:38.951] [ze_loader] [trace] SUCCESS (ZE_RESULT_SUCCESS) in zeEventPoolCreate(hContext=0x5b261fa74228, desc={stype=0x7ffdd20fe200, flags=1, count=1}, numDevices=1, phDevices=0x7ffdd20fe138, phEventPool=0x7ffdd20fe160)
96+
[2026-01-14 09:01:38.951] [ze_loader] [trace] zeEventCreate(hEventPool, desc, phEvent)
97+
[2026-01-14 09:01:38.951] [ze_loader] [trace] SUCCESS (ZE_RESULT_SUCCESS) in zeEventCreate(hEventPool=0x5b261fa19c18, desc={stype=0x7ffdd20fe220, index=0, signal=4, wait=4}, phEvent=0x7ffdd20fe158)
98+
[2026-01-14 09:01:38.951] [ze_loader] [trace] zeCommandListAppendSignalEvent(hCommandList, hEvent)
99+
[2026-01-14 09:01:38.952] [ze_loader] [trace] SUCCESS (ZE_RESULT_SUCCESS) in zeCommandListAppendSignalEvent(hCommandList=0x5b261fa743c8, hEvent=0x5b261c69e5d8)
100+
[2026-01-14 09:01:38.952] [ze_loader] [trace] zeEventHostSynchronize(hEvent, timeout)
101+
[2026-01-14 09:01:38.954] [ze_loader] [trace] SUCCESS (ZE_RESULT_SUCCESS) in zeEventHostSynchronize(hEvent=0x5b261c69e5d8, timeout=18446744073709551615)
102+
[2026-01-14 09:01:38.954] [ze_loader] [trace] zeContextDestroy(hContext)
103+
[2026-01-14 09:01:38.954] [ze_loader] [trace] SUCCESS (ZE_RESULT_SUCCESS) in zeContextDestroy(hContext=0x5b261fa74228)
104+
[2026-01-14 09:01:38.954] [ze_loader] [trace] zeCommandListDestroy(hCommandList)
105+
[2026-01-14 09:01:38.955] [ze_loader] [trace] SUCCESS (ZE_RESULT_SUCCESS) in zeCommandListDestroy(hCommandList=0x5b261fa743c8)
106+
[2026-01-14 09:01:38.955] [ze_loader] [trace] zeEventDestroy(hEvent)
107+
[2026-01-14 09:01:38.955] [ze_loader] [trace] SUCCESS (ZE_RESULT_SUCCESS) in zeEventDestroy(hEvent=0x5b261c69e5d8)
108+
[2026-01-14 09:01:38.955] [ze_loader] [trace] zeEventPoolDestroy(hEventPool)
109+
[2026-01-14 09:01:38.955] [ze_loader] [trace] SUCCESS (ZE_RESULT_SUCCESS) in zeEventPoolDestroy(hEventPool=0x5b261fa19c18)
110+
```
111+
112+
113+
87114
# Driver/Device Sorting
88115

89116
As of v1.20.3 of the Loader, Drivers and Devices reported to the user are sorted to enable the first device to be the best available device.

scripts/generate_code.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Copyright (C) 2019-2025 Intel Corporation
2+
Copyright (C) 2019-2026 Intel Corporation
33
44
SPDX-License-Identifier: MIT
55
@@ -182,6 +182,7 @@ def _mako_loader_cpp(path, namespace, tags, version, specs, meta):
182182
'handle_lifetime.h.mako' : ('handle_lifetime_tracking', 'handle_lifetime.h'),
183183
'handle_lifetime.cpp.mako' : ('handle_lifetime_tracking', 'handle_lifetime.cpp'),
184184
'certification.h.mako' : ('checkers/certification/generated', 'certification.h'),
185+
'to_string.h.mako' : ('../../utils', 'to_string.h'),
185186
}
186187

187188
def _mako_validation_layer_cpp(path, namespace, tags, version, specs, meta):
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<%!
2+
import re
3+
from templates import helper as th
4+
%><%
5+
n=namespace
6+
N=n.upper()
7+
8+
x=tags['$x']
9+
X=x.upper()
10+
%>/*
11+
* ***THIS FILE IS GENERATED. ***
12+
* See to_string.h.mako for modifications
13+
*
14+
* Copyright (C) 2025-2026 Intel Corporation
15+
*
16+
* SPDX-License-Identifier: MIT
17+
*
18+
* @file ${name}
19+
*
20+
* to_string functions for Level Zero types
21+
*/
22+
23+
#ifndef _${N}_TO_STRING_H
24+
#define _${N}_TO_STRING_H
25+
26+
#include "${x}_api.h"
27+
#include <string>
28+
#include <sstream>
29+
#include <iomanip>
30+
31+
%if n == 'ze':
32+
namespace loader {
33+
34+
// Forward declarations
35+
std::string to_string(const ${x}_result_t result);
36+
37+
// Pointer to_string
38+
template<typename T>
39+
inline std::string to_string(const T* ptr) {
40+
if (ptr == nullptr) {
41+
return "nullptr";
42+
}
43+
std::ostringstream oss;
44+
oss << "0x" << std::hex << reinterpret_cast<uintptr_t>(ptr);
45+
return oss.str();
46+
}
47+
48+
%else:
49+
// Include ze_to_string.h for common definitions
50+
#include "ze_to_string.h"
51+
52+
namespace loader {
53+
%endif
54+
%if n == 'ze':
55+
// Handle to_string functions
56+
%for obj in th.extract_objs(specs, r"handle"):
57+
inline std::string to_string(${th.make_type_name(n, tags, obj)} handle) {
58+
return to_string(reinterpret_cast<const void*>(handle));
59+
}
60+
61+
%endfor
62+
%endif
63+
%if n == 'ze':
64+
// For primitive types and Level Zero typedef'd types
65+
// Since most Level Zero types are typedef'd to uint32_t, we can't distinguish them by type
66+
inline std::string to_string(uint32_t value) { return std::to_string(value); }
67+
inline std::string to_string(uint64_t value) { return std::to_string(value); }
68+
inline std::string to_string(uint8_t value) { return std::to_string(static_cast<unsigned>(value)); }
69+
inline std::string to_string(uint16_t value) { return std::to_string(value); }
70+
inline std::string to_string(int32_t value) { return std::to_string(value); }
71+
inline std::string to_string(int64_t value) { return std::to_string(value); }
72+
#if SIZE_MAX != UINT64_MAX
73+
inline std::string to_string(size_t value) { return std::to_string(value); }
74+
#endif
75+
inline std::string to_string(double value) { return std::to_string(value); }
76+
inline std::string to_string(const char* str) {
77+
if (!str) return "nullptr";
78+
return std::string("\"") + str + "\"";
79+
}
80+
81+
// Pointer to primitive types - dereference and print value
82+
inline std::string to_string(const uint32_t* ptr) {
83+
if (!ptr) return "nullptr";
84+
return to_string(*ptr);
85+
}
86+
inline std::string to_string(const uint64_t* ptr) {
87+
if (!ptr) return "nullptr";
88+
return to_string(*ptr);
89+
}
90+
inline std::string to_string(const uint8_t* ptr) {
91+
if (!ptr) return "nullptr";
92+
return to_string(*ptr);
93+
}
94+
inline std::string to_string(const uint16_t* ptr) {
95+
if (!ptr) return "nullptr";
96+
return to_string(*ptr);
97+
}
98+
inline std::string to_string(const int32_t* ptr) {
99+
if (!ptr) return "nullptr";
100+
return to_string(*ptr);
101+
}
102+
inline std::string to_string(const int64_t* ptr) {
103+
if (!ptr) return "nullptr";
104+
return to_string(*ptr);
105+
}
106+
#if SIZE_MAX != UINT64_MAX
107+
inline std::string to_string(const size_t* ptr) {
108+
if (!ptr) return "nullptr";
109+
return to_string(*ptr);
110+
}
111+
#endif
112+
inline std::string to_string(const double* ptr) {
113+
if (!ptr) return "nullptr";
114+
return to_string(*ptr);
115+
}
116+
117+
%endif
118+
// Struct to_string functions
119+
%for obj in th.extract_objs(specs, r"struct"):
120+
<%
121+
struct_name = th.make_type_name(n, tags, obj)
122+
%>\
123+
inline std::string to_string(const ${struct_name}* desc) {
124+
if (!desc) return "nullptr";
125+
std::ostringstream oss;
126+
oss << "{";
127+
%for idx, member in enumerate(obj['members']):
128+
%if member['name'] != 'pNext':
129+
<%
130+
# Extract the actual member name without array brackets
131+
member_name_full = member['name']
132+
member_name = member_name_full.split('[')[0] if '[' in member_name_full else member_name_full
133+
is_array = '[' in member_name_full
134+
135+
# Check if member is a pointer or regular value
136+
member_type = member.get('type', '')
137+
if is_array:
138+
# For arrays, just pass the array name (decays to pointer)
139+
member_access = f"desc->{member_name}"
140+
elif '*' in member_type:
141+
# It's already a pointer - pass directly
142+
member_access = f"desc->{member_name}"
143+
else:
144+
# Check if it's a struct type by looking at the type name
145+
# If it contains a struct typename pattern, take its address
146+
if '_t' in member_type and 'uint' not in member_type and 'int' not in member_type and 'size_t' not in member_type:
147+
member_access = f"&desc->{member_name}"
148+
else:
149+
member_access = f"desc->{member_name}"
150+
%>\
151+
%if idx == 0 and member['name'] == 'stype':
152+
oss << "stype=" << to_string(${member_access});
153+
%elif idx == 0:
154+
oss << "${member_name}=" << to_string(${member_access});
155+
%else:
156+
oss << ", ${member_name}=" << to_string(${member_access});
157+
%endif
158+
%endif
159+
%endfor
160+
oss << "}";
161+
return oss.str();
162+
}
163+
164+
inline std::string to_string(const ${struct_name}& desc) {
165+
return to_string(&desc);
166+
}
167+
168+
%endfor
169+
} // namespace loader
170+
171+
#endif // _${N}_TO_STRING_H

0 commit comments

Comments
 (0)