Skip to content

Commit 1c6381a

Browse files
authored
chore: set gorm user-agent header (#397)
* chore: set gorm user-agent header Set the user-agent header to go-gorm-spanner if it is Spanner gorm that is creating the connection. * chore: move check for connection from gorm to separate func
1 parent 4193437 commit 1c6381a

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

driver.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"log/slog"
2424
"math/big"
2525
"regexp"
26+
"runtime"
27+
"runtime/debug"
2628
"strconv"
2729
"strings"
2830
"sync"
@@ -43,6 +45,9 @@ import (
4345

4446
const userAgent = "go-sql-spanner/1.11.2" // x-release-please-version
4547

48+
const gormModule = "github.com/googleapis/go-gorm-spanner"
49+
const gormUserAgent = "go-gorm-spanner"
50+
4651
// LevelNotice is the default logging level that the Spanner database/sql driver
4752
// uses for informational logs. This level is deliberately chosen to be one level
4853
// lower than the default log level, which is slog.LevelInfo. This prevents the
@@ -467,7 +472,15 @@ func createConnector(d *Driver, connectorConfig ConnectorConfig) (*connector, er
467472
connectorConfig.AutoConfigEmulator = val
468473
}
469474
}
470-
config.UserAgent = userAgent
475+
476+
// Check if it is Spanner gorm that is creating the connection.
477+
// If so, we should set a different user-agent header than the
478+
// default go-sql-spanner header.
479+
if isConnectionFromGorm() {
480+
config.UserAgent = spannerGormHeader()
481+
} else {
482+
config.UserAgent = userAgent
483+
}
471484
var logger *slog.Logger
472485
if connectorConfig.logger == nil {
473486
d := slog.Default()
@@ -500,6 +513,34 @@ func createConnector(d *Driver, connectorConfig ConnectorConfig) (*connector, er
500513
return c, nil
501514
}
502515

516+
func isConnectionFromGorm() bool {
517+
callers := make([]uintptr, 20)
518+
length := runtime.Callers(0, callers)
519+
frames := runtime.CallersFrames(callers[0:length])
520+
gorm := false
521+
for frame, more := frames.Next(); more; {
522+
if strings.HasPrefix(frame.Function, gormModule) {
523+
gorm = true
524+
break
525+
}
526+
frame, more = frames.Next()
527+
}
528+
return gorm
529+
}
530+
531+
func spannerGormHeader() string {
532+
info, ok := debug.ReadBuildInfo()
533+
if !ok {
534+
return gormUserAgent
535+
}
536+
for _, module := range info.Deps {
537+
if module.Path == gormModule {
538+
return fmt.Sprintf("%s/%s", gormUserAgent, module.Version)
539+
}
540+
}
541+
return gormUserAgent
542+
}
543+
503544
func (c *connector) Connect(ctx context.Context) (driver.Conn, error) {
504545
c.closerMu.RLock()
505546
defer c.closerMu.RUnlock()

0 commit comments

Comments
 (0)