Open6
go-agent/v3/integrations/nrmysql のコードリーディングメモ
モチベーション
go-agentを使っているとSQLのCOMMITでDatastoreSegmentが生成されない。
どうにかできないかコードを読んでみた記録。
driverはこんな感じで初期化されているので
func InstrumentSQLDriver(d driver.Driver, bld SQLDriverSegmentBuilder) driver.Driver {
return optionalMethodsDriver(&wrapDriver{bld: bld, original: d})
}
実際はここに処理が移譲されている。
var (
baseBuilder = newrelic.SQLDriverSegmentBuilder{
BaseSegment: newrelic.DatastoreSegment{
Product: newrelic.DatastoreMySQL,
},
ParseQuery: sqlparse.ParseQuery,
ParseDSN: parseDSN,
}
)
あとは wrapDriver
がいろいろメソッドをラップしている。
このへんで BEGIN
されるが何もTxにNewrelicの情報を埋め込んでいない。
func (w *wrapConn) Begin() (driver.Tx, error) {
return w.original.Begin()
}
// BeginTx implements ConnBeginTx.
func (w *wrapConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
return w.original.(driver.ConnBeginTx).BeginTx(ctx, opts)
}
理想はこんな感じだけどunexportなので真似できない。
// QueryContext implements QueryerContext.
func (w *wrapConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
startTime := time.Now()
rows, err := w.original.(driver.QueryerContext).QueryContext(ctx, query, args)
if err != driver.ErrSkip {
seg := w.bld.useQuery(query).startSegmentAt(ctx, startTime)
seg.End()
}
return rows, err
}
txn
はcontextから取得できるので、contextと接続情報さえ手に入れば自前でDatastoreSegmentを作れる。
s := newrelic.DatastoreSegment{
// ...
}
s.StartTime = txn.StartSegmentNow()
// ... make the datastore call
s.End()
DatastoreSegment のメソッド