Skip to content

Commit b3e450c

Browse files
authored
[releases/2.3] service: Enable type checking for tracelogging (#1185)
service: Enable type checking for tracelogging (#1123) * service: Remove ignore_missing_imports for traceloggingdynamic * service: Update traceloggingdynamic in poetry.lock * service: Fix _tracelogging typing bugs * service: Only try to import traceloggingdynamic on Windows * service: Install traceloggingdynamic as a dev dependency on Linux for type checking * service: Update poetry.lock * Revert "service: Only try to import traceloggingdynamic on Windows" This reverts commit 8215a0e. * service: Try to import traceloggingdynamic on all platforms for type hints, but only create a provider on Windows * service: Import traceloggingdynamic on Windows and when type checking (cherry picked from commit 45f53e6)
1 parent 88ca43f commit b3e450c

5 files changed

Lines changed: 2601 additions & 10 deletions

File tree

packages/service/ni_measurement_plugin_sdk_service/_tracelogging.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,21 @@
33
import ctypes
44
import sys
55
import uuid
6+
from typing import TYPE_CHECKING
67

7-
try:
8-
import traceloggingdynamic
8+
if sys.platform == "win32":
9+
try:
10+
import traceloggingdynamic
11+
12+
_event_provider: traceloggingdynamic.Provider | None = traceloggingdynamic.Provider(
13+
b"NI-Measurement-Plug-In-Python"
14+
)
15+
except ImportError:
16+
_event_provider = None
17+
else:
18+
if TYPE_CHECKING:
19+
import traceloggingdynamic
920

10-
_event_provider = traceloggingdynamic.Provider(b"NI-Measurement-Plug-In-Python")
11-
except ImportError:
1221
_event_provider = None
1322

1423
_LEVEL_LOG_ALWAYS = 0
@@ -72,7 +81,7 @@ def _get_current_thread_activity_id() -> uuid.UUID:
7281

7382
def is_enabled() -> bool:
7483
"""Queries whether the event provider is enabled."""
75-
return _event_provider and _event_provider.is_enabled()
84+
return _event_provider is not None and _event_provider.is_enabled()
7685

7786

7887
def log_grpc_client_call_start(method_name: str) -> uuid.UUID | None:
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
from __future__ import annotations
2+
3+
import ctypes
4+
import sys
5+
import uuid
6+
<<<<<<< HEAD
7+
=======
8+
from typing import TYPE_CHECKING
9+
>>>>>>> 714eda9 (service: Enable type checking for tracelogging (#1123))
10+
11+
if sys.platform == "win32":
12+
try:
13+
import traceloggingdynamic
14+
15+
_event_provider: traceloggingdynamic.Provider | None = traceloggingdynamic.Provider(
16+
b"NI-Measurement-Plug-In-Python"
17+
)
18+
except ImportError:
19+
_event_provider = None
20+
else:
21+
if TYPE_CHECKING:
22+
import traceloggingdynamic
23+
24+
_event_provider = None
25+
26+
_LEVEL_LOG_ALWAYS = 0
27+
_LEVEL_CRITICAL = 1
28+
_LEVEL_ERROR = 3
29+
_LEVEL_WARNING = 3
30+
_LEVEL_INFO = 4
31+
_LEVEL_VERBOSE = 5
32+
33+
_OPCODE_INFO = 0
34+
_OPCODE_START = 1
35+
_OPCODE_STOP = 2
36+
37+
_KEYWORD_NONE = 0
38+
_KEYWORD_GRPC = 1 << 0
39+
40+
_TASK_GRPC_CLIENT_CALL = 1
41+
_TASK_GRPC_SERVER_CALL = 2
42+
43+
44+
if sys.platform == "win32":
45+
# 0x00000800 = LOAD_LIBRARY_SEARCH_SYSTEM32 (Win8 or later)
46+
_eventing_dll = ctypes.WinDLL("api-ms-win-eventing-provider-l1-1-0.dll", mode=0x00000800)
47+
48+
_EventActivityIdControl = _eventing_dll.EventActivityIdControl
49+
_EventActivityIdControl.restype = ctypes.c_uint32
50+
_EventActivityIdControl.argtypes = (ctypes.c_uint32, ctypes.c_void_p)
51+
52+
_EVENT_ACTIVITY_CTRL_GET_ID = 1
53+
_EVENT_ACTIVITY_CTRL_SET_ID = 2
54+
_EVENT_ACTIVITY_CTRL_CREATE_ID = 3
55+
_EVENT_ACTIVITY_CTRL_GET_SET_ID = 4
56+
_EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5
57+
58+
def _create_activity_id() -> uuid.UUID:
59+
activity_bytes = (ctypes.c_byte * 16)()
60+
status = _EventActivityIdControl(
61+
_EVENT_ACTIVITY_CTRL_CREATE_ID, ctypes.pointer(activity_bytes)
62+
)
63+
if status != 0:
64+
raise OSError("EventActivityIdControl error", status)
65+
return uuid.UUID(bytes_le=bytes(activity_bytes))
66+
67+
def _get_current_thread_activity_id() -> uuid.UUID:
68+
activity_bytes = (ctypes.c_byte * 16)()
69+
status = _EventActivityIdControl(
70+
_EVENT_ACTIVITY_CTRL_GET_ID, ctypes.pointer(activity_bytes)
71+
)
72+
if status != 0:
73+
raise OSError("EventActivityIdControl error", status)
74+
return uuid.UUID(bytes_le=bytes(activity_bytes))
75+
76+
else:
77+
78+
def _create_activity_id() -> uuid.UUID:
79+
return uuid.uuid4()
80+
81+
def _get_current_thread_activity_id() -> uuid.UUID:
82+
return uuid.UUID()
83+
84+
85+
def is_enabled() -> bool:
86+
"""Queries whether the event provider is enabled."""
87+
return _event_provider is not None and _event_provider.is_enabled()
88+
89+
90+
def log_grpc_client_call_start(method_name: str) -> uuid.UUID | None:
91+
"""Log when starting a gRPC client call."""
92+
if _event_provider and _event_provider.is_enabled(level=_LEVEL_INFO, keyword=_KEYWORD_GRPC):
93+
eb = traceloggingdynamic.EventBuilder()
94+
eb.reset(
95+
b"GrpcClientCall",
96+
level=_LEVEL_INFO,
97+
keyword=_KEYWORD_GRPC,
98+
opcode=_OPCODE_START,
99+
task=_TASK_GRPC_CLIENT_CALL,
100+
)
101+
eb.add_str8(b"FormattedMessage", "gRPC client call starting: " + method_name)
102+
activity_id = _create_activity_id()
103+
related_activity_id = _get_current_thread_activity_id()
104+
_event_provider.write(eb, activity_id, related_activity_id)
105+
return activity_id
106+
else:
107+
return None
108+
109+
110+
def log_grpc_client_call_stop(method_name: str, activity_id: uuid.UUID | None = None) -> None:
111+
"""Log when a gRPC client call has completed."""
112+
if _event_provider and _event_provider.is_enabled(level=_LEVEL_INFO, keyword=_KEYWORD_GRPC):
113+
eb = traceloggingdynamic.EventBuilder()
114+
eb.reset(
115+
b"GrpcClientCall",
116+
level=_LEVEL_INFO,
117+
keyword=_KEYWORD_GRPC,
118+
opcode=_OPCODE_STOP,
119+
task=_TASK_GRPC_CLIENT_CALL,
120+
)
121+
eb.add_str8(b"FormattedMessage", "gRPC client call complete: " + method_name)
122+
_event_provider.write(eb, activity_id)
123+
124+
125+
def log_grpc_client_call_streaming_request(method_name: str) -> None:
126+
"""Log when a gRPC client call is sending a client-streaming request."""
127+
if _event_provider and _event_provider.is_enabled(level=_LEVEL_INFO, keyword=_KEYWORD_GRPC):
128+
eb = traceloggingdynamic.EventBuilder()
129+
eb.reset(
130+
b"GrpcClientCallStreamingRequest",
131+
level=_LEVEL_INFO,
132+
keyword=_KEYWORD_GRPC,
133+
opcode=_OPCODE_INFO,
134+
)
135+
eb.add_str8(b"FormattedMessage", "gRPC client call streaming request: " + method_name)
136+
_event_provider.write(eb)
137+
138+
139+
def log_grpc_client_call_streaming_response(method_name: str) -> None:
140+
"""Log when a gRPC client call has received a server-streaming response."""
141+
if _event_provider and _event_provider.is_enabled(level=_LEVEL_INFO, keyword=_KEYWORD_GRPC):
142+
eb = traceloggingdynamic.EventBuilder()
143+
eb.reset(
144+
b"GrpcClientCallStreamingResponse",
145+
level=_LEVEL_INFO,
146+
keyword=_KEYWORD_GRPC,
147+
opcode=_OPCODE_INFO,
148+
)
149+
eb.add_str8(b"FormattedMessage", "gRPC client call streaming response: " + method_name)
150+
_event_provider.write(eb)
151+
152+
153+
def log_grpc_server_call_start(method_name: str) -> uuid.UUID | None:
154+
"""Log when starting a gRPC server call."""
155+
if _event_provider and _event_provider.is_enabled(level=_LEVEL_INFO, keyword=_KEYWORD_GRPC):
156+
eb = traceloggingdynamic.EventBuilder()
157+
eb.reset(
158+
b"GrpcServerCall",
159+
level=_LEVEL_INFO,
160+
keyword=_KEYWORD_GRPC,
161+
opcode=_OPCODE_START,
162+
task=_TASK_GRPC_SERVER_CALL,
163+
)
164+
eb.add_str8(b"FormattedMessage", "gRPC server call starting: " + method_name)
165+
activity_id = _create_activity_id()
166+
related_activity_id = _get_current_thread_activity_id()
167+
_event_provider.write(eb, activity_id, related_activity_id)
168+
return activity_id
169+
else:
170+
return None
171+
172+
173+
def log_grpc_server_call_stop(method_name: str, activity_id: uuid.UUID | None = None) -> None:
174+
"""Log when a gRPC server call has completed."""
175+
if _event_provider and _event_provider.is_enabled(level=_LEVEL_INFO, keyword=_KEYWORD_GRPC):
176+
eb = traceloggingdynamic.EventBuilder()
177+
eb.reset(
178+
b"GrpcServerCall",
179+
level=_LEVEL_INFO,
180+
keyword=_KEYWORD_GRPC,
181+
opcode=_OPCODE_STOP,
182+
task=_TASK_GRPC_SERVER_CALL,
183+
)
184+
eb.add_str8(b"FormattedMessage", "gRPC server call complete: " + method_name)
185+
_event_provider.write(eb, activity_id)
186+
187+
188+
def log_grpc_server_call_streaming_request(method_name: str) -> None:
189+
"""Log when a gRPC server call is sending a server-streaming request."""
190+
if _event_provider and _event_provider.is_enabled(level=_LEVEL_INFO, keyword=_KEYWORD_GRPC):
191+
eb = traceloggingdynamic.EventBuilder()
192+
eb.reset(
193+
b"GrpcServerCallStreamingRequest",
194+
level=_LEVEL_INFO,
195+
keyword=_KEYWORD_GRPC,
196+
opcode=_OPCODE_INFO,
197+
)
198+
eb.add_str8(b"FormattedMessage", "gRPC server call streaming request: " + method_name)
199+
_event_provider.write(eb)
200+
201+
202+
def log_grpc_server_call_streaming_response(method_name: str) -> None:
203+
"""Log when a gRPC server call has received a server-streaming response."""
204+
if _event_provider and _event_provider.is_enabled(level=_LEVEL_INFO, keyword=_KEYWORD_GRPC):
205+
eb = traceloggingdynamic.EventBuilder()
206+
eb.reset(
207+
b"GrpcServerCallStreamingResponse",
208+
level=_LEVEL_INFO,
209+
keyword=_KEYWORD_GRPC,
210+
opcode=_OPCODE_INFO,
211+
)
212+
eb.add_str8(b"FormattedMessage", "gRPC server call streaming response: " + method_name)
213+
_event_provider.write(eb)

packages/service/poetry.lock

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)