Configure logging with slog
maingo-hdb supports the slog package for structured logging. This replaces standard logging output, including SQL and protocol traces.repository·main·Indexed 41 days ago
https://github.com/sap/go-hdbA pure Go, native driver for the SAP HANA database that implements the SAP HANA SQL Command Network Protocol. It is designed as a statically linked, cross-compilable binary with no dependency on cgo or official SAP HANA client libraries. It supports LZ4 compression via a plugin-based Compressor interface and includes the bulkbench tool for performance benchmarking.
go-hdb supports the slog package for structured logging. This replaces standard logging output, including SQL and protocol traces.In v1.17.0, the value provided by the driver for decimal and fixed columns changed from *big.Rat to a different internal representation.
Impact: If your application uses custom sql.Scanner implementations that perform type assertions to *big.Rat, your code will break.
Action Required: Adapt your custom scanners to use the database/sql decimal Decompose / Compose interfaces. Note that code scanning directly into driver.Decimal or driver.NullDecimal is not affected by this change.
The benchmark uses a column table with two columns:
id: integerfield: doubleSQL definition:
create column table <TableName> (id integer, field double)Tests insert data in chunks of batchSize for a total of batchCount chunks.
sql.DB connection pool configuration.go-hdb supports LZ4 compression for data exchanged with a HANA database to reduce network traffic. To maintain a pure Go, no-CGO, and zero-dependency architecture, the driver does not ship with a built-in compressor. Instead, it uses a plugin-based model where you provide your own implementation of the Compressor interface.
Compression is negotiated at connection time using two independent behaviors:
EnableWrite() method determines if the driver should attempt to send compressed packets. If EnableWrite() returns false, the driver will still decompress inbound traffic but will never compress outbound traffic.Compress output is discarded and the original bytes are sent.type Compressor interface {
EnableWrite() bool // send data compressed if the server supports it
Decompress(src, dst []byte) (int, error) // decompress src into dst, returning bytes written
CompressBound(n int) int // upper bound of compressed size for n input bytes
Compress(src, dst []byte) (int, error) // compress src into dst, returning bytes written
}To get a complete picture of performance, you must correlate go-hdb driver stats with Go's standard database/sql pool stats (db.Stats()).
sql.DBStats.WaitCount and WaitDuration are climbing, your MaxOpenConnections is likely too low for your application's parallelism.sql.DBStats.MaxIdleTimeClosed or MaxIdleClosed are climbing, the pool is discarding connections. This forces the driver to perform new authentications on the next request, increasing latency. This is controlled by MaxIdleConns and ConnMaxIdleTime settings.When diagnosing slow database calls in Go, do not treat "slow SQL" as a single unit. A single Prepare + Exec operation involves several distinct phases, each with different causes and fixes. Application-level tracing (like otelsql) typically measures the total wall-clock time of all phases combined (A through H). To localize the issue, you must use the driver's internal instrumentation to split these phases apart.
| Phase | Description | Potential Cause / Fix |
|---|---|---|
| (A) Pool Waiting | Waiting for a free connection from database/sql | Pool size or contention |
| (B) Ping Round-trip | Optional Ping when reusing an idle connection | SetPingInterval |
| (C) TCP Connect | Establishing a new physical connection | Network, DNS, or routing issues |
| (D) HANA Auth | The authentication handshake | AuthTime |
| (E) Auth Refresh | Execution of auth refresh callbacks | SetRefreshPassword, SetToken, or SetClientCert |
| (F) Prepare RTT | Round-trip to HANA for statement preparation | SQLTimes["prepare"] |
| (G) Exec/Query RTT | Round-trip + data fetching | SQLTimes["exec"|"query"|"fetch"] |
| (H) HANA Execution | Actual work performed by the HANA backend | HANA plan cache or expensive statements |
Key Insight: Establishing a new physical connection (Phases C–E) is expensive. High connection churn (frequent opening/closing of connections) is a common source of latency that is unrelated to the SQL statements themselves.
In addition to standard Go benchmark results (like ns/op), bulkbench reports four specific time-based metrics for inserting BatchCount x BatchSize records:
avgsec/op: Average time per operation.maxsec/op: Maximum time per operation.medsec/op: Median time per operation.minsec/op: Minimum time per operation.You can connect to a HANA database by creating a connector using driver.NewBasicAuthConnector and then opening a database handle with sql.OpenDB. This approach avoids the need for a DSN string and uses the driver's native connector interface.
package main
import (
"database/sql"
"fmt"
"github.com/SAP/go-hdb/driver"
)
func main() {
connector := driver.NewBasicAuthConnector("host:port", "user", "password")
db := sql.OpenDB(connector)
defer db.Close()
var name string
if err := db.QueryRow("select current_user from dummy").Scan(&name); err != nil {
panic(err)
}
fmt.Println(name)
}SQL tracing allows you to see individual statements and their execution durations.
Important Caveat: The tracer is attached to a connection when it is created. If you enable tracing at runtime via driver.SetSQLTrace(true), it will only affect new connections. Existing pooled connections will not be traced until they are recycled. To trace all traffic immediately, enable it at process startup using the flag -hdb.sqlTrace=true.
Log Format: The trace uses structured slog at INFO level with the message "SQL".
Example:
level=INFO msg=SQL exec="SELECT * FROM t WHERE id=?" ms=12 arg.1=42
Routing Logs: By default, traces use slog.Default(). You can route them to your application's logger using connector.SetLogger(myStructuredLogger).
// Enable/disable at runtime
driver.SetSQLTrace(true) // enable
driver.SetSQLTrace(false) // disable
driver.SQLTrace() // returns current bool state
// Or via CLI flag at startup
// -hdb.sqlTrace=trueWhen experiencing performance issues, follow this checklist to isolate whether the bottleneck is in the HANA backend, the network, or the driver/pool.
cmd/bulkbench to create a controlled reference measurement with a known network baseline and warmed pool.NativeDriver().Stats() or db.ExStats() to log AuthTime.Count, AuthTime.Sum, and SQLTimes[*].Count.AuthTime.Count climbs during steady traffic.sql.DBStats for WaitCount/WaitDuration (contention) and MaxIdleTimeClosed/MaxIdleClosed (idle eviction).go_hdb_* metrics and NewDBStatsCollector with Prometheus/OTel to correlate auth/churn spikes with application tracing.driver.SetSQLTrace(true) (affects new connections only) to see per-statement millisecond timing.MaxIdleConns, ConnMaxIdleTime, and MaxOpenConns match observed parallelism.SetPingInterval to weed out dead connections.SQLTimes["exec"] tail against HANA's measured execution time. A large gap indicates the delay is on the client, network, or pool side.To install the pure Go HANA database driver for use with the database/sql package, use the following command:
go get -u github.com/SAP/go-hdb/driver