git » chasquid » commit a54d81f

monitoring: Get build information from Go's runtime

author Alberto Bertogli
2023-02-05 10:58:48 UTC
committer Alberto Bertogli
2023-02-05 11:01:36 UTC
parent ab63834cba3f769ae6bd96c5fb14f7008f296e9f

monitoring: Get build information from Go's runtime

Currently, chasquid gets version information from build-time flags that
have to be passed by the user.

This patch extends this logic so, if no flags are given, Go's build
information will be used to construct a synthetic version string.

chasquid.go +0 -32
monitoring.go +67 -0

diff --git a/chasquid.go b/chasquid.go
index fbf0274..628045b 100644
--- a/chasquid.go
+++ b/chasquid.go
@@ -6,7 +6,6 @@ package main
 
 import (
 	"context"
-	"expvar"
 	"flag"
 	"fmt"
 	"math/rand"
@@ -14,14 +13,12 @@ import (
 	"os"
 	"os/signal"
 	"path/filepath"
-	"strconv"
 	"syscall"
 	"time"
 
 	"blitiri.com.ar/go/chasquid/internal/config"
 	"blitiri.com.ar/go/chasquid/internal/courier"
 	"blitiri.com.ar/go/chasquid/internal/dovecot"
-	"blitiri.com.ar/go/chasquid/internal/expvarom"
 	"blitiri.com.ar/go/chasquid/internal/maillog"
 	"blitiri.com.ar/go/chasquid/internal/normalize"
 	"blitiri.com.ar/go/chasquid/internal/smtpsrv"
@@ -40,22 +37,6 @@ var (
 	showVer = flag.Bool("version", false, "show version and exit")
 )
 
-// Build information, overridden at build time using
-// -ldflags="-X main.version=blah".
-var (
-	version      = "undefined"
-	sourceDateTs = "0"
-)
-
-var (
-	versionVar = expvar.NewString("chasquid/version")
-
-	sourceDate      time.Time
-	sourceDateVar   = expvar.NewString("chasquid/sourceDateStr")
-	sourceDateTsVar = expvarom.NewInt("chasquid/sourceDateTimestamp",
-		"timestamp when the binary was built, in seconds since epoch")
-)
-
 func main() {
 	flag.Parse()
 	log.Init()
@@ -303,16 +284,3 @@ func mustReadDir(path string) []os.DirEntry {
 
 	return dirs
 }
-
-func parseVersionInfo() {
-	versionVar.Set(version)
-
-	sdts, err := strconv.ParseInt(sourceDateTs, 10, 0)
-	if err != nil {
-		panic(err)
-	}
-
-	sourceDate = time.Unix(sdts, 0)
-	sourceDateVar.Set(sourceDate.Format("2006-01-02 15:04:05 -0700"))
-	sourceDateTsVar.Set(sdts)
-}
diff --git a/monitoring.go b/monitoring.go
index dfe676f..29231ed 100644
--- a/monitoring.go
+++ b/monitoring.go
@@ -2,12 +2,15 @@ package main
 
 import (
 	"context"
+	"expvar"
 	"flag"
 	"fmt"
 	"html/template"
 	"net/http"
 	"os"
 	"runtime"
+	"runtime/debug"
+	"strconv"
 	"time"
 
 	"blitiri.com.ar/go/chasquid/internal/config"
@@ -20,6 +23,70 @@ import (
 	_ "net/http/pprof"
 )
 
+// Build information, overridden at build time using
+// -ldflags="-X main.version=blah".
+var (
+	version      = ""
+	sourceDateTs = ""
+)
+
+var (
+	versionVar = expvar.NewString("chasquid/version")
+
+	sourceDate      time.Time
+	sourceDateVar   = expvar.NewString("chasquid/sourceDateStr")
+	sourceDateTsVar = expvarom.NewInt("chasquid/sourceDateTimestamp",
+		"timestamp when the binary was built, in seconds since epoch")
+)
+
+func parseVersionInfo() {
+	bi, ok := debug.ReadBuildInfo()
+	if !ok {
+		panic("unable to read build info")
+	}
+
+	dirty := false
+	gitRev := ""
+	gitTime := ""
+	for _, s := range bi.Settings {
+		switch s.Key {
+		case "vcs.modified":
+			if s.Value == "true" {
+				dirty = true
+			}
+		case "vcs.time":
+			gitTime = s.Value
+		case "vcs.revision":
+			gitRev = s.Value
+		}
+	}
+
+	if sourceDateTs != "" {
+		sdts, err := strconv.ParseInt(sourceDateTs, 10, 0)
+		if err != nil {
+			panic(err)
+		}
+
+		sourceDate = time.Unix(sdts, 0)
+	} else {
+		sourceDate, _ = time.Parse(time.RFC3339, gitTime)
+	}
+	sourceDateVar.Set(sourceDate.Format("2006-01-02 15:04:05 -0700"))
+	sourceDateTsVar.Set(sourceDate.Unix())
+
+	if version == "" {
+		version = sourceDate.Format("20060102")
+
+		if gitRev != "" {
+			version += fmt.Sprintf("-%.9s", gitRev)
+		}
+		if dirty {
+			version += "-dirty"
+		}
+	}
+	versionVar.Set(version)
+}
+
 func launchMonitoringServer(conf *config.Config) {
 	log.Infof("Monitoring HTTP server listening on %s", conf.MonitoringAddress)