Skip to content

Commit 3238db3

Browse files
committed
feat: ⚡ new relic basic sample
new relic basic sample new relic basic sample
0 parents  commit 3238db3

File tree

12 files changed

+433
-0
lines changed

12 files changed

+433
-0
lines changed

.github/workflows/go.yml

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Go
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches:
9+
- master
10+
jobs:
11+
build_and_test:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Setup go-task
15+
uses: pnorton5432/setup-task@v1
16+
with:
17+
task-version: 3.29.1
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
- name: Setup Go
21+
uses: actions/setup-go@v5
22+
with:
23+
go-version: 'stable'
24+
check-latest: true
25+
- name: Task Build
26+
run: task build
27+
- name: Task Build for mage
28+
run: task build-gg
29+
- name: Test with gg build
30+
run: ./gg build

.gitignore

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Dependency directories (remove the comment below to include it)
18+
# vendor/
19+
20+
# Go workspace file
21+
go.work
22+
go.work.sum
23+
24+
# env file
25+
.env
26+
bin
27+
gg
28+
mage

README.md

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# golang-new-relic-instruction-sample
2+
3+
This repository is demo how to instruction golang application with new-relic agent
4+
5+
## steps
6+
7+
1. go to new relic website and register a license key
8+
```shell
9+
go get github.com/newrelic/go-agent/v3/newrelic
10+
```
11+
2. install new relic agent on golang
12+
13+
## sample code
14+
15+
```golang
16+
package main
17+
18+
import (
19+
"fmt"
20+
"os"
21+
"time"
22+
23+
"github.com/leetcode-golang-classroom/golang-new-relic-instruction-sample/internal/config"
24+
"github.com/newrelic/go-agent/v3/newrelic"
25+
)
26+
27+
var (
28+
// Making app and err a global variable
29+
nrApp *newrelic.Application
30+
nrErr error
31+
)
32+
33+
func main() {
34+
nrApp, nrErr = newrelic.NewApplication(
35+
36+
// Workshop > Set the values in the newrelic.Config struct from within a custom newrelic.ConfigOption
37+
// https://docs.newrelic.com/docs/apm/agents/go-agent/configuration/go-agent-configuration/
38+
39+
// Workshop > Name your application
40+
newrelic.ConfigAppName(config.AppConfig.AppName),
41+
// Workshop > Fill in your New Relic Ingest license key
42+
newrelic.ConfigLicense(config.AppConfig.NewRelicLicenseKey),
43+
// Workshop > Add debug logging for extra details
44+
newrelic.ConfigDebugLogger(os.Stdout),
45+
)
46+
47+
// If an application could not be created then err will reveal why.
48+
if nrErr != nil {
49+
fmt.Println("unable to start NR instrumentation - ", nrErr)
50+
}
51+
// Not necessary for monitoring a production application with a lot of data.
52+
nrApp.WaitForConnection(5 * time.Second)
53+
54+
// Run a simple function
55+
print()
56+
57+
// Wait for shut down to ensure data gets flushed
58+
nrApp.Shutdown(5 * time.Second)
59+
}
60+
61+
func print() {
62+
// Workshop > Monitor a Golang transaction
63+
// https://docs.newrelic.com/docs/apm/agents/go-agent/instrumentation/instrument-go-transactions/#go-txn
64+
// Put your code here
65+
txn := nrApp.StartTransaction("go-hello-app")
66+
defer txn.End()
67+
fmt.Println("Hello world! Welcome to your first instrumented Golang App!")
68+
}
69+
70+
```
71+
72+
透過 StartTransaction 來針對要執行的 print 作 profile
73+
74+
當使用 ./gg lauch 啟動之後
75+
76+
透過 new relic 後台的 APM 內部的 Transaction 的屬性
77+
可以看到如下圖:
78+
![new-relic-transaction-view](new-relic-transaction-view.png)
79+
80+
Transaction 的狀況
81+
82+
以及細節如下圖
83+
84+
![new-relic-transaction-detail](new-relic-transaction-detail.png)

Taskfile.yml

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
version: '3'
2+
3+
tasks:
4+
default:
5+
cmds:
6+
- echo "This is task cmd"
7+
silent: true
8+
9+
build:
10+
cmds:
11+
- CGO_ENABLED=0 GOOS=linux go build -o bin/main cmd/main.go
12+
silent: true
13+
run:
14+
cmds:
15+
- ./bin/main
16+
deps:
17+
- build
18+
silent: true
19+
20+
build-mage:
21+
cmds:
22+
- CGO_ENABLED=0 GOOS=linux go build -o ./mage mage-tools/mage.go
23+
silent: true
24+
25+
build-gg:
26+
cmds:
27+
- ./mage -d mage-tools -compile ../gg
28+
deps:
29+
- build-mage
30+
silent: true
31+
32+
coverage:
33+
cmds:
34+
- go test -v -cover ./...
35+
silent: true
36+
test:
37+
cmds:
38+
- go test -v ./...
39+
silent: true
40+

cmd/main.go

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"time"
7+
8+
"github.com/leetcode-golang-classroom/golang-new-relic-instruction-sample/internal/config"
9+
"github.com/newrelic/go-agent/v3/newrelic"
10+
)
11+
12+
var (
13+
// Making app and err a global variable
14+
nrApp *newrelic.Application
15+
nrErr error
16+
)
17+
18+
func main() {
19+
nrApp, nrErr = newrelic.NewApplication(
20+
21+
// Workshop > Set the values in the newrelic.Config struct from within a custom newrelic.ConfigOption
22+
// https://docs.newrelic.com/docs/apm/agents/go-agent/configuration/go-agent-configuration/
23+
24+
// Workshop > Name your application
25+
newrelic.ConfigAppName(config.AppConfig.AppName),
26+
// Workshop > Fill in your New Relic Ingest license key
27+
newrelic.ConfigLicense(config.AppConfig.NewRelicLicenseKey),
28+
// Workshop > Add debug logging for extra details
29+
newrelic.ConfigDebugLogger(os.Stdout),
30+
)
31+
32+
// If an application could not be created then err will reveal why.
33+
if nrErr != nil {
34+
fmt.Println("unable to start NR instrumentation - ", nrErr)
35+
}
36+
// Not necessary for monitoring a production application with a lot of data.
37+
nrApp.WaitForConnection(5 * time.Second)
38+
39+
// Run a simple function
40+
print()
41+
42+
// Wait for shut down to ensure data gets flushed
43+
nrApp.Shutdown(5 * time.Second)
44+
}
45+
46+
func print() {
47+
// Workshop > Monitor a Golang transaction
48+
// https://docs.newrelic.com/docs/apm/agents/go-agent/instrumentation/instrument-go-transactions/#go-txn
49+
// Put your code here
50+
txn := nrApp.StartTransaction("go-hello-app")
51+
defer txn.End()
52+
fmt.Println("Hello world! Welcome to your first instrumented Golang App!")
53+
}

go.mod

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
module github.com/leetcode-golang-classroom/golang-new-relic-instruction-sample
2+
3+
go 1.22.4
4+
5+
require github.com/magefile/mage v1.15.0
6+
7+
require (
8+
github.com/fsnotify/fsnotify v1.7.0 // indirect
9+
github.com/hashicorp/hcl v1.0.0 // indirect
10+
github.com/magiconair/properties v1.8.7 // indirect
11+
github.com/mitchellh/mapstructure v1.5.0 // indirect
12+
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
13+
github.com/sagikazarmark/locafero v0.4.0 // indirect
14+
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
15+
github.com/sourcegraph/conc v0.3.0 // indirect
16+
github.com/spf13/afero v1.11.0 // indirect
17+
github.com/spf13/cast v1.6.0 // indirect
18+
github.com/spf13/pflag v1.0.5 // indirect
19+
github.com/subosito/gotenv v1.6.0 // indirect
20+
go.uber.org/atomic v1.9.0 // indirect
21+
go.uber.org/multierr v1.9.0 // indirect
22+
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
23+
gopkg.in/ini.v1 v1.67.0 // indirect
24+
gopkg.in/yaml.v3 v3.0.1 // indirect
25+
)
26+
27+
require (
28+
github.com/newrelic/go-agent/v3 v3.35.1 // indirect
29+
github.com/spf13/viper v1.19.0
30+
golang.org/x/net v0.25.0 // indirect
31+
golang.org/x/sys v0.20.0 // indirect
32+
golang.org/x/text v0.15.0 // indirect
33+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
34+
google.golang.org/grpc v1.65.0 // indirect
35+
google.golang.org/protobuf v1.34.2 // indirect
36+
)

go.sum

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
4+
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
5+
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
6+
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
7+
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
8+
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
9+
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
10+
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
11+
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
12+
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
13+
github.com/newrelic/go-agent/v3 v3.35.1 h1:N43qBNDILmnwLDCSfnE1yy6adyoVEU95nAOtdUgG4vA=
14+
github.com/newrelic/go-agent/v3 v3.35.1/go.mod h1:GNTda53CohAhkgsc7/gqSsJhDZjj8vaky5u+vKz7wqM=
15+
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
16+
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
17+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
18+
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
19+
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
20+
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
21+
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
22+
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
23+
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
24+
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
25+
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
26+
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
27+
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
28+
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
29+
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
30+
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
31+
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
32+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
33+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
34+
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
35+
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
36+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
37+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
38+
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
39+
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
40+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
41+
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
42+
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
43+
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
44+
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
45+
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
46+
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
47+
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
48+
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
49+
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
50+
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
51+
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
52+
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
53+
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
54+
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
55+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
56+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
57+
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
58+
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
59+
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
60+
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
61+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
62+
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
63+
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
64+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
65+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
66+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

internal/config/config.go

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package config
2+
3+
import (
4+
"log"
5+
6+
"github.com/spf13/viper"
7+
)
8+
9+
type Config struct {
10+
NewRelicKey string `mapstructure:"NEW_RELIC_KEY"`
11+
NewRelicLicenseKey string `mapstructure:"NEW_RELIC_LICENSE_KEY"`
12+
AppName string `mapstructure:"APP_NAME"`
13+
}
14+
15+
var AppConfig *Config
16+
17+
func init() {
18+
v := viper.New()
19+
v.AddConfigPath(".")
20+
v.SetConfigName(".env")
21+
v.SetConfigType("env")
22+
v.AutomaticEnv()
23+
FailOnError(v.BindEnv("NEW_RELIC_KEY"), "failed to bind NEW_RELIC_KEY")
24+
FailOnError(v.BindEnv("NEW_RELIC_LICENSE_KEY"), "failed to bind NEW_RELIC_LICENSE_KEY")
25+
FailOnError(v.BindEnv("APP_NAME"), "failed to bind APP_NAME")
26+
err := v.ReadInConfig()
27+
if err != nil {
28+
log.Println("Load from environment variable")
29+
}
30+
err = v.Unmarshal(&AppConfig)
31+
if err != nil {
32+
FailOnError(err, "Failed to read enivronment")
33+
}
34+
}
35+
36+
func FailOnError(err error, msg string) {
37+
if err != nil {
38+
log.Fatalf("%s: %s", msg, err)
39+
}
40+
}

0 commit comments

Comments
 (0)