1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
// Copyright 2020 New Relic Corporation. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package newrelic
import (
"os"
"time"
)
// Application represents your application. All methods on Application are nil
// safe. Therefore, a nil Application pointer can be safely used as a mock.
type Application struct {
Private interface{}
app *app
}
// StartTransaction begins a Transaction with the given name.
func (app *Application) StartTransaction(name string) *Transaction {
if nil == app {
return nil
}
return app.app.StartTransaction(name)
}
// RecordCustomEvent adds a custom event.
//
// eventType must consist of alphanumeric characters, underscores, and
// colons, and must contain fewer than 255 bytes.
//
// Each value in the params map must be a number, string, or boolean.
// Keys must be less than 255 bytes. The params map may not contain
// more than 64 attributes. For more information, and a set of
// restricted keywords, see:
// https://docs.newrelic.com/docs/insights/new-relic-insights/adding-querying-data/inserting-custom-events-new-relic-apm-agents
//
// An error is logged if eventType or params is invalid.
func (app *Application) RecordCustomEvent(eventType string, params map[string]interface{}) {
if nil == app {
return
}
if nil == app.app {
return
}
err := app.app.RecordCustomEvent(eventType, params)
if err != nil {
app.app.Error("unable to record custom event", map[string]interface{}{
"event-type": eventType,
"reason": err.Error(),
})
}
}
// RecordCustomMetric records a custom metric. The metric name you
// provide will be prefixed by "Custom/". Custom metrics are not
// currently supported in serverless mode.
//
// See
// https://docs.newrelic.com/docs/agents/manage-apm-agents/agent-data/collect-custom-metrics
// for more information on custom events.
func (app *Application) RecordCustomMetric(name string, value float64) {
if nil == app {
return
}
if nil == app.app {
return
}
err := app.app.RecordCustomMetric(name, value)
if err != nil {
app.app.Error("unable to record custom metric", map[string]interface{}{
"metric-name": name,
"reason": err.Error(),
})
}
}
// WaitForConnection blocks until the application is connected, is
// incapable of being connected, or the timeout has been reached. This
// method is useful for short-lived processes since the application will
// not gather data until it is connected. nil is returned if the
// application is connected successfully.
//
// If Infinite Tracing is enabled, WaitForConnection will block until a
// connection to the Trace Observer is made, a fatal error is reached, or the
// timeout is hit.
//
// Note that in most cases, it is not necesary nor recommended to call
// WaitForConnection() at all, particularly for any but the most trivial, short-lived
// processes. It is better to simply start the application and allow the
// instrumentation code to handle its connections on its own, which it will do
// as needed in the background (and will continue attempting to connect
// if it wasn't immediately successful, all while allowing your application
// to proceed with its primary function).
//
func (app *Application) WaitForConnection(timeout time.Duration) error {
if nil == app {
return nil
}
return app.app.WaitForConnection(timeout)
}
// Shutdown flushes data to New Relic's servers and stops all
// agent-related goroutines managing this application. After Shutdown
// is called, the Application is disabled and will never collect data
// again. This method blocks until all final data is sent to New Relic
// or the timeout has elapsed. Increase the timeout and check debug
// logs if you aren't seeing data.
//
// If Infinite Tracing is enabled, Shutdown will block until all queued span
// events have been sent to the Trace Observer or the timeout has been reached.
func (app *Application) Shutdown(timeout time.Duration) {
if nil == app {
return
}
app.app.Shutdown(timeout)
}
func newApplication(app *app) *Application {
return &Application{
app: app,
Private: app,
}
}
// NewApplication creates an Application and spawns goroutines to manage the
// aggregation and harvesting of data. On success, a non-nil Application and a
// nil error are returned. On failure, a nil Application and a non-nil error
// are returned. All methods on an Application are nil safe. Therefore, a nil
// Application pointer can be safely used. Applications do not share global
// state, therefore it is safe to create multiple applications.
//
// The ConfigOption arguments allow for configuration of the Application. They
// are applied in order from first to last, i.e. latter ConfigOptions may
// overwrite the Config fields already set.
func NewApplication(opts ...ConfigOption) (*Application, error) {
c := defaultConfig()
for _, fn := range opts {
if nil != fn {
fn(&c)
if nil != c.Error {
return nil, c.Error
}
}
}
cfg, err := newInternalConfig(c, os.Getenv, os.Environ())
if nil != err {
return nil, err
}
return newApplication(newApp(cfg)), nil
}
|