summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/flags/flags.go2
-rw-r--r--internal/ior_mode_registry.go2
-rw-r--r--internal/ior_mode_test.go17
-rw-r--r--internal/ior_parquet_sink.go7
4 files changed, 17 insertions, 11 deletions
diff --git a/internal/flags/flags.go b/internal/flags/flags.go
index e7171ce..285569c 100644
--- a/internal/flags/flags.go
+++ b/internal/flags/flags.go
@@ -170,7 +170,7 @@ func registerFlags(fs *flag.FlagSet, cfg *Config) (tpsAttach, tpsExclude, fields
fs.BoolVar(&cfg.PlainMode, "plain", false, "Enable plain CSV output mode (disable TUI)")
fs.BoolVar(&cfg.FlamegraphOutput, "flamegraph", false, "Write aggregated .ior.zst output for trace/integration workflows")
- fs.StringVar(&cfg.ParquetPath, "parquet", cfg.ParquetPath, "Write all traced syscall rows directly to a parquet file in headless mode (skip the TUI; incompatible with -plain, -flamegraph, --testflames, --testliveflames, and content filters)")
+ fs.StringVar(&cfg.ParquetPath, "parquet", cfg.ParquetPath, "Write traced syscall rows directly to a parquet file in headless mode (skip the TUI; compatible with -pid; incompatible with -plain, -flamegraph, --testflames, --testliveflames, and other content filters)")
fs.StringVar(&cfg.OutputName, "name", cfg.OutputName, "Base name for .ior.zst trace output files")
fs.BoolVar(&cfg.TestFlames, "testflames", false, "Run TUI with static synthetic flamegraph data for keyboard-navigation testing")
fs.BoolVar(&cfg.TestLiveFlames, "testliveflames", false, "Run TUI with continuously-updating synthetic flamegraph data for live keyboard-navigation testing")
diff --git a/internal/ior_mode_registry.go b/internal/ior_mode_registry.go
index e262784..b0ef59f 100644
--- a/internal/ior_mode_registry.go
+++ b/internal/ior_mode_registry.go
@@ -214,7 +214,7 @@ func (h *headlessParquetModeHandler) validate(cfg flags.Config) error {
return errors.New("-parquet and -flamegraph are mutually exclusive")
}
if hasHeadlessParquetContentFilters(cfg) {
- return errors.New("-parquet cannot be combined with content filters (-comm, -path, -pid, -tid)")
+ return errors.New("-parquet cannot be combined with content filters (-comm, -path, -tid)")
}
return nil
}
diff --git a/internal/ior_mode_test.go b/internal/ior_mode_test.go
index 526b9af..8a152cc 100644
--- a/internal/ior_mode_test.go
+++ b/internal/ior_mode_test.go
@@ -446,11 +446,18 @@ func TestValidateRunConfigRejectsParquetWithContentFilters(t *testing.T) {
if err == nil {
t.Fatalf("expected error for -parquet with content filters")
}
- if err.Error() != "-parquet cannot be combined with content filters (-comm, -path, -pid, -tid)" {
+ if err.Error() != "-parquet cannot be combined with content filters (-comm, -path, -tid)" {
t.Fatalf("unexpected error: %v", err)
}
}
+func TestValidateRunConfigAllowsParquetWithPIDFilter(t *testing.T) {
+ cfg := flags.Config{ParquetPath: "trace.parquet", PidFilter: 42}
+ if err := validateRunConfig(cfg); err != nil {
+ t.Fatalf("expected -parquet with -pid to be accepted, got %v", err)
+ }
+}
+
func TestValidateRunConfigRejectsParquetWithGlobalFilter(t *testing.T) {
cfg := flags.Config{
ParquetPath: "trace.parquet",
@@ -462,7 +469,7 @@ func TestValidateRunConfigRejectsParquetWithGlobalFilter(t *testing.T) {
if err == nil {
t.Fatalf("expected error for -parquet with global filter")
}
- if err.Error() != "-parquet cannot be combined with content filters (-comm, -path, -pid, -tid)" {
+ if err.Error() != "-parquet cannot be combined with content filters (-comm, -path, -tid)" {
t.Fatalf("unexpected error: %v", err)
}
}
@@ -664,7 +671,7 @@ func TestTuiTraceStarterFromRunTraceRespectsCancel(t *testing.T) {
}
}
-func TestHeadlessParquetTraceConfigClearsContentFilters(t *testing.T) {
+func TestHeadlessParquetTraceConfigPreservesPIDAndClearsContentFilters(t *testing.T) {
cfg := flags.Config{
ParquetPath: "trace.parquet",
PidFilter: 1234,
@@ -677,8 +684,8 @@ func TestHeadlessParquetTraceConfigClearsContentFilters(t *testing.T) {
}
got := headlessParquetTraceConfig(cfg)
- if got.PidFilter != -1 || got.TidFilter != -1 {
- t.Fatalf("pid/tid filters = %d/%d, want -1/-1", got.PidFilter, got.TidFilter)
+ if got.PidFilter != 1234 || got.TidFilter != -1 {
+ t.Fatalf("pid/tid filters = %d/%d, want 1234/-1", got.PidFilter, got.TidFilter)
}
if got.CommFilter != "" || got.PathFilter != "" {
t.Fatalf("comm/path filters = %q/%q, want empty", got.CommFilter, got.PathFilter)
diff --git a/internal/ior_parquet_sink.go b/internal/ior_parquet_sink.go
index 6869e1e..f52dffa 100644
--- a/internal/ior_parquet_sink.go
+++ b/internal/ior_parquet_sink.go
@@ -67,24 +67,23 @@ func isHeadlessParquetMode(cfg flags.Config) bool {
}
// hasHeadlessParquetContentFilters reports whether cfg carries filters that are
-// incompatible with headless Parquet mode (all events must be recorded unfiltered).
+// incompatible with headless Parquet mode. PID filtering is still allowed so
+// focused headless recordings can avoid tracing unrelated system activity.
func hasHeadlessParquetContentFilters(cfg flags.Config) bool {
return cfg.CommFilter != "" ||
cfg.PathFilter != "" ||
- cfg.PidFilter > 0 ||
cfg.TidFilter > 0 ||
cfg.GlobalFilter.IsActive()
}
// headlessParquetTraceConfig strips TUI-only flags from cfg so that the
-// headless Parquet run records a clean, unfiltered event stream.
+// headless Parquet run records a clean event stream, optionally scoped by PID.
func headlessParquetTraceConfig(cfg flags.Config) flags.Config {
out := cfg
out.PlainMode = false
out.FlamegraphOutput = false
out.CommFilter = ""
out.PathFilter = ""
- out.PidFilter = -1
out.TidFilter = -1
out.GlobalFilter = globalfilter.Filter{}
return out