DTrace Topics USDT
From Siwiki
Contents |
[edit] DTrace Topics: USDT
This article is about DTrace USDT, and is part of the DTrace Topics collection. A general understanding of DTrace is assumed knowledge, which can be studied from the DTrace Topics: Intro section.
DTrace is a dynamic troubleshooting and analysis tool first introduced in the Solaris 10 and OpenSolaris operating systems.
Completion
Difficulty
Audience Developers, DTrace users with source access
[edit] USDT
USDT is User-Level Statically Defined Tracing, and is a framework for placing custom probe points in application code.
For performance analysis and troubleshooting, programmers commonly instrument their applications by placing debug statements throughout the code - which are enabled either at compile time (by using compile flags), or at run time (config files). USDT serves a similar purpose, providing debug macros that can be customized and placed throughout the code.
[edit] USDT Features
- USDT probes are compiled in and are always available in both development and production code
- DTrace dynamically activates the USDT probes when required
- There is negligible CPU overhead from the addition of USDT probes when they are not in use
- This form of debugging benifits from standard DTrace features, such as,
- Rich reporting functionality (aggregations)
- Capability to walk memory structures as required
[edit] When to use USDT
USDT can help in many scenarios, but first - check the language of your program in DTrace Topics to see what can already be traced. For example, the pid provider allows all function entries and returns of C programs to be traced, including their arguments. Ever added a debug statement to print "function X began"? Well, pid already does that for you, for every function, dynamically.
Two good uses of USDT are,
- For tracing activity within a function
- For creating a high level provider with meaningful and stable probes
[edit] Function Activity
Your function either does either A, B or C, and you want to know which. See Hints for other techniques that may be available besides USDT.
[edit] High Level Provider
Adding a meaningful and stable provider will make life easier for all who need to analyse your application. For example, adding transaction-begin and transaction-end probes to your application server code to allow everyone to perform custom transaction based analysis without digging through the source code themselves.
Existing high level providers that use USDT include:
- JavaScript
- The JavaScript provider uses USDT to instrument the Mozilla JavaScript engine (libmozjs, which is written in C++ and is called "Spider Monkey"). It provides probes for function calls, object creation, garbage collection, and code execution. Users can use this provider to trace the operation of JavaScript code.
- iSCSI
- The iSCSI provider uses USDT to instrument the iSCSI target deamon. This provides high level and stable probes to allow iSCSI events to be traced on the server.
- Apache
- The Apache DTrace module is loaded with Apache and uses USDT to provide stable probes for Apache analysis.
[edit] Getting Started
To get started with USDT, work through the following steps to instrument a "Hello World!" style C program using basic USDT macros. This will demonstrate USDT concepts and compilation steps.
[edit] helloworld.c
[edit] Compiling
[edit] Adding a Probe
[edit] Defining a Provider
[edit] Compiling with USDT
[edit] Testing USDT
[edit] Provider Definition File
[edit] USDT Macros
To instrument C or C++ code, USDT macros are placed where appropriate. Three types can be used:
- Basic
- These are predefined macros that are ready for immediate use.
- Auto Generated
- After creating a provider definition file, the dtrace -h comand generates a header files of macros which contain the provider and probe name.
- Custom
- You can create your own header files with whatever macros are appropriate.
[edit] Basic
Basic USDT macros are defined in uts/common/sys/sdt.h and include,
#define DTRACE_PROBE(provider, name) { \
extern void __dtrace_##provider##___##name(void); \
__dtrace_##provider##___##name(); \
}
#define DTRACE_PROBE1(provider, name, arg1) { \
extern void __dtrace_##provider##___##name(unsigned long); \
__dtrace_##provider##___##name((unsigned long)arg1); \
}
#define DTRACE_PROBE2(provider, name, arg1, arg2) { \
extern void __dtrace_##provider##___##name(unsigned long, \
unsigned long); \
__dtrace_##provider##___##name((unsigned long)arg1, \
(unsigned long)arg2); \
}
[...]
Don't worry about the contents, we are just interested in the names and arguments for now, such as "DTRACE_PROBE2(provider, name, arg1, arg2)". You can probably guess the style of: DTRACE_PROBEn takes n of the arg probes.
[edit] Arguments
[edit] Examples
Examples of how these may be used,
| Example Code | Description |
| DTRACE_PROBE(sshd, login) | This could be placed in the sshd code to instrument when a user logs in |
| DTRACE_PROBE1(sshd, login, username) | This could instrument sshd logins, providing the username as the first argument |
| DTRACE_PROBE2(sshd, login, username, ipaddr) | This could instrument sshd logins, providing the username and IP address as arguments |
[edit] Auto-Generated
[edit] Custom
[edit] Resources
- Placing SDT and USDT probes by Alan Hargreaves
- USDT enhancements, is-enabled probes by Adam Leventhal
- Putting USDT probes in an Application by Bart Smaalders
