@@ -7,6 +7,7 @@ package testing
7
7
import (
8
8
"archive/zip"
9
9
"context"
10
+ "encoding/json"
10
11
"errors"
11
12
"fmt"
12
13
"io"
@@ -23,7 +24,6 @@ import (
23
24
"github.com/stretchr/testify/require"
24
25
25
26
"github.com/elastic/elastic-agent-libs/mapstr"
26
- "github.com/elastic/elastic-agent-libs/opt"
27
27
agentsystemprocess "github.com/elastic/elastic-agent-system-metrics/metric/system/process"
28
28
"github.com/elastic/elastic-agent/internal/pkg/agent/application/paths"
29
29
"github.com/elastic/elastic-agent/pkg/control/v2/client"
@@ -170,6 +170,38 @@ func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts ..
170
170
c := client .New (client .WithAddress (socketPath ))
171
171
f .setClient (c )
172
172
173
+ f .t .Cleanup (func () {
174
+ if f .t .Failed () {
175
+ procs := getProcesses (f .t , `.*` )
176
+ dir , err := findProjectRoot (f .caller )
177
+ if err != nil {
178
+ f .t .Logf ("failed to dump process; failed to find project root: %s" , err )
179
+ return
180
+ }
181
+
182
+ // Sub-test names are separated by "/" characters which are not valid filenames on Linux.
183
+ sanitizedTestName := strings .ReplaceAll (f .t .Name (), "/" , "-" )
184
+
185
+ filePath := filepath .Join (dir , "build" , "diagnostics" , fmt .Sprintf ("TEST-%s-%s-%s-ProcessDump.json" , sanitizedTestName , f .operatingSystem , f .architecture ))
186
+ f .t .Logf ("Dumping running processes in %s" , filePath )
187
+ file , err := os .OpenFile (filePath , os .O_CREATE | os .O_TRUNC | os .O_WRONLY , 0o644 )
188
+ if err != nil {
189
+ f .t .Logf ("failed to dump process; failed to create output file %s root: %s" , file .Name (), err )
190
+ return
191
+ }
192
+ defer func (file * os.File ) {
193
+ err := file .Close ()
194
+ if err != nil {
195
+ f .t .Logf ("error closing file %s: %s" , file .Name (), err )
196
+ }
197
+ }(file )
198
+ err = json .NewEncoder (file ).Encode (procs )
199
+ if err != nil {
200
+ f .t .Logf ("error serializing processes: %s" , err )
201
+ }
202
+ }
203
+ })
204
+
173
205
f .t .Cleanup (func () {
174
206
// check for running agents after uninstall had a chance to run
175
207
assert .Empty (f .t , getElasticAgentProcesses (f .t ), "there should be no running agent at the end of the test" )
@@ -235,19 +267,19 @@ func (f *Fixture) Install(ctx context.Context, installOpts *InstallOpts, opts ..
235
267
236
268
type runningProcess struct {
237
269
// Basic Process data
238
- Name string
239
- State agentsystemprocess.PidState
240
- Username string
241
- Pid opt. Int
242
- Ppid opt. Int
243
- Pgid opt. Int
270
+ Name string `json:"name,omitempty"`
271
+ State agentsystemprocess.PidState `json:"state,omitempty"`
272
+ Username string `json:"username,omitempty"`
273
+ Pid int `json:"pid"`
274
+ Ppid int `json:"ppid"`
275
+ Pgid int `json:"pgid"`
244
276
245
277
// Extended Process Data
246
- Args []string
247
- Cmdline string
248
- Cwd string
249
- Exe string
250
- Env mapstr.M
278
+ Args []string `json:"args,omitempty"`
279
+ Cmdline string `json:"cmdline,omitempty"`
280
+ Cwd string `json:"cwd,omitempty"`
281
+ Exe string `json:"exe,omitempty"`
282
+ Env mapstr.M `json:"env,omitempty"`
251
283
}
252
284
253
285
func (p runningProcess ) String () string {
@@ -260,14 +292,15 @@ func mapProcess(p agentsystemprocess.ProcState) runningProcess {
260
292
Name : p .Name ,
261
293
State : p .State ,
262
294
Username : p .Username ,
263
- Pid : p .Pid ,
264
- Ppid : p .Ppid ,
265
- Pgid : p .Pgid ,
266
- Cmdline : p .Cmdline ,
267
- Cwd : p .Cwd ,
268
- Exe : p .Exe ,
269
- Args : make ([]string , len (p .Args )),
270
- Env : make (mapstr.M ),
295
+ // map pid/gid to int and default to an obvious impossible pid if we don't have a value
296
+ Pid : p .Pid .ValueOr (- 1 ),
297
+ Ppid : p .Ppid .ValueOr (- 1 ),
298
+ Pgid : p .Pgid .ValueOr (- 1 ),
299
+ Cmdline : p .Cmdline ,
300
+ Cwd : p .Cwd ,
301
+ Exe : p .Exe ,
302
+ Args : make ([]string , len (p .Args )),
303
+ Env : make (mapstr.M ),
271
304
}
272
305
copy (mappedProcess .Args , p .Args )
273
306
for k , v := range p .Env {
@@ -277,8 +310,12 @@ func mapProcess(p agentsystemprocess.ProcState) runningProcess {
277
310
}
278
311
279
312
func getElasticAgentProcesses (t * gotesting.T ) []runningProcess {
313
+ return getProcesses (t , `.*elastic\-agent.*` )
314
+ }
315
+
316
+ func getProcesses (t * gotesting.T , regex string ) []runningProcess {
280
317
procStats := agentsystemprocess.Stats {
281
- Procs : []string {`.*elastic\-agent.*` },
318
+ Procs : []string {regex },
282
319
}
283
320
284
321
err := procStats .Init ()
0 commit comments