Stefan Schuermans commited on 2020-05-22 13:32:43
Showing 11 changed files, with 210 additions and 14 deletions.
also add test to trace build, add readme
| ... | ... |
@@ -0,0 +1,102 @@ |
| 1 |
+# UProcTrace: User-space Process Tracing |
|
| 2 |
+ |
|
| 3 |
+UProcTrace traces process executions and process ends on Linux systems. |
|
| 4 |
+ |
|
| 5 |
+On process starts, UProcTrace records the time, the entire command line, |
|
| 6 |
+working directory and environment. On process end, it logs the CPU time used by |
|
| 7 |
+the process (split by user and kernel time) and the peak memory usage. |
|
| 8 |
+ |
|
| 9 |
+UProcTrace is implemented in user-space, so does not reuire any special kernel |
|
| 10 |
+modules. This means it can also be used in containers (e.g. docker) without |
|
| 11 |
+any changes the to conteiner host. The implementation is based on the |
|
| 12 |
+`LD_PRELOAD` mechanism. A shared library is injected into each process |
|
| 13 |
+started. This libarary records trace events at begin of the process (when the |
|
| 14 |
+preload library is initialized) and at the end of the process (when the library |
|
| 15 |
+is de-initiazlied). |
|
| 16 |
+ |
|
| 17 |
+## Building |
|
| 18 |
+ |
|
| 19 |
+UProcTrace is developed on Debian Linux 10 "buster". |
|
| 20 |
+ |
|
| 21 |
+Install the prerequisites: |
|
| 22 |
+ |
|
| 23 |
+``` |
|
| 24 |
+apt-get install -y build-essential cmake gcc \ |
|
| 25 |
+ libprotobuf-c-dev libprotobuf-dev |
|
| 26 |
+ ninja-build \ |
|
| 27 |
+ protobuf-c-compiler protobuf-compiler \ |
|
| 28 |
+ python3 python3-protobuf |
|
| 29 |
+``` |
|
| 30 |
+ |
|
| 31 |
+Change to the directory of this `REAMDE.md` file. |
|
| 32 |
+ |
|
| 33 |
+Configure a build directory: |
|
| 34 |
+ |
|
| 35 |
+``` |
|
| 36 |
+mkdir build |
|
| 37 |
+cd build |
|
| 38 |
+cmake -G Ninja -D CMAKE_BUILD_TYPE=Release .. |
|
| 39 |
+``` |
|
| 40 |
+ |
|
| 41 |
+Build: |
|
| 42 |
+ |
|
| 43 |
+``` |
|
| 44 |
+ninja |
|
| 45 |
+``` |
|
| 46 |
+ |
|
| 47 |
+Run tests: |
|
| 48 |
+ |
|
| 49 |
+``` |
|
| 50 |
+ctest |
|
| 51 |
+``` |
|
| 52 |
+ |
|
| 53 |
+## Tracing Applications |
|
| 54 |
+ |
|
| 55 |
+To trace an application, prefix the command with `upt-trace` and the |
|
| 56 |
+file name for the trace. For example, to trace the command |
|
| 57 |
+``` |
|
| 58 |
+/usr/bin/printf "trace me" |
|
| 59 |
+``` |
|
| 60 |
+run the following command: |
|
| 61 |
+``` |
|
| 62 |
+<build dir>/bin/upt-trace mytrace.proto /usr/bin/printf "trace me" |
|
| 63 |
+``` |
|
| 64 |
+ |
|
| 65 |
+To show the recorded events, run: |
|
| 66 |
+``` |
|
| 67 |
+<build dir>/dump/dump.py mytrace.proto |
|
| 68 |
+``` |
|
| 69 |
+ |
|
| 70 |
+## Example: Trace Build Process |
|
| 71 |
+ |
|
| 72 |
+To show the capabilities of the UProcTrace, a process that calls several child |
|
| 73 |
+processes is required. In this example, the build of UProcTrace is used for |
|
| 74 |
+this purpose. |
|
| 75 |
+ |
|
| 76 |
+Change to the build directory. |
|
| 77 |
+ |
|
| 78 |
+Start a new shell to be traced: |
|
| 79 |
+``` |
|
| 80 |
+bin/upt-trace mytrace.proto bash |
|
| 81 |
+``` |
|
| 82 |
+ |
|
| 83 |
+Configure another build directory for this tracing example and run the build: |
|
| 84 |
+ |
|
| 85 |
+``` |
|
| 86 |
+mkdir example_trace_build |
|
| 87 |
+cd example_trace_build |
|
| 88 |
+cmake -G Ninja -D CMAKE_BUILD_TYPE=Release ../.. |
|
| 89 |
+ninja |
|
| 90 |
+``` |
|
| 91 |
+ |
|
| 92 |
+Stop tracing by ending the shell: |
|
| 93 |
+ |
|
| 94 |
+``` |
|
| 95 |
+exit |
|
| 96 |
+``` |
|
| 97 |
+ |
|
| 98 |
+Show traced information: |
|
| 99 |
+``` |
|
| 100 |
+dump/dump.py mytrace.proto |
|
| 101 |
+``` |
|
| 102 |
+ |
| ... | ... |
@@ -2,18 +2,5 @@ add_test( |
| 2 | 2 |
NAME |
| 3 | 3 |
first |
| 4 | 4 |
COMMAND |
| 5 |
- bash -c |
|
| 6 |
- " |
|
| 7 |
- set -eux -o pipefail |
|
| 8 |
- > out.proto |
|
| 9 |
- ( |
|
| 10 |
- export UPTPL_OUTPUT=out.proto |
|
| 11 |
- export LD_PRELOAD=${CMAKE_BINARY_DIR}/libuptpl/libuptpl.so
|
|
| 12 |
- /bin/true a b 'c d' |
|
| 13 |
- /usr/bin/printf '' e f 'g h' |
|
| 14 |
- ) |
|
| 15 |
- ls -l out.proto |
|
| 16 |
- ${CMAKE_BINARY_DIR}/dump/dump.py out.proto | tee out.dump
|
|
| 17 |
- grep '^ *event *{ *$' out.dump | wc -l | grep '^4$'
|
|
| 18 |
- " |
|
| 5 |
+ ${CMAKE_CURRENT_SOURCE_DIR}/first.bash ${CMAKE_BINARY_DIR}
|
|
| 19 | 6 |
) |
| ... | ... |
@@ -0,0 +1,22 @@ |
| 1 |
+#! /bin/bash |
|
| 2 |
+ |
|
| 3 |
+set -eux -o pipefail |
|
| 4 |
+ |
|
| 5 |
+if (( $# < 1 )) |
|
| 6 |
+then |
|
| 7 |
+ echo "usage: $0 <UPT_HOME>" >&2 |
|
| 8 |
+ exit 2 |
|
| 9 |
+fi |
|
| 10 |
+UPT_HOME="$1" |
|
| 11 |
+ |
|
| 12 |
+SCRIPT_DIR="$(dirname "$0")" |
|
| 13 |
+ |
|
| 14 |
+rm -rf out.proto |
|
| 15 |
+ |
|
| 16 |
+"$UPT_HOME/bin/upt-trace" out.proto "$SCRIPT_DIR/traceme.bash" |
|
| 17 |
+ |
|
| 18 |
+ls -l out.proto |
|
| 19 |
+ |
|
| 20 |
+"$UPT_HOME/dump/dump.py" out.proto | tee out.dump |
|
| 21 |
+grep '^ *event *{ *$' out.dump | wc -l | tee out.event_cnt
|
|
| 22 |
+grep '^6$' out.event_cnt |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 1 |
+#! /bin/bash |
|
| 2 |
+ |
|
| 3 |
+set -eux -o pipefail |
|
| 4 |
+ |
|
| 5 |
+if (( $# < 1 )) |
|
| 6 |
+then |
|
| 7 |
+ echo "usage: $0 <SOURCE_DIR>" >&2 |
|
| 8 |
+ exit 2 |
|
| 9 |
+fi |
|
| 10 |
+SOURCE_DIR="$(readlink -f "$1")" |
|
| 11 |
+ |
|
| 12 |
+ |
|
| 13 |
+mkdir build |
|
| 14 |
+cd build |
|
| 15 |
+cmake -G Ninja -D CMAKE_BUILD_TYPE=Release "$SOURCE_DIR" |
|
| 16 |
+ninja |
| ... | ... |
@@ -0,0 +1,24 @@ |
| 1 |
+#! /bin/bash |
|
| 2 |
+ |
|
| 3 |
+set -eux -o pipefail |
|
| 4 |
+ |
|
| 5 |
+if (( $# < 2 )) |
|
| 6 |
+then |
|
| 7 |
+ echo "usage: $0 <SOURCE_DIR> <UPT_HOME>" >&2 |
|
| 8 |
+ exit 2 |
|
| 9 |
+fi |
|
| 10 |
+SOURCE_DIR="$(readlink -f "$1")" |
|
| 11 |
+UPT_HOME="$(readlink -f "$2")" |
|
| 12 |
+ |
|
| 13 |
+SCRIPT_DIR="$(dirname "$0")" |
|
| 14 |
+ |
|
| 15 |
+rm -rf out.proto build |
|
| 16 |
+ |
|
| 17 |
+"$UPT_HOME/bin/upt-trace" out.proto "$SCRIPT_DIR/run_build.bash" "$SOURCE_DIR" |
|
| 18 |
+ |
|
| 19 |
+ls -l out.proto |
|
| 20 |
+ |
|
| 21 |
+"$UPT_HOME/dump/dump.py" out.proto | tee out.dump |
|
| 22 |
+grep -A 1 '^ *cmdline {$' out.dump | grep '^ *s: "mkdir"$'
|
|
| 23 |
+grep '^ *s: "proc_begin.c"$' out.dump |
|
| 24 |
+grep '^ *s: "libuptpl.so"$' out.dump |
| ... | ... |
@@ -0,0 +1,16 @@ |
| 1 |
+add_custom_command( |
|
| 2 |
+ OUTPUT |
|
| 3 |
+ ${CMAKE_BINARY_DIR}/bin/upt-trace
|
|
| 4 |
+ DEPENDS |
|
| 5 |
+ ${CMAKE_CURRENT_SOURCE_DIR}/upt-trace.bash
|
|
| 6 |
+ COMMAND |
|
| 7 |
+ cp -a ${CMAKE_CURRENT_SOURCE_DIR}/upt-trace.bash
|
|
| 8 |
+ ${CMAKE_BINARY_DIR}/bin/upt-trace
|
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+add_custom_target( |
|
| 12 |
+ upt-trace |
|
| 13 |
+ ALL |
|
| 14 |
+ DEPENDS |
|
| 15 |
+ ${CMAKE_BINARY_DIR}/bin/upt-trace
|
|
| 16 |
+) |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 1 |
+#! /bin/bash |
|
| 2 |
+ |
|
| 3 |
+if (( $# < 2 )) |
|
| 4 |
+then |
|
| 5 |
+ echo "usage: $0 <upt-trace-file.proto> <command> [<arg> [...]]" >&2 |
|
| 6 |
+ exit 2 |
|
| 7 |
+fi |
|
| 8 |
+TRACE_FILE="$1" |
|
| 9 |
+shift |
|
| 10 |
+ |
|
| 11 |
+UPT_HOME="$(readlink -f "$(dirname "$(dirname "$0")")")" |
|
| 12 |
+ |
|
| 13 |
+touch "$TRACE_FILE" |
|
| 14 |
+export UPTPL_OUTPUT="$(readlink -f "$TRACE_FILE")" |
|
| 15 |
+export LD_PRELOAD="$UPT_HOME/libuptpl/libuptpl.so" |
|
| 16 |
+ |
|
| 17 |
+exec "$@" |
|
| 0 | 18 |