Skip to content

Commit d68af67

Browse files
authored
feat(nuclei): generate trace file when using profile-mem (#5690)
* feat(nuclei): generate trace file when using `profile-mem` Signed-off-by: Dwi Siswanto <[email protected]> * docs(DESIGN): dynamically grep mod path Signed-off-by: Dwi Siswanto <[email protected]> --------- Signed-off-by: Dwi Siswanto <[email protected]>
1 parent 888a732 commit d68af67

File tree

3 files changed

+69
-21
lines changed

3 files changed

+69
-21
lines changed

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,9 @@ pkg/protocols/common/helpers/deserialization/testdata/ValueObject2.ser
4242
vendor
4343

4444
# Headless `screenshot` action
45-
*.png
45+
*.png
46+
47+
# Profiling & tracing
48+
*.prof
49+
*.pprof
50+
*.trace

DESIGN.md

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -457,26 +457,49 @@ func (template *Template) compileProtocolRequests(options protocols.ExecuterOpti
457457
That's it, you've added a new protocol to Nuclei. The next good step would be to write integration tests which are described in `integration-tests` and `cmd/integration-tests` directories.
458458

459459

460-
## Profiling Instructions
460+
## Profiling and Tracing
461461

462-
To enable dumping of Memory profiling data, `-profile-mem` flag can be used along with path to a file. This writes a pprof formatted file which can be used for investigate resource usage with `pprof` tool.
462+
To analyze Nuclei's performance and resource usage, you can generate memory profiles and trace files using the `-profile-mem` flag:
463463

464-
```console
465-
$ nuclei -t nuclei-templates/ -u https://example.com -profile-mem mem.pprof
464+
```bash
465+
nuclei -t nuclei-templates/ -u https://example.com -profile-mem=nuclei-$(git describe --tags)
466466
```
467467

468-
To view profile data in pprof, first install pprof. Then run the below command -
468+
This command creates two files:
469469

470-
```console
471-
$ go tool pprof mem.pprof
470+
* `nuclei.prof`: Memory (heap) profile
471+
* `nuclei.trace`: Execution trace
472+
473+
### Analyzing the Memory Profile
474+
475+
1. View the profile in the terminal:
476+
477+
```bash
478+
go tool pprof nuclei.prof
479+
```
480+
481+
2. Display top memory consumers:
482+
483+
```bash
484+
go tool pprof -top nuclei.prof | grep "$(go list -m)" | head -10
472485
```
473486

474-
To open a web UI on a port to visualize debug data, the below command can be used.
487+
3. Visualize the profile in a web browser:
475488

476-
```console
477-
$ go tool pprof -http=:8081 mem.pprof
489+
```bash
490+
go tool pprof -http=:$(shuf -i 1000-99999 -n 1) nuclei.prof
478491
```
479492

493+
### Analyzing the Trace File
494+
495+
To examine the execution trace:
496+
497+
```bash
498+
go tool trace nuclei.trace
499+
```
500+
501+
These tools help identify performance bottlenecks and memory leaks, allowing for targeted optimizations of Nuclei's codebase.
502+
480503
## Project Structure
481504

482505
- [pkg/reporting](./pkg/reporting) - Reporting modules for nuclei.

cmd/nuclei/main.go

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"path/filepath"
1010
"runtime"
1111
"runtime/pprof"
12+
"runtime/trace"
1213
"strings"
1314
"time"
1415

@@ -103,21 +104,40 @@ func main() {
103104
return
104105
}
105106

106-
// Profiling related code
107+
// Profiling & tracing related code
107108
if memProfile != "" {
108-
f, err := os.Create(memProfile)
109+
memProfile = strings.TrimSuffix(memProfile, filepath.Ext(memProfile)) + ".prof"
110+
memProfileFile, err := os.Create(memProfile)
109111
if err != nil {
110-
gologger.Fatal().Msgf("profile: could not create memory profile %q: %v", memProfile, err)
112+
gologger.Fatal().Msgf("profile: could not create memory profile %q file: %v", memProfile, err)
111113
}
112-
old := runtime.MemProfileRate
114+
115+
traceFilepath := strings.TrimSuffix(memProfile, filepath.Ext(memProfile)) + ".trace"
116+
traceFile, err := os.Create(traceFilepath)
117+
if err != nil {
118+
gologger.Fatal().Msgf("profile: could not create trace %q file: %v", traceFilepath, err)
119+
}
120+
121+
oldMemProfileRate := runtime.MemProfileRate
113122
runtime.MemProfileRate = 4096
114-
gologger.Print().Msgf("profile: memory profiling enabled (rate %d), %s", runtime.MemProfileRate, memProfile)
123+
124+
// Start tracing
125+
if err := trace.Start(traceFile); err != nil {
126+
gologger.Fatal().Msgf("profile: could not start trace: %v", err)
127+
}
115128

116129
defer func() {
117-
_ = pprof.Lookup("heap").WriteTo(f, 0)
118-
f.Close()
119-
runtime.MemProfileRate = old
120-
gologger.Print().Msgf("profile: memory profiling disabled, %s", memProfile)
130+
// Start CPU profiling
131+
if err := pprof.WriteHeapProfile(memProfileFile); err != nil {
132+
gologger.Fatal().Msgf("profile: could not start CPU profile: %v", err)
133+
}
134+
memProfileFile.Close()
135+
traceFile.Close()
136+
trace.Stop()
137+
runtime.MemProfileRate = oldMemProfileRate
138+
139+
gologger.Info().Msgf("Memory profile saved at %q", memProfile)
140+
gologger.Info().Msgf("Traced at %q", traceFilepath)
121141
}()
122142
}
123143

@@ -402,7 +422,7 @@ on extensive configurability, massive extensibility and ease of use.`)
402422
flagSet.CallbackVar(printVersion, "version", "show nuclei version"),
403423
flagSet.BoolVarP(&options.HangMonitor, "hang-monitor", "hm", false, "enable nuclei hang monitoring"),
404424
flagSet.BoolVarP(&options.Verbose, "verbose", "v", false, "show verbose output"),
405-
flagSet.StringVar(&memProfile, "profile-mem", "", "optional nuclei memory profile dump file"),
425+
flagSet.StringVar(&memProfile, "profile-mem", "", "generate memory (heap) profile & trace files"),
406426
flagSet.BoolVar(&options.VerboseVerbose, "vv", false, "display templates loaded for scan"),
407427
flagSet.BoolVarP(&options.ShowVarDump, "show-var-dump", "svd", false, "show variables dump for debugging"),
408428
flagSet.BoolVarP(&options.EnablePprof, "enable-pprof", "ep", false, "enable pprof debugging server"),

0 commit comments

Comments
 (0)