Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AI Event Types and Configuration Options (WIP) #861

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion v3/newrelic/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,32 @@ func (app *Application) RecordCustomEvent(eventType string, params map[string]in
}
}

// RecordLlmFeedbackEvent adds a LLM Feedback event.
// An error is logged if eventType or params is invalid.
func (app *Application) RecordLLMFeedbackEvent(trace_id string, rating any, category string, message string, metadata map[string]interface{}) {
if app == nil || app.app == nil {
return
}
CustomEventData := map[string]interface{}{
"trace_id": trace_id,
"rating": rating,
"category": category,
"message": message,
"ingest_source": "Go",
}
for k, v := range metadata {
CustomEventData[k] = v
}
// if rating is an int or string, record the event
err := app.app.RecordCustomEvent("LlmFeedbackMessage", CustomEventData)
if err != nil {
app.app.Error("unable to record custom event", map[string]interface{}{
"event-type": "LlmFeedbackMessage",
"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.
Expand Down Expand Up @@ -136,7 +162,6 @@ func (app *Application) Shutdown(timeout time.Duration) {
// a boolean true value is returned as the second return value. If it is
// false, then the Config data returned is the standard default configuration.
// This usually occurs if the Application is not yet fully initialized.
//
func (app *Application) Config() (Config, bool) {
if app == nil || app.app == nil {
return defaultConfig(), false
Expand Down
16 changes: 15 additions & 1 deletion v3/newrelic/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,18 @@ type Config struct {
DynoNamePrefixesToShorten []string
}

// AIMonitoring controls the behavior of AI monitoring features.
AIMonitoring struct {
Enabled bool
// Indicates whether streams will be instrumented
Streaming struct {
Enabled bool
}
RecordContent struct {
Enabled bool
}
}

// CrossApplicationTracer controls behavior relating to cross application
// tracing (CAT). In the case where CrossApplicationTracer and
// DistributedTracer are both enabled, DistributedTracer takes precedence.
Expand Down Expand Up @@ -666,7 +678,9 @@ func defaultConfig() Config {

c.Heroku.UseDynoNames = true
c.Heroku.DynoNamePrefixesToShorten = []string{"scheduler", "run"}

c.AIMonitoring.Enabled = false
c.AIMonitoring.Streaming.Enabled = true
c.AIMonitoring.RecordContent.Enabled = true
c.InfiniteTracing.TraceObserver.Port = 443
c.InfiniteTracing.SpanEvents.QueueSize = 10000

Expand Down
16 changes: 16 additions & 0 deletions v3/newrelic/config_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,22 @@ func ConfigAppLogDecoratingEnabled(enabled bool) ConfigOption {
}
}

func ConfigAIMonitoringEnabled(enabled bool) ConfigOption {
return func(cfg *Config) {
if enabled && !cfg.HighSecurity {
cfg.AIMonitoring.Enabled = true
} else {
cfg.AIMonitoring.Enabled = false
}
}
}

func ConfigAIMonitoringRecordContentEnabled(enabled bool) ConfigOption {
return func(cfg *Config) {
cfg.AIMonitoring.RecordContent.Enabled = enabled
}
}

// ConfigAppLogMetricsEnabled enables or disables the collection of metrics
// data for logs seen by an instrumented logging framework
// default: true
Expand Down
18 changes: 18 additions & 0 deletions v3/newrelic/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@ func TestCopyConfigReferenceFieldsPresent(t *testing.T) {
"agent_version":"0.2.2",
"host":"my-hostname",
"settings":{
"AIMonitoring": {
"Enabled": false,
"RecordContent": {
"Enabled": true
},
"Streaming": {
"Enabled": true
}
},
"AppName":"my appname",
"ApplicationLogging": {
"Enabled": true,
Expand Down Expand Up @@ -326,6 +335,15 @@ func TestCopyConfigReferenceFieldsAbsent(t *testing.T) {
"agent_version":"0.2.2",
"host":"my-hostname",
"settings":{
"AIMonitoring": {
"Enabled": false,
"RecordContent": {
"Enabled": true
},
"Streaming": {
"Enabled": true
}
},
"AppName":"my appname",
"ApplicationLogging": {
"Enabled": true,
Expand Down
20 changes: 20 additions & 0 deletions v3/newrelic/internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,26 @@ func testApp(replyfn func(*internal.ConnectReply), cfgfn func(*Config), t testin
}
}

func TestRecordLLMFeedbackEventSuccess(t *testing.T) {
app := testApp(nil, nil, t)
app.RecordLLMFeedbackEvent("traceid", "5", "informative", "message", validParams)
app.expectNoLoggedErrors(t)
app.ExpectCustomEvents(t, []internal.WantEvent{{
Intrinsics: map[string]interface{}{
"type": "LlmFeedbackMessage",
"timestamp": internal.MatchAnything,
},
UserAttributes: map[string]interface{}{
"trace_id": "traceid",
"rating": "5",
"category": "informative",
"message": "message",
"ingest_source": "Go",
"zip": 1,
"zap": 2,
},
}})
}
func TestRecordCustomEventSuccess(t *testing.T) {
app := testApp(nil, nil, t)
app.RecordCustomEvent("myType", validParams)
Expand Down
Loading