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  ```