github.com/newrelic/go-agent@v3.26.0+incompatible/examples/custom-instrumentation/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 Distributed Tracing with custom 5 // instrumentation. 6 // 7 // This application simulates simple inter-process communication between a 8 // calling and a called process. 9 // 10 // Invoked without arguments, the application acts as a calling process; 11 // invoked with one argument representing a payload, it acts as a called 12 // process. The calling process creates a payload, starts a called process and 13 // passes on the payload. The calling process waits until the called process is 14 // done and then terminates. Thus to start both processes, only a single 15 // invocation of the application (without any arguments) is needed. 16 package main 17 18 import ( 19 "fmt" 20 "os" 21 "os/exec" 22 "time" 23 24 "github.com/newrelic/go-agent" 25 ) 26 27 func mustGetEnv(key string) string { 28 if val := os.Getenv(key); "" != val { 29 return val 30 } 31 panic(fmt.Sprintf("environment variable %s unset", key)) 32 } 33 34 func called(app newrelic.Application, payload string) { 35 txn := app.StartTransaction("called-txn", nil, nil) 36 defer txn.End() 37 38 // Accept the payload that was passed on the command line. 39 txn.AcceptDistributedTracePayload(newrelic.TransportOther, payload) 40 time.Sleep(1 * time.Second) 41 } 42 43 func calling(app newrelic.Application) { 44 txn := app.StartTransaction("calling-txn", nil, nil) 45 defer txn.End() 46 47 // Create a payload, start the called process and pass the payload. 48 payload := txn.CreateDistributedTracePayload() 49 cmd := exec.Command(os.Args[0], payload.Text()) 50 cmd.Start() 51 52 // Wait until the called process is done, then exit. 53 cmd.Wait() 54 time.Sleep(1 * time.Second) 55 } 56 57 func makeApplication(name string) (newrelic.Application, error) { 58 cfg := newrelic.NewConfig(name, mustGetEnv("NEW_RELIC_LICENSE_KEY")) 59 cfg.Logger = newrelic.NewDebugLogger(os.Stdout) 60 61 // Distributed Tracing and Cross Application Tracing cannot both be 62 // enabled at the same time. 63 cfg.DistributedTracer.Enabled = true 64 65 app, err := newrelic.NewApplication(cfg) 66 67 if nil != err { 68 return nil, err 69 } 70 71 // Wait for the application to connect. 72 if err = app.WaitForConnection(5 * time.Second); nil != err { 73 return nil, err 74 } 75 76 return app, nil 77 } 78 79 func main() { 80 // Calling processes have no command line arguments, called processes 81 // have one command line argument (the payload). 82 isCalled := (len(os.Args) > 1) 83 84 // Initialize the application name. 85 name := "Go Custom Instrumentation" 86 if isCalled { 87 name += " Called" 88 } else { 89 name += " Calling" 90 } 91 92 // Initialize the application. 93 app, err := makeApplication(name) 94 if nil != err { 95 fmt.Println(err) 96 os.Exit(1) 97 } 98 99 // Run calling/called routines. 100 if isCalled { 101 payload := os.Args[1] 102 called(app, payload) 103 } else { 104 calling(app) 105 } 106 107 // Shut down the application to flush data to New Relic. 108 app.Shutdown(10 * time.Second) 109 }