package sentry import ( "crypto/rand" "encoding/hex" "encoding/json" "fmt" "os" "runtime/debug" "strings" "time" exec "golang.org/x/sys/execabs" ) func uuid() string { id := make([]byte, 16) // Prefer rand.Read over rand.Reader, see https://go-review.googlesource.com/c/go/+/272326/. _, _ = rand.Read(id) id[6] &= 0x0F // clear version id[6] |= 0x40 // set version to 4 (random uuid) id[8] &= 0x3F // clear variant id[8] |= 0x80 // set to IETF variant return hex.EncodeToString(id) } func fileExists(fileName string) bool { _, err := os.Stat(fileName) return err == nil } // monotonicTimeSince replaces uses of time.Now() to take into account the // monotonic clock reading stored in start, such that duration = end - start is // unaffected by changes in the system wall clock. func monotonicTimeSince(start time.Time) (end time.Time) { return start.Add(time.Since(start)) } // nolint: deadcode, unused func prettyPrint(data interface{}) { dbg, _ := json.MarshalIndent(data, "", " ") fmt.Println(string(dbg)) } // defaultRelease attempts to guess a default release for the currently running // program. func defaultRelease() (release string) { // Return first non-empty environment variable known to hold release info, if any. envs := []string{ "SENTRY_RELEASE", "HEROKU_SLUG_COMMIT", "SOURCE_VERSION", "CODEBUILD_RESOLVED_SOURCE_VERSION", "CIRCLE_SHA1", "GAE_DEPLOYMENT_ID", "GITHUB_SHA", // GitHub Actions - https://help.github.com/en/actions "COMMIT_REF", // Netlify - https://docs.netlify.com/ "VERCEL_GIT_COMMIT_SHA", // Vercel - https://vercel.com/ "ZEIT_GITHUB_COMMIT_SHA", // Zeit (now known as Vercel) "ZEIT_GITLAB_COMMIT_SHA", "ZEIT_BITBUCKET_COMMIT_SHA", } for _, e := range envs { if release = os.Getenv(e); release != "" { Logger.Printf("Using release from environment variable %s: %s", e, release) return release } } if info, ok := debug.ReadBuildInfo(); ok { buildInfoVcsRevision := revisionFromBuildInfo(info) if len(buildInfoVcsRevision) > 0 { return buildInfoVcsRevision } } // Derive a version string from Git. Example outputs: // v1.0.1-0-g9de4 // v2.0-8-g77df-dirty // 4f72d7 if _, err := exec.LookPath("git"); err == nil { cmd := exec.Command("git", "describe", "--long", "--always", "--dirty") b, err := cmd.Output() if err != nil { // Either Git is not available or the current directory is not a // Git repository. var s strings.Builder fmt.Fprintf(&s, "Release detection failed: %v", err) if err, ok := err.(*exec.ExitError); ok && len(err.Stderr) > 0 { fmt.Fprintf(&s, ": %s", err.Stderr) } Logger.Print(s.String()) } else { release = strings.TrimSpace(string(b)) Logger.Printf("Using release from Git: %s", release) return release } } Logger.Print("Some Sentry features will not be available. See https://docs.sentry.io/product/releases/.") Logger.Print("To stop seeing this message, pass a Release to sentry.Init or set the SENTRY_RELEASE environment variable.") return "" } func revisionFromBuildInfo(info *debug.BuildInfo) string { for _, setting := range info.Settings { if setting.Key == "vcs.revision" && setting.Value != "" { Logger.Printf("Using release from debug info: %s", setting.Value) return setting.Value } } return "" } func Pointer[T any](v T) *T { return &v }