github.com/newrelic/go-agent@v3.26.0+incompatible/_integrations/nrpq/example/sqlx/main.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 // An application that illustrates how to instrument jmoiron/sqlx with DatastoreSegments 5 // 6 // To run this example, be sure the environment varible NEW_RELIC_LICENSE_KEY 7 // is set to your license key. Postgres must be running on the default port 8 // 5432 and have a user "foo" and a database "bar". 9 // 10 // Adding instrumentation for the SQLx package is easy. It means you can 11 // make database calls without having to manually create DatastoreSegments. 12 // Setup can be done in two steps: 13 // 14 // Set up your driver 15 // 16 // If you are using one of our currently supported database drivers (see 17 // https://docs.newrelic.com/docs/agents/go-agent/get-started/go-agent-compatibility-requirements#frameworks), 18 // follow the instructions on installing the driver. 19 // 20 // As an example, for the `lib/pq` driver, you will use the newrelic 21 // integration's driver in place of the postgres driver. If your code is using 22 // sqlx.Open with `lib/pq` like this: 23 // 24 // import ( 25 // "github.com/jmoiron/sqlx" 26 // _ "github.com/lib/pq" 27 // ) 28 // 29 // func main() { 30 // db, err := sqlx.Open("postgres", "user=pqgotest dbname=pqgotest sslmode=verify-full") 31 // } 32 // 33 // Then change the side-effect import to the integration package, and open 34 // "nrpostgres" instead: 35 // 36 // import ( 37 // "github.com/jmoiron/sqlx" 38 // _ "github.com/newrelic/go-agent/_integrations/nrpq" 39 // ) 40 // 41 // func main() { 42 // db, err := sqlx.Open("nrpostgres", "user=pqgotest dbname=pqgotest sslmode=verify-full") 43 // } 44 // 45 // If you are not using one of the supported database drivers, use the 46 // `InstrumentSQLDriver` 47 // (https://godoc.org/github.com/newrelic/go-agent#InstrumentSQLDriver) API. 48 // See 49 // https://github.com/newrelic/go-agent/blob/master/_integrations/nrmysql/nrmysql.go 50 // for a full example. 51 // 52 // Add context to your database calls 53 // 54 // Next, you must provide a context containing a newrelic.Transaction to all 55 // methods on sqlx.DB, sqlx.NamedStmt, sqlx.Stmt, and sqlx.Tx that make a 56 // database call. For example, instead of the following: 57 // 58 // err := db.Get(&jason, "SELECT * FROM person WHERE first_name=$1", "Jason") 59 // 60 // Do this: 61 // 62 // ctx := newrelic.NewContext(context.Background(), txn) 63 // err := db.GetContext(ctx, &jason, "SELECT * FROM person WHERE first_name=$1", "Jason") 64 // 65 package main 66 67 import ( 68 "context" 69 "fmt" 70 "log" 71 "os" 72 "time" 73 74 "github.com/jmoiron/sqlx" 75 newrelic "github.com/newrelic/go-agent" 76 _ "github.com/newrelic/go-agent/_integrations/nrpq" 77 ) 78 79 var schema = ` 80 CREATE TABLE person ( 81 first_name text, 82 last_name text, 83 email text 84 )` 85 86 // Person is a person in the database 87 type Person struct { 88 FirstName string `db:"first_name"` 89 LastName string `db:"last_name"` 90 Email string 91 } 92 93 func mustGetEnv(key string) string { 94 if val := os.Getenv(key); "" != val { 95 return val 96 } 97 panic(fmt.Sprintf("environment variable %s unset", key)) 98 } 99 100 func createApp() newrelic.Application { 101 cfg := newrelic.NewConfig("SQLx", mustGetEnv("NEW_RELIC_LICENSE_KEY")) 102 cfg.Logger = newrelic.NewDebugLogger(os.Stdout) 103 app, err := newrelic.NewApplication(cfg) 104 if nil != err { 105 log.Fatalln(err) 106 } 107 if err := app.WaitForConnection(5 * time.Second); nil != err { 108 log.Fatalln(err) 109 } 110 return app 111 } 112 113 func main() { 114 // Create application 115 app := createApp() 116 defer app.Shutdown(10 * time.Second) 117 // Start a transaction 118 txn := app.StartTransaction("main", nil, nil) 119 defer txn.End() 120 // Add transaction to context 121 ctx := newrelic.NewContext(context.Background(), txn) 122 123 // Connect to database using the "nrpostgres" driver 124 db, err := sqlx.Connect("nrpostgres", "user=foo dbname=bar sslmode=disable") 125 if err != nil { 126 log.Fatalln(err) 127 } 128 129 // Create database table if it does not exist already 130 // When the context is passed, DatastoreSegments will be created 131 db.ExecContext(ctx, schema) 132 133 // Add people to the database 134 // When the context is passed, DatastoreSegments will be created 135 tx := db.MustBegin() 136 tx.MustExecContext(ctx, "INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "Jason", "Moiron", "jmoiron@jmoiron.net") 137 tx.MustExecContext(ctx, "INSERT INTO person (first_name, last_name, email) VALUES ($1, $2, $3)", "John", "Doe", "johndoeDNE@gmail.net") 138 tx.Commit() 139 140 // Read from the database 141 // When the context is passed, DatastoreSegments will be created 142 people := []Person{} 143 db.SelectContext(ctx, &people, "SELECT * FROM person ORDER BY first_name ASC") 144 jason := Person{} 145 db.GetContext(ctx, &jason, "SELECT * FROM person WHERE first_name=$1", "Jason") 146 }