Your data. Anywhere you go.

New Relic for iOS or Android


Download on the App Store    Android App on Google play


New Relic Insights App for iOS


Download on the App Store


Learn more

Close icon

RecordCustomEvent in Go

go-agent

#1

I am FAR from a professional developer, but trying to write some code to record info from a 3rd party app, I am really struggling to get the RecordCustomEvent to work at all.

I am outputting information, with fmt.Println, right before I call this code… but nothing ever shows up in Insights.

Here’s the initialization

config := newrelic.NewConfig(newRelicAppName, newRelicLicenseKey)
newRelicLog, err := os.OpenFile("NRlog.log", os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
if nil == err {
	config.Logger = newrelic.NewDebugLogger(newRelicLog)
}
newRelicApp, err := newrelic.NewApplication(config)

Here is the RecordCustomEvent portion.

newRelicApp.RecordCustomEvent("ProductHealth", map[string]interface{}{
	"name.DbStatus": "ok",
	// "myFloat":  0.603,
	// "myInt":    123,
	// "myBool":   true,
})

Can anyone see what I am doing wrong? It’s also reporting to a sub-account being used for testing so when I search Select * From… The only thing that shows up is NrDailyUsage. Which is blank…


#2

I found a way to record the data, but there’s a bit of a hitch.
First: I had to loop the transaction from more than a minute before the data is reported. I am certain this is related to the NR harvest cycle time of 60 sec. However, we have gotten around this before with a graceful exist:
app.Shutdown(15 * time.Second)

Using txn.AddAttribute to add APM data which can also be queried using Insights.

Information can be found on New Relic’s Github Site

After reaching out to our account technical manager, I got these suggestions.

  • try waiting for the application to connect before sending the events, with something like app.WaitForConnection(10 * time.Second)
  • check the return value (err) from newRelicApp.RecordCustomEvent and see if it is nil or if it is an error, and if so what the error is
  • If neither of those is helpful, we’d suggest checking the DEBUG logging (it looks like they have already set it to DEBUG so hopefully that will have some useful output.)

#3

Alright, Alright, Alright! I finally got it working…

Background: I was searching for a way to monitor our on-prem Gitlab service and discovered there is a health status API that does the work. The decision was made to hit the API, parse the JSON response, and send the status messages to New Relic where we can create alerts if there is a status change.

You will need a Gitlab token for your service that is created in the admin UI.

logEnabled variable can be set to true to enable debug logging.

The code below comes with no guarantee, but I thought someone might find it helpful for their own use since I learn a lot from seeing how others do things.

Copy/Paste and update the variables that are wrapped in << >>.

package main

// For more detailed information check: https://docs.gitlab.com/ee/user/admin_area/monitoring/health_check.html
// **** Readiness Probe ****
// The readiness probe checks whether the GitLab instance is ready to use.
// It checks the dependent services (Database, Redis, Gitaly etc.) and gives a status for each.
// **** Liveness Probe ****
// The liveness probe checks whether the application server is alive.

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"time"

	"github.com/newrelic/go-agent"
)

var newRelicLicenseKey = "<<Your_Key_Here>>" Account License Key
var newRelicEventType = "GitlabHealth"
var gitlabToken = "<<Token_Here>>" // Access token has been deprecated in GitLab 9.4 in favor of IP whitelist. 
var newRelicTransactionName1 = "custom/health/readiness.go"
var newRelicTransactionName2 = "custom/health/liveness.go"
var newRelicApp newrelic.Application
var logEnabled = false

type reply struct {
	Db          dbcheck          `json:"db_check"`
	Redis       redischeck       `json:"redis_check"`
	Cache       cachecheck       `json:"cache_check"`
	Queues      queuescheck      `json:"queues_check"`
	Sharedstate sharedstatecheck `json:"shared_state_check"`
	Gitaly      gitalycheck      `json:"gitaly_check"`
}

type dbcheck struct {
	Status string `json:"status"`
}
type redischeck struct {
	Status string `json:"status"`
}
type cachecheck struct {
	Status string `json:"status"`
}
type queuescheck struct {
	Status string `json:"status"`
}
type sharedstatecheck struct {
	Status string `json:"status"`
}
type gitalycheck struct {
	Status string            `json:"status"`
	Labels map[string]string `json:"labels"`
}

func main() {
	var err error
	config := newrelic.NewConfig(newRelicEventType, newRelicLicenseKey)
if logEnabled == true {
	newRelicLog, err := os.OpenFile("NRlog.log", os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
	if nil == err {
		config.Logger = newrelic.NewDebugLogger(newRelicLog)
	}
}
	newRelicApp, err = newrelic.NewApplication(config)
	if nil != err {
		panic(err)
	}
	err = newRelicApp.WaitForConnection(10 * time.Second)
	if nil != err {
		panic(err)
	}

	sum := 0
	for i := 1; i < 20; i++ { //Change Increment from 20 to run more times
		sum += i
		fmt.Println(i)
		readiness()
		time.Sleep(15 * time.Second)
		liveness()
		time.Sleep(15 * time.Second)
	}
	newRelicApp.Shutdown(15 * time.Second) //Allows New Relic to send data & gracefully end.
}

func readiness() {
	url1 := "https://<<Insert_Git_Url>>/-/readiness?token=" + gitlabToken
	txn := newRelicApp.StartTransaction(newRelicTransactionName1, nil, nil) // Begin New Relic transaction capture
	req, _ := http.NewRequest("GET", url1, nil)
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	if res.StatusCode != http.StatusOK {
		fmt.Println("Failed with Status Code: ", res.StatusCode)
	}
	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)
	var response reply
	err = json.Unmarshal(body, &response)

	newRelicApp.RecordCustomEvent("GitlabReadiness", map[string]interface{}{
		"Gitlab.Readiness.ResponseCode":      res.StatusCode,
		"Gitlab.Readiness.DbStatus":          response.Db.Status,
		"Gitlab.Readiness.RedisStatus":       response.Redis.Status,
		"Gitlab.Readiness.CacheStatus":       response.Cache.Status,
		"Gitlab.Readiness.QueuesStatus":      response.Queues.Status,
		"Gitlab.Readiness.SharedstateStatus": response.Sharedstate.Status,
		"Gitlab.Readiness.GitalyStatus":      response.Gitaly.Status,
	})
	txn.End()
}

func liveness() {
	url2 := "https://<<Insert_Git_Url>>/-/liveness?token=" + gitlabToken
	txn := newRelicApp.StartTransaction(newRelicTransactionName2, nil, nil)
	req, _ := http.NewRequest("GET", url2, nil)

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	if res.StatusCode != http.StatusOK {
		fmt.Println("Failed with Status Code: ", res.StatusCode)
	}
	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)
	var response reply
	err = json.Unmarshal(body, &response)
	newRelicApp.RecordCustomEvent("GitlabLiveness", map[string]interface{}{
		"Gitlab.Liveness.ResponseCode":      res.StatusCode,
		"Gitlab.Liveness.DbStatus":          response.Db.Status,
		"Gitlab.Liveness.RedisStatus":       response.Redis.Status,
		"Gitlab.Liveness.CacheStatus":       response.Cache.Status,
		"Gitlab.Liveness.QueuesStatus":      response.Queues.Status,
		"Gitlab.Liveness.SharedstateStatus": response.Sharedstate.Status,
		"Gitlab.Liveness.GitalyStatus":      response.Gitaly.Status,
	})
	txn.End()
}

#4

Awesome! Thanks so much for sharing that solution! :smiley: