mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-15 07:57:07 +08:00
metrics: add build command duration metric
This adds a build duration metric for the build command with attributes related to the buildx driver, the error type (if any), and which options were used to perform the build from a subset of the options. This also refactors some of the utility methods used by the git tool to determine filepaths into its own separate package so they can be reused in another place. Also adds a test to ensure the resource is initialized correctly and doesn't error. The otel handler logging message is suppressed on buildx invocations so we never see the error if there's a problem with the schema url. It's so easy to mess up the schema url when upgrading OTEL that we need a proper test to make sure we haven't broken the functionality. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This commit is contained in:
@ -4,10 +4,8 @@ import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
_ "crypto/sha256" // ensure digests can be computed
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -26,9 +24,11 @@ import (
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/buildx/builder"
|
||||
"github.com/docker/buildx/driver"
|
||||
"github.com/docker/buildx/util/confutil"
|
||||
"github.com/docker/buildx/util/desktop"
|
||||
"github.com/docker/buildx/util/dockerutil"
|
||||
"github.com/docker/buildx/util/imagetools"
|
||||
"github.com/docker/buildx/util/osutil"
|
||||
"github.com/docker/buildx/util/progress"
|
||||
"github.com/docker/buildx/util/resolver"
|
||||
"github.com/docker/buildx/util/waitmap"
|
||||
@ -389,7 +389,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
|
||||
if p, err := filepath.Abs(sharedKey); err == nil {
|
||||
sharedKey = filepath.Base(p)
|
||||
}
|
||||
so.SharedKey = sharedKey + ":" + tryNodeIdentifier(configDir)
|
||||
so.SharedKey = sharedKey + ":" + confutil.TryNodeIdentifier(configDir)
|
||||
}
|
||||
|
||||
if opt.Pull {
|
||||
@ -1148,7 +1148,7 @@ func LoadInputs(ctx context.Context, d *driver.DriverHandle, inp Inputs, pw prog
|
||||
target.LocalDirs["context"] = inp.ContextPath
|
||||
}
|
||||
}
|
||||
case isLocalDir(inp.ContextPath):
|
||||
case osutil.IsLocalDir(inp.ContextPath):
|
||||
target.LocalDirs["context"] = inp.ContextPath
|
||||
switch inp.DockerfilePath {
|
||||
case "-":
|
||||
@ -1465,31 +1465,6 @@ func handleLowercaseDockerfile(dir, p string) string {
|
||||
return p
|
||||
}
|
||||
|
||||
var nodeIdentifierMu sync.Mutex
|
||||
|
||||
func tryNodeIdentifier(configDir string) (out string) {
|
||||
nodeIdentifierMu.Lock()
|
||||
defer nodeIdentifierMu.Unlock()
|
||||
sessionFile := filepath.Join(configDir, ".buildNodeID")
|
||||
if _, err := os.Lstat(sessionFile); err != nil {
|
||||
if os.IsNotExist(err) { // create a new file with stored randomness
|
||||
b := make([]byte, 8)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return out
|
||||
}
|
||||
if err := os.WriteFile(sessionFile, []byte(hex.EncodeToString(b)), 0600); err != nil {
|
||||
return out
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dt, err := os.ReadFile(sessionFile)
|
||||
if err == nil {
|
||||
return string(dt)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func noPrintFunc(opt map[string]Options) bool {
|
||||
for _, v := range opt {
|
||||
if v.PrintFunc != nil {
|
||||
|
19
build/git.go
19
build/git.go
@ -9,6 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/docker/buildx/util/gitutil"
|
||||
"github.com/docker/buildx/util/osutil"
|
||||
"github.com/moby/buildkit/client"
|
||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
@ -46,9 +47,9 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
|
||||
if filepath.IsAbs(contextPath) {
|
||||
wd = contextPath
|
||||
} else {
|
||||
wd, _ = filepath.Abs(filepath.Join(getWd(), contextPath))
|
||||
wd, _ = filepath.Abs(filepath.Join(osutil.GetWd(), contextPath))
|
||||
}
|
||||
wd = gitutil.SanitizePath(wd)
|
||||
wd = osutil.SanitizePath(wd)
|
||||
|
||||
gitc, err := gitutil.New(gitutil.WithContext(ctx), gitutil.WithWorkingDir(wd))
|
||||
if err != nil {
|
||||
@ -104,7 +105,7 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
|
||||
dockerfilePath = filepath.Join(wd, "Dockerfile")
|
||||
}
|
||||
if !filepath.IsAbs(dockerfilePath) {
|
||||
dockerfilePath = filepath.Join(getWd(), dockerfilePath)
|
||||
dockerfilePath = filepath.Join(osutil.GetWd(), dockerfilePath)
|
||||
}
|
||||
if r, err := filepath.Rel(root, dockerfilePath); err == nil && !strings.HasPrefix(r, "..") {
|
||||
res["label:"+DockerfileLabel] = r
|
||||
@ -124,21 +125,13 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if lp, err := getLongPathName(dir); err == nil {
|
||||
if lp, err := osutil.GetLongPathName(dir); err == nil {
|
||||
dir = lp
|
||||
}
|
||||
dir = gitutil.SanitizePath(dir)
|
||||
dir = osutil.SanitizePath(dir)
|
||||
if r, err := filepath.Rel(root, dir); err == nil && !strings.HasPrefix(r, "..") {
|
||||
so.FrontendAttrs["vcs:localdir:"+k] = r
|
||||
}
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getWd() string {
|
||||
wd, _ := os.Getwd()
|
||||
if lp, err := getLongPathName(wd); err == nil {
|
||||
return lp
|
||||
}
|
||||
return wd
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package build
|
||||
|
||||
// getLongPathName is a no-op on non-Windows platforms.
|
||||
func getLongPathName(path string) (string, error) {
|
||||
return path, nil
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package build
|
||||
|
||||
import "golang.org/x/sys/windows"
|
||||
|
||||
// getLongPathName converts Windows short pathnames to full pathnames.
|
||||
// For example C:\Users\ADMIN~1 --> C:\Users\Administrator.
|
||||
func getLongPathName(path string) (string, error) {
|
||||
// See https://groups.google.com/forum/#!topic/golang-dev/1tufzkruoTg
|
||||
p, err := windows.UTF16FromString(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b := p // GetLongPathName says we can reuse buffer
|
||||
n, err := windows.GetLongPathName(&p[0], &b[0], uint32(len(b)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if n > uint32(len(b)) {
|
||||
b = make([]uint16, n)
|
||||
_, err = windows.GetLongPathName(&p[0], &b[0], uint32(len(b)))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return windows.UTF16ToString(b), nil
|
||||
}
|
@ -5,7 +5,6 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/buildx/driver"
|
||||
@ -34,11 +33,6 @@ func IsRemoteURL(c string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func isLocalDir(c string) bool {
|
||||
st, err := os.Stat(c)
|
||||
return err == nil && st.IsDir()
|
||||
}
|
||||
|
||||
func isArchive(header []byte) bool {
|
||||
for _, m := range [][]byte{
|
||||
{0x42, 0x5A, 0x68}, // bzip2
|
||||
|
Reference in New Issue
Block a user