mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-21 22:51:09 +02:00
* initial implementation of unseal trace * close file if we fail to start the trace didn't bother to check the error from traceFile.Close() * use reloadable config instead of env var * license * remove leftover * allow setting custom dir and remove new package * bring back StartDebugTrace after talking to Kuba it sounds like it's a good idea to try to move stuff out of core, so even if there's no immediate need for a generic debug trace function it's still fair to add it * track postUnseal instead of unsealInternal also some usability improvements from manual testing * address PR comments * address security review there were concerns about using the /tmp directory because of permissions, or having a default dir at all, so now it's required to set a dir in order to generate the traces. * add unit tests to StartDebugTrace * move back to default dir * document new parameters * add tiny integration test * avoid column in trace filename sounds like it might be forbidden in Windows and possibly cause problems in some MacOS applications. * address PR feedback * add go doc to test CI was complaining about missing comments on the new test function. It feels a bit silly to require this of tests but whatever XD * fix tests
64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package trace
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime/trace"
|
|
"time"
|
|
)
|
|
|
|
func StartDebugTrace(dir string, filePrefix string) (file string, stop func() error, err error) {
|
|
dirMustExist := true
|
|
if dir == "" {
|
|
dirMustExist = false // if a dir is provided it must exist, otherwise we'll create a default one
|
|
dir = filepath.Join(os.TempDir(), "vault-traces")
|
|
}
|
|
|
|
d, err := os.Stat(dir)
|
|
if err != nil && !os.IsNotExist(err) {
|
|
return "", nil, fmt.Errorf("failed to stat trace directory %q: %s", dir, err)
|
|
}
|
|
|
|
if os.IsNotExist(err) && dirMustExist {
|
|
return "", nil, fmt.Errorf("trace directory %q does not exist", dir)
|
|
}
|
|
|
|
if !os.IsNotExist(err) && !d.IsDir() {
|
|
return "", nil, fmt.Errorf("trace directory %q is not a directory", dir)
|
|
}
|
|
|
|
if os.IsNotExist(err) {
|
|
if err := os.Mkdir(dir, 0o700); err != nil {
|
|
return "", nil, fmt.Errorf("failed to create trace directory %q: %s", dir, err)
|
|
}
|
|
}
|
|
|
|
// would prefer a more human readable time reference in the file name but the column
|
|
// character can cause problems in filenames
|
|
fileName := fmt.Sprintf("%s-%d.trace", filePrefix, time.Now().Unix())
|
|
traceFile, err := filepath.Abs(filepath.Join(dir, fileName))
|
|
if err != nil {
|
|
return "", nil, fmt.Errorf("failed to get absolute path for trace file: %s", err)
|
|
}
|
|
f, err := os.Create(traceFile)
|
|
if err != nil {
|
|
return "", nil, fmt.Errorf("failed to create trace file %q: %s", traceFile, err)
|
|
}
|
|
|
|
if err := trace.Start(f); err != nil {
|
|
f.Close()
|
|
return "", nil, fmt.Errorf("failed to start trace: %s", err)
|
|
}
|
|
|
|
stop = func() error {
|
|
trace.Stop()
|
|
return f.Close()
|
|
}
|
|
|
|
return f.Name(), stop, nil
|
|
}
|