# scripts/lib/trace-extract.awk # Extract instrumented source locations from xtrace logs produced via # scripts/lib/trace-init.sh. # # Marker lines look like (bash repeats the leading '@' once per nesting level): # @@TBL@@ /path/to/trbldoc.sh:1234 1712345678.123456 # # Variables: # MODE=cov (default) -> prints "\t" per marker line # MODE=time -> prints "\t\t\t" at END, # computing per-line durations from consecutive markers # WITHIN each trace file (one file == one process, so # parallel xargs workers are not cross-attributed). function basename(p) { sub(/.*\//, "", p) # strip up to last forward slash sub(/.*\\/, "", p) # strip up to last backslash (defensive) return p } # Parse a marker line into globals g_base and g_line (and g_epoch for time). # Returns 1 on success, 0 if the line is not a usable marker. function parse(line, s, n, f, loc, rest) { if (line !~ /@+TBL@@ /) return 0 s = line sub(/^.*TBL@@ /, "", s) # drop marker and everything before it n = split(s, f, " ") if (n < 1) return 0 loc = f[1] # : if (!match(loc, /:[0-9]+$/)) return 0 g_line = substr(loc, RSTART + 1) g_base = basename(substr(loc, 1, RSTART - 1)) if (MODE == "time") { g_epoch = (n >= 2 ? f[2] : "") } return 1 } BEGIN { if (MODE == "") MODE = "cov" } # Reset per-process state at the start of each trace file. FNR == 1 { have_prev = 0 } { if (!parse($0)) next if (MODE == "cov") { print g_base "\t" g_line next } # MODE == time: attribute elapsed time to the PREVIOUS marker. if (have_prev && g_epoch != "" && prev_epoch != "") { d = g_epoch - prev_epoch if (d < 0) d = 0 key = prev_base SUBSEP prev_line ms[key] += d * 1000.0 hits[key] += 1 base_of[key] = prev_base line_of[key] = prev_line } prev_base = g_base prev_line = g_line prev_epoch = g_epoch have_prev = 1 } END { if (MODE != "time") exit for (k in ms) { printf "%.3f\t%d\t%s\t%s\n", ms[k], hits[k], base_of[k], line_of[k] } }