git.colasdn.top/newrelic/go-agent@v3.26.0+incompatible/_integrations/nrmysql/nrmysql.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 // +build go1.10 5 6 // Package nrmysql instruments https://github.com/go-sql-driver/mysql. 7 // 8 // Use this package to instrument your MySQL calls without having to manually 9 // create DatastoreSegments. This is done in a two step process: 10 // 11 // 1. Use this package's driver in place of the mysql driver. 12 // 13 // If your code is using sql.Open like this: 14 // 15 // import ( 16 // _ "github.com/go-sql-driver/mysql" 17 // ) 18 // 19 // func main() { 20 // db, err := sql.Open("mysql", "user@unix(/path/to/socket)/dbname") 21 // } 22 // 23 // Then change the side-effect import to this package, and open "nrmysql" instead: 24 // 25 // import ( 26 // _ "github.com/newrelic/go-agent/_integrations/nrmysql" 27 // ) 28 // 29 // func main() { 30 // db, err := sql.Open("nrmysql", "user@unix(/path/to/socket)/dbname") 31 // } 32 // 33 // 2. Provide a context containing a newrelic.Transaction to all exec and query 34 // methods on sql.DB, sql.Conn, sql.Tx, and sql.Stmt. This requires using the 35 // context methods ExecContext, QueryContext, and QueryRowContext in place of 36 // Exec, Query, and QueryRow respectively. For example, instead of the 37 // following: 38 // 39 // row := db.QueryRow("SELECT count(*) from tables") 40 // 41 // Do this: 42 // 43 // ctx := newrelic.NewContext(context.Background(), txn) 44 // row := db.QueryRowContext(ctx, "SELECT count(*) from tables") 45 // 46 // A working example is shown here: 47 // https://github.com/newrelic/go-agent/tree/master/_integrations/nrmysql/example/main.go 48 package nrmysql 49 50 import ( 51 "database/sql" 52 "net" 53 54 "github.com/go-sql-driver/mysql" 55 newrelic "github.com/newrelic/go-agent" 56 "github.com/newrelic/go-agent/internal" 57 "github.com/newrelic/go-agent/internal/sqlparse" 58 ) 59 60 var ( 61 baseBuilder = newrelic.SQLDriverSegmentBuilder{ 62 BaseSegment: newrelic.DatastoreSegment{ 63 Product: newrelic.DatastoreMySQL, 64 }, 65 ParseQuery: sqlparse.ParseQuery, 66 ParseDSN: parseDSN, 67 } 68 ) 69 70 func init() { 71 sql.Register("nrmysql", newrelic.InstrumentSQLDriver(mysql.MySQLDriver{}, baseBuilder)) 72 internal.TrackUsage("integration", "driver", "mysql") 73 } 74 75 func parseDSN(s *newrelic.DatastoreSegment, dsn string) { 76 cfg, err := mysql.ParseDSN(dsn) 77 if nil != err { 78 return 79 } 80 parseConfig(s, cfg) 81 } 82 83 func parseConfig(s *newrelic.DatastoreSegment, cfg *mysql.Config) { 84 s.DatabaseName = cfg.DBName 85 86 var host, ppoid string 87 switch cfg.Net { 88 case "unix", "unixgram", "unixpacket": 89 host = "localhost" 90 ppoid = cfg.Addr 91 case "cloudsql": 92 host = cfg.Addr 93 default: 94 var err error 95 host, ppoid, err = net.SplitHostPort(cfg.Addr) 96 if nil != err { 97 host = cfg.Addr 98 } else if host == "" { 99 host = "localhost" 100 } 101 } 102 103 s.Host = host 104 s.PortPathOrID = ppoid 105 }