github.com/pinpoint-apm/pinpoint-go-agent@v1.4.1-0.20240110120318-a50c2eb18c8c/doc/quick_start.md (about) 1 # Quick Start 2 3 ## Install 4 ### Go get 5 ``` 6 go get github.com/pinpoint-apm/pinpoint-go-agent 7 ``` 8 9 ### import 10 ``` go 11 import "github.com/pinpoint-apm/pinpoint-go-agent" 12 ``` 13 14 ## Create an Agent 15 Go programs cannot be automatically instrumented because they are compiled into native machine code. 16 Therefore, developers must add the codes for instrumenting to the Go program they want to track. 17 18 First, you can create a pinpoint agent from the main function or http request handler. 19 After you set the application name, agent id, pinpoint collector's host address, and so on for ConfigOptions, 20 you can call the NewAgent() function to create an agent. 21 For more information on config option, refer the [Configuration](config.md) document. 22 23 ``` go 24 func main() { 25 opts := []pinpoint.ConfigOption{ 26 pinpoint.WithAppName("Your Application Name"), 27 pinpoint.WithAgentId("Agent Id"), 28 pinpoint.WithCollectorHost("pinpoint's collector host"), 29 } 30 cfg, _ := pinpoint.NewConfig(opts...) 31 agent, err := pinpoint.NewAgent(cfg) 32 if err != nil { 33 log.Fatalf("pinpoint agent start fail: %v", err) 34 } 35 36 ... 37 ``` 38 39 ## Instrument HTTP Request 40 41 As mentioned earlier, the Go application must be manually instrumented at the source code level. 42 Pinpoint Go Agent provides plugins packages to help developers trace the popular frameworks and toolkits. 43 These packages help you to make instruments with simple source code modifications. 44 For more information on plugins packages, refer the [Plugin User Guide](plugin_guide.md). 45 46 ### Inbound Http Request 47 48 The pinpoint http plugin lets you trace Go's built-in http packages. 49 For example, if you want to trace the handler of the http server below, 50 51 ``` go 52 http.HandleFunc("/", index) 53 ``` 54 you can write code for the instruments as shown below. 55 ``` go 56 http.HandleFunc("/", pphttp.WrapHandlerFunc(index)) 57 ``` 58 59 The complete example code for tracing the http server's handler is as follows: 60 ``` go 61 package main 62 63 import ( 64 "github.com/pinpoint-apm/pinpoint-go-agent" 65 "github.com/pinpoint-apm/pinpoint-go-agent/plugin/http" 66 ) 67 68 func index(w http.ResponseWriter, r *http.Request) { 69 io.WriteString(w, "hello world") 70 } 71 72 func main() { 73 opts := []pinpoint.ConfigOption{ 74 pinpoint.WithAppName("TraceWebRequest"), 75 pinpoint.WithAgentId("TraceWebRequestAgent"), 76 pinpoint.WithCollectorHost("localhost"), 77 } 78 cfg, _ := pinpoint.NewConfig(opts...) 79 agent, err := pinpoint.NewAgent(cfg) 80 if err != nil { 81 log.Fatalf("pinpoint agent start fail: %v", err) 82 } 83 defer agent.Shutdown() 84 85 http.HandleFunc("/", pphttp.WrapHandlerFunc(index)) 86 ... 87 } 88 ``` 89 90 ### Outgoing Http Request 91 If you are tracking outgoing HTTP requests, you must instrument the HTTP client. 92 The WrapClient() function in the pinpoint http plugin allows you to trace http client calls. 93 94 ``` go 95 func outgoing(w http.ResponseWriter, r *http.Request) { 96 client := phttp.WrapClient(nil) 97 98 request, _ := http.NewRequest("GET", "http://localhost:9000/hello", nil) 99 request = request.WithContext(r.Context()) 100 101 resp, err := client.Do(request) 102 if nil != err { 103 io.WriteString(w, err.Error()) 104 return 105 } 106 defer resp.Body.Close() 107 io.Copy(w, resp.Body) 108 } 109 110 func main() { 111 ... //setup agent 112 113 http.HandleFunc("/outgoing", pphttp.WrapHandlerFunc(outgoing)) 114 } 115 ``` 116 117 ## Instrument Web Framework 118 Pinpoint Go Agent provides a plugin to track the Gin, Echo, Chi and Gorilla Web framework. 119 Below is an example of tracking the handler of the Gin framework. 120 You can simply register Gin plugin with the middleware of the Gin or wrap the Gin handler like http plugin. 121 122 ``` go 123 router.Use(pgin.Middleware()) 124 ``` 125 ``` go 126 package main 127 128 import ( 129 "github.com/gin-gonic/gin" 130 "github.com/pinpoint-apm/pinpoint-go-agent" 131 "github.com/pinpoint-apm/pinpoint-go-agent/plugin/gin" 132 ) 133 134 func hello(c *gin.Context) { 135 c.Writer.WriteString("hello") 136 } 137 138 func main() { 139 ... //set up agent 140 141 router := gin.Default() 142 router.Use(ppgin.Middleware()) 143 144 router.GET("/hello", hello) 145 router.Run(":8000") 146 } 147 ``` 148 149 ## Instrument Database Query 150 Pinpoint mysql plugin is a 'database/sql' driver that instruments the go-sql-driver/mysql. 151 When invoking the sql.Open() function, instead of the go-sql-driver/mysql driver, 152 ``` go 153 import "database/sql" 154 import _ "github.com/go-sql-driver/mysql" 155 156 db, err := sql.Open("mysql", "user:password@/dbname") 157 ``` 158 you can use the pinpoint mysql plugin. 159 ``` go 160 import _ "github.com/pinpoint-apm/pinpoint-go-agent/plugin/mysql" 161 162 db, err := sql.Open("mysql-pinpoint", "root:p123@tcp(127.0.0.1:3306)/information_schema") 163 ``` 164 165 Below is a complete example of tracking MySQL calls. 166 ``` go 167 package main 168 169 import ( 170 "database/sql" 171 172 _ "github.com/pinpoint-apm/pinpoint-go-agent/plugin/mysql" 173 github.com/pinpoint-apm/pinpoint-go-agent" 174 ) 175 176 func query(w http.ResponseWriter, r *http.Request) { 177 tracer := pinpoint.FromContext(r.Context()) 178 179 db, err := sql.Open("mysql-pinpoint", "root:p123@tcp(127.0.0.1:3306)/information_schema") 180 if nil != err { 181 panic(err) 182 } 183 184 ctx := pinpoint.NewContext(context.Background(), tracer) 185 row := db.QueryRowContext(ctx, "SELECT count(*) from tables") 186 var count int 187 row.Scan(&count) 188 189 fmt.Println("number of tables in information_schema", count) 190 } 191 192 ``` 193 194 ## Context propagation 195 In the example of trace database query above, looking at the query() function, 196 there is a code that invokes the pinpoint.FromContext() function to acquire the tracer. 197 198 ``` go 199 tracer := pinpoint.FromContext(r.Context()) 200 ``` 201 202 And, the query() function calls the pinpoint.NewContext() function to add the tracer to the go context. 203 204 ``` go 205 ctx := pinpoint.NewContext(context.Background(), tracer) 206 row := db.QueryRowContext(ctx, "SELECT count(*) from tables") 207 ``` 208 209 The tracer is the object that implements the Tracer interface of the Pinpoint Go Agent, 210 which generates and stores instrumentation information. When calling the go function, 211 we use the context of the go language to propagate this tracer. 212 Pinpoint Go Agent provides a function that adds a tracer to the context, 213 and a function that imports a tracer from the context, respectively. 214 215 ``` go 216 NewContext(ctx context.Context, tracer Tracer) context.Context 217 FromContext(ctx context.Context) Tracer 218 ```