Skip to content
Merged
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
2 changes: 1 addition & 1 deletion v3/integrations/nrnats/test/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ replace github.com/newrelic/go-agent/v3/integrations/nrnats v1.0.0 => ../

require (
github.com/nats-io/nats-server v1.4.1
github.com/nats-io/nats.go v1.17.0
github.com/nats-io/nats.go v1.36.0
github.com/newrelic/go-agent/v3 v3.39.0
github.com/newrelic/go-agent/v3/integrations/nrnats v1.0.0
)
Expand Down
3 changes: 1 addition & 2 deletions v3/integrations/nrsnowflake/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/newrelic/go-agent/v3/integrations/nrsnowflake

go 1.22
go 1.22.0

toolchain go1.23.2

Expand All @@ -9,5 +9,4 @@ require (
github.com/snowflakedb/gosnowflake v1.14.0
)


replace github.com/newrelic/go-agent/v3 => ../..
7 changes: 6 additions & 1 deletion v3/integrations/nrstan/examples/go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
module github.com/newrelic/go-agent/v3/integrations/nrstan/examples

// This module exists to avoid a dependency on nrnrats.
go 1.22

require (
github.com/nats-io/stan.go v0.5.0
github.com/nats-io/stan.go v0.10.4
github.com/newrelic/go-agent/v3 v3.39.0
github.com/newrelic/go-agent/v3/integrations/nrnats v0.0.0
github.com/newrelic/go-agent/v3/integrations/nrstan v0.0.0
)

replace github.com/newrelic/go-agent/v3/integrations/nrstan => ../

replace github.com/newrelic/go-agent/v3/integrations/nrnats => ../../nrnats/

replace github.com/newrelic/go-agent/v3 => ../../..
3 changes: 3 additions & 0 deletions v3/newrelic/app_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ func (run *appRun) LoggingConfig() (config loggingConfig) {
config.includeLabels = run.Config.Labels
config.excludeLabels = &logging.Forwarding.Labels.Exclude
}
if run.Config.CustomInsightsEvents.CustomAttributesValues != nil && logging.Forwarding.Enabled && run.Config.CustomInsightsEvents.CustomAttributesEnabled {
config.customAttributes = run.Config.CustomInsightsEvents.CustomAttributesValues
}
return config
}

Expand Down
13 changes: 13 additions & 0 deletions v3/newrelic/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ type Config struct {
//
// https://docs.newrelic.com/docs/insights/new-relic-insights/adding-querying-data/inserting-custom-events-new-relic-apm-agents
CustomInsightsEvents struct {
// CustomAttributesEnabled Toggles whether we send our custom attributes with forwarded logs.
CustomAttributesEnabled bool
// CustomAttributes A hash with key/value pairs to add as custom attributes to all log events forwarded to New Relic.
// https://docs.newrelic.com/docs/TODO
CustomAttributesValues map[string]string
// Enabled controls whether RecordCustomEvent will collect
// custom analytics events. High security mode overrides this
// setting.
Expand Down Expand Up @@ -631,6 +636,8 @@ func defaultConfig() Config {

c.Enabled = true
c.Labels = make(map[string]string)
c.CustomInsightsEvents.CustomAttributesEnabled = false
c.CustomInsightsEvents.CustomAttributesValues = make(map[string]string)
c.CustomInsightsEvents.Enabled = true
c.CustomInsightsEvents.MaxSamplesStored = internal.MaxCustomEvents
c.TransactionEvents.Enabled = true
Expand Down Expand Up @@ -827,6 +834,12 @@ func copyConfigReferenceFields(cfg Config) Config {
cp.Labels[key] = val
}
}
if cfg.CustomInsightsEvents.CustomAttributesValues != nil {
cp.CustomInsightsEvents.CustomAttributesValues = make(map[string]string, len(cfg.CustomInsightsEvents.CustomAttributesValues))
for key, val := range cfg.CustomInsightsEvents.CustomAttributesValues {
cp.CustomInsightsEvents.CustomAttributesValues[key] = val
}
}
if cfg.ErrorCollector.IgnoreStatusCodes != nil {
ignored := make([]int, len(cfg.ErrorCollector.IgnoreStatusCodes))
copy(ignored, cfg.ErrorCollector.IgnoreStatusCodes)
Expand Down
108 changes: 70 additions & 38 deletions v3/newrelic/config_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,46 +389,67 @@ func ConfigLabels(labels map[string]string) ConfigOption {
}
}

// ConfigCustomInsightsCustomAttributesEnabled enables or disables sending our application
// custom attributes (which are configured via ConfigCustomInsightsCustomAttributesValues) with forwarded log events.
// Defaults: enabled=false
// This may also be set using the NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CUSTOM_ATTRIBUTES_ENABLED environment variable.
func ConfigCustomInsightsCustomAttributesEnabled(enabled bool) ConfigOption {
return func(cfg *Config) {
cfg.CustomInsightsEvents.CustomAttributesEnabled = enabled
}
}

// ConfigCustomInsightsCustomAttributesValues configures a set of custom attributes to add as attributes to all log events forwarded to New Relic.
// This may also be set using the NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CUSTOM_ATTRIBUTES environment variable.
func ConfigCustomInsightsCustomAttributesValues(customAttributes map[string]string) ConfigOption {
return func(cfg *Config) {
cfg.CustomInsightsEvents.CustomAttributesValues = make(map[string]string)
maps.Copy(cfg.CustomInsightsEvents.CustomAttributesValues, customAttributes)
}
}

// ConfigFromEnvironment populates the config based on environment variables:
//
// NEW_RELIC_APP_NAME sets AppName
// NEW_RELIC_ATTRIBUTES_EXCLUDE sets Attributes.Exclude using a comma-separated list, eg. "request.headers.host,request.method"
// NEW_RELIC_ATTRIBUTES_INCLUDE sets Attributes.Include using a comma-separated list
// NEW_RELIC_MODULE_DEPENDENCY_METRICS_ENABLED sets ModuleDependencyMetrics.Enabled
// NEW_RELIC_MODULE_DEPENDENCY_METRICS_IGNORED_PREFIXES sets ModuleDependencyMetrics.IgnoredPrefixes
// NEW_RELIC_MODULE_DEPENDENCY_METRICS_REDACT_IGNORED_PREFIXES sets ModuleDependencyMetrics.RedactIgnoredPrefixes to a boolean value
// NEW_RELIC_CODE_LEVEL_METRICS_ENABLED sets CodeLevelMetrics.Enabled
// NEW_RELIC_CODE_LEVEL_METRICS_SCOPE sets CodeLevelMetrics.Scope using a comma-separated list, e.g. "transaction"
// NEW_RELIC_CODE_LEVEL_METRICS_PATH_PREFIX sets CodeLevelMetrics.PathPrefixes using a comma-separated list
// NEW_RELIC_CODE_LEVEL_METRICS_REDACT_PATH_PREFIXES sets CodeLevelMetrics.RedactPathPrefixes to a boolean value
// NEW_RELIC_CODE_LEVEL_METRICS_REDACT_IGNORED_PREFIXES sets CodeLevelMetrics.RedactIgnoredPrefixes to a boolean value
// NEW_RELIC_CODE_LEVEL_METRICS_IGNORED_PREFIX sets CodeLevelMetrics.IgnoredPrefixes using a comma-separated list
// NEW_RELIC_DISTRIBUTED_TRACING_ENABLED sets DistributedTracer.Enabled using strconv.ParseBool
// NEW_RELIC_ENABLED sets Enabled using strconv.ParseBool
// NEW_RELIC_HIGH_SECURITY sets HighSecurity using strconv.ParseBool
// NEW_RELIC_HOST sets Host
// NEW_RELIC_INFINITE_TRACING_SPAN_EVENTS_QUEUE_SIZE sets InfiniteTracing.SpanEvents.QueueSize using strconv.Atoi
// NEW_RELIC_INFINITE_TRACING_TRACE_OBSERVER_PORT sets InfiniteTracing.TraceObserver.Port using strconv.Atoi
// NEW_RELIC_INFINITE_TRACING_TRACE_OBSERVER_HOST sets InfiniteTracing.TraceObserver.Host
// NEW_RELIC_LABELS sets Labels using a semi-colon delimited string of colon-separated pairs, eg. "Server:One;DataCenter:Primary"
// NEW_RELIC_LICENSE_KEY sets License
// NEW_RELIC_LOG sets Logger to log to either "stdout" or "stderr" (filenames are not supported)
// NEW_RELIC_LOG_LEVEL controls the NEW_RELIC_LOG level, must be "debug" for debug, or empty for info
// NEW_RELIC_PROCESS_HOST_DISPLAY_NAME sets HostDisplayName
// NEW_RELIC_SECURITY_POLICIES_TOKEN sets SecurityPoliciesToken
// NEW_RELIC_UTILIZATION_BILLING_HOSTNAME sets Utilization.BillingHostname
// NEW_RELIC_UTILIZATION_LOGICAL_PROCESSORS sets Utilization.LogicalProcessors using strconv.Atoi
// NEW_RELIC_UTILIZATION_TOTAL_RAM_MIB sets Utilization.TotalRAMMIB using strconv.Atoi
// NEW_RELIC_APPLICATION_LOGGING_ENABLED sets ApplicationLogging.Enabled. Set to false to disable all application logging features.
// NEW_RELIC_APPLICATION_LOGGING_FORWARDING_ENABLED sets ApplicationLogging.LogForwarding.Enabled. Set to false to disable in agent log forwarding.
// NEW_RELIC_APPLICATION_LOGGING_FORWARDING_LABELS_ENABLED sets ApplicationLogging.LogForwarding.Labels.Enabled to enable sending application labels with forwarded logs.
// NEW_RELIC_APPLICATION_LOGGING_FORWARDING_LABELS_EXCLUDE sets ApplicationLogging.LogForwarding.Labels.Exclude to filter out a set of unwanted label types from the ones reported with logs.
// NEW_RELIC_APPLICATION_LOGGING_METRICS_ENABLED sets ApplicationLogging.Metrics.Enabled. Set to false to disable the collection of application log metrics.
// NEW_RELIC_APPLICATION_LOGGING_LOCAL_DECORATING_ENABLED sets ApplicationLogging.LocalDecoration.Enabled. Set to true to enable local log decoration.
// NEW_RELIC_APPLICATION_LOGGING_FORWARDING_MAX_SAMPLES_STORED sets ApplicationLogging.LogForwarding.Limit. Set to 0 to prevent captured logs from being forwarded.
// NEW_RELIC_AI_MONITORING_ENABLED sets AIMonitoring.Enabled
// NEW_RELIC_AI_MONITORING_STREAMING_ENABLED sets AIMonitoring.Streaming.Enabled
// NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED sets AIMonitoring.RecordContent.Enabled
// NEW_RELIC_APP_NAME sets AppName
// NEW_RELIC_ATTRIBUTES_EXCLUDE sets Attributes.Exclude using a comma-separated list, eg. "request.headers.host,request.method"
// NEW_RELIC_ATTRIBUTES_INCLUDE sets Attributes.Include using a comma-separated list
// NEW_RELIC_MODULE_DEPENDENCY_METRICS_ENABLED sets ModuleDependencyMetrics.Enabled
// NEW_RELIC_MODULE_DEPENDENCY_METRICS_IGNORED_PREFIXES sets ModuleDependencyMetrics.IgnoredPrefixes
// NEW_RELIC_MODULE_DEPENDENCY_METRICS_REDACT_IGNORED_PREFIXES sets ModuleDependencyMetrics.RedactIgnoredPrefixes to a boolean value
// NEW_RELIC_CODE_LEVEL_METRICS_ENABLED sets CodeLevelMetrics.Enabled
// NEW_RELIC_CODE_LEVEL_METRICS_SCOPE sets CodeLevelMetrics.Scope using a comma-separated list, e.g. "transaction"
// NEW_RELIC_CODE_LEVEL_METRICS_PATH_PREFIX sets CodeLevelMetrics.PathPrefixes using a comma-separated list
// NEW_RELIC_CODE_LEVEL_METRICS_REDACT_PATH_PREFIXES sets CodeLevelMetrics.RedactPathPrefixes to a boolean value
// NEW_RELIC_CODE_LEVEL_METRICS_REDACT_IGNORED_PREFIXES sets CodeLevelMetrics.RedactIgnoredPrefixes to a boolean value
// NEW_RELIC_CODE_LEVEL_METRICS_IGNORED_PREFIX sets CodeLevelMetrics.IgnoredPrefixes using a comma-separated list
// NEW_RELIC_DISTRIBUTED_TRACING_ENABLED sets DistributedTracer.Enabled using strconv.ParseBool
// NEW_RELIC_ENABLED sets Enabled using strconv.ParseBool
// NEW_RELIC_HIGH_SECURITY sets HighSecurity using strconv.ParseBool
// NEW_RELIC_HOST sets Host
// NEW_RELIC_INFINITE_TRACING_SPAN_EVENTS_QUEUE_SIZE sets InfiniteTracing.SpanEvents.QueueSize using strconv.Atoi
// NEW_RELIC_INFINITE_TRACING_TRACE_OBSERVER_PORT sets InfiniteTracing.TraceObserver.Port using strconv.Atoi
// NEW_RELIC_INFINITE_TRACING_TRACE_OBSERVER_HOST sets InfiniteTracing.TraceObserver.Host
// NEW_RELIC_LABELS sets Labels using a semi-colon delimited string of colon-separated pairs, eg. "Server:One;DataCenter:Primary"
// NEW_RELIC_LICENSE_KEY sets License
// NEW_RELIC_LOG sets Logger to log to either "stdout" or "stderr" (filenames are not supported)
// NEW_RELIC_LOG_LEVEL controls the NEW_RELIC_LOG level, must be "debug" for debug, or empty for info
// NEW_RELIC_PROCESS_HOST_DISPLAY_NAME sets HostDisplayName
// NEW_RELIC_SECURITY_POLICIES_TOKEN sets SecurityPoliciesToken
// NEW_RELIC_UTILIZATION_BILLING_HOSTNAME sets Utilization.BillingHostname
// NEW_RELIC_UTILIZATION_LOGICAL_PROCESSORS sets Utilization.LogicalProcessors using strconv.Atoi
// NEW_RELIC_UTILIZATION_TOTAL_RAM_MIB sets Utilization.TotalRAMMIB using strconv.Atoi
// NEW_RELIC_APPLICATION_LOGGING_ENABLED sets ApplicationLogging.Enabled. Set to false to disable all application logging features.
// NEW_RELIC_APPLICATION_LOGGING_FORWARDING_ENABLED sets ApplicationLogging.LogForwarding.Enabled. Set to false to disable in agent log forwarding.
// NEW_RELIC_APPLICATION_LOGGING_FORWARDING_LABELS_ENABLED sets ApplicationLogging.LogForwarding.Labels.Enabled to enable sending application labels with forwarded logs.
// NEW_RELIC_APPLICATION_LOGGING_FORWARDING_LABELS_EXCLUDE sets ApplicationLogging.LogForwarding.Labels.Exclude to filter out a set of unwanted label types from the ones reported with logs.
// NEW_RELIC_APPLICATION_LOGGING_METRICS_ENABLED sets ApplicationLogging.Metrics.Enabled. Set to false to disable the collection of application log metrics.
// NEW_RELIC_APPLICATION_LOGGING_LOCAL_DECORATING_ENABLED sets ApplicationLogging.LocalDecoration.Enabled. Set to true to enable local log decoration.
// NEW_RELIC_APPLICATION_LOGGING_FORWARDING_MAX_SAMPLES_STORED sets ApplicationLogging.LogForwarding.Limit. Set to 0 to prevent captured logs from being forwarded.
// NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CUSTOM_ATTRIBUTES_ENABLED sets CustomInsightsEvents.CustomAttributesEnabled to enable sending application custom attributes with forwarded logs.
// NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CUSTOM_ATTRIBUTES sets CustomInsightsEvents.CustomAttributesValues A hash with key/value pairs to add as custom attributes to all log events forwarded to New Relic.
// NEW_RELIC_AI_MONITORING_ENABLED sets AIMonitoring.Enabled
// NEW_RELIC_AI_MONITORING_STREAMING_ENABLED sets AIMonitoring.Streaming.Enabled
// NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED sets AIMonitoring.RecordContent.Enabled
//
// This function is strict and will assign Config.Error if any of the
// environment variables cannot be parsed.
Expand Down Expand Up @@ -504,6 +525,7 @@ func configFromEnvironment(getenv func(string) string) ConfigOption {
assignBool(&cfg.AIMonitoring.Enabled, "NEW_RELIC_AI_MONITORING_ENABLED")
assignBool(&cfg.AIMonitoring.Streaming.Enabled, "NEW_RELIC_AI_MONITORING_STREAMING_ENABLED")
assignBool(&cfg.AIMonitoring.RecordContent.Enabled, "NEW_RELIC_AI_MONITORING_RECORD_CONTENT_ENABLED")
assignBool(&cfg.CustomInsightsEvents.CustomAttributesEnabled, "NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CUSTOM_ATTRIBUTES_ENABLED")

if env := getenv("NEW_RELIC_LABELS"); env != "" {
labels, err := getLabels(getenv("NEW_RELIC_LABELS"))
Expand All @@ -515,6 +537,16 @@ func configFromEnvironment(getenv func(string) string) ConfigOption {
}
}

if env := getenv("NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CUSTOM_ATTRIBUTES"); env != "" {
customAttributes, err := getLabels(getenv("NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CUSTOM_ATTRIBUTES"))
if err != nil {
cfg.Error = fmt.Errorf("invalid NEW_RELIC_APPLICATION_LOGGING_FORWARDING_CUSTOM_ATTRIBUTES value: %s: %v", env, err)
cfg.CustomInsightsEvents.CustomAttributesValues = nil
} else if len(customAttributes) > 0 {
cfg.CustomInsightsEvents.CustomAttributesValues = customAttributes
}
}

if env := getenv("NEW_RELIC_ATTRIBUTES_INCLUDE"); env != "" {
cfg.Attributes.Include = strings.Split(env, ",")
}
Expand Down
10 changes: 9 additions & 1 deletion v3/newrelic/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func TestCopyConfigReferenceFieldsPresent(t *testing.T) {
cfg.AppName = "my appname"
cfg.License = "0123456789012345678901234567890123456789"
cfg.Labels["zip"] = "zap"
cfg.CustomInsightsEvents.CustomAttributesValues["fiz"] = "baz"
cfg.ErrorCollector.IgnoreStatusCodes = append(cfg.ErrorCollector.IgnoreStatusCodes, 405)
cfg.ErrorCollector.ExpectStatusCodes = append(cfg.ErrorCollector.ExpectStatusCodes, 500)
cfg.Attributes.Include = append(cfg.Attributes.Include, "1")
Expand All @@ -107,6 +108,7 @@ func TestCopyConfigReferenceFieldsPresent(t *testing.T) {
cp := copyConfigReferenceFields(cfg)

cfg.Labels["zop"] = "zup"
cfg.Labels["foz"] = "buz"
cfg.ErrorCollector.IgnoreStatusCodes[0] = 201
cfg.Attributes.Include[0] = "zap"
cfg.Attributes.Exclude[0] = "zap"
Expand Down Expand Up @@ -168,6 +170,8 @@ func TestCopyConfigReferenceFieldsPresent(t *testing.T) {
"CodeLevelMetrics":{"Enabled":true,"IgnoredPrefix":"","IgnoredPrefixes":null,"PathPrefix":"","PathPrefixes":null,"RedactIgnoredPrefixes":true,"RedactPathPrefixes":true,"Scope":"all"},
"CrossApplicationTracer":{"Enabled":false},
"CustomInsightsEvents":{
"CustomAttributesEnabled":false,
"CustomAttributesValues":{"fiz":"baz"},
"Enabled":true,
"MaxSamplesStored":%d
},
Expand Down Expand Up @@ -329,6 +333,7 @@ func TestCopyConfigReferenceFieldsPresent(t *testing.T) {
func TestCopyConfigReferenceFieldsAbsent(t *testing.T) {
cfg := defaultConfig()
cfg.AppName = "my appname"
cfg.CustomInsightsEvents.CustomAttributesValues = nil
cfg.License = "0123456789012345678901234567890123456789"
cfg.Labels = nil
cfg.ErrorCollector.IgnoreStatusCodes = nil
Expand Down Expand Up @@ -384,6 +389,8 @@ func TestCopyConfigReferenceFieldsAbsent(t *testing.T) {
"CodeLevelMetrics":{"Enabled":true,"IgnoredPrefix":"","IgnoredPrefixes":null,"PathPrefix":"","PathPrefixes":null,"RedactIgnoredPrefixes":true,"RedactPathPrefixes":true,"Scope":"all"},
"CrossApplicationTracer":{"Enabled":false},
"CustomInsightsEvents":{
"CustomAttributesEnabled": false,
"CustomAttributesValues": null,
"Enabled":true,
"MaxSamplesStored":%d
},
Expand Down Expand Up @@ -507,7 +514,8 @@ func TestCopyConfigReferenceFieldsAbsent(t *testing.T) {
}
out := standardizeNumbers(string(js))
if out != expect {
t.Error(string(js))
t.Error(expect)
t.Error(out)
}
}

Expand Down
1 change: 1 addition & 0 deletions v3/newrelic/harvest.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ var (
internal.MaxLogEvents,
nil,
nil,
nil,
},
}
)
8 changes: 8 additions & 0 deletions v3/newrelic/log_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ func (events *logEvents) CollectorJSON(agentRunID string) ([]byte, error) {
}
}
}
if events.config.customAttributes != nil {
for k, v := range events.config.customAttributes {
buf.WriteByte(',')
jsonx.AppendString(buf, k)
buf.WriteByte(':')
jsonx.AppendString(buf, v)
}
}
buf.WriteByte('}')
buf.WriteByte('}')
buf.WriteByte(',')
Expand Down
15 changes: 8 additions & 7 deletions v3/newrelic/metric_names.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,14 @@ func supportMetric(metrics *metricTable, b bool, metricName string) {
// logging features for log data generation and supportability
// metrics generation.
type loggingConfig struct {
loggingEnabled bool // application logging features are enabled
collectEvents bool // collection of log event data is enabled
collectMetrics bool // collection of log metric data is enabled
localEnrichment bool // local log enrichment is enabled
maxLogEvents int // maximum number of log events allowed to be collected
includeLabels map[string]string // READ ONLY: if not nil, add these labels to log common data too
excludeLabels *[]string // READ ONLY: if not nil, exclude these label keys from the included labels
loggingEnabled bool // application logging features are enabled
collectEvents bool // collection of log event data is enabled
collectMetrics bool // collection of log metric data is enabled
localEnrichment bool // local log enrichment is enabled
maxLogEvents int // maximum number of log events allowed to be collected
includeLabels map[string]string // READ ONLY: if not nil, add these labels to log common data too
excludeLabels *[]string // READ ONLY: if not nil, exclude these label keys from the included labels
customAttributes map[string]string // READ ONLY: if not nil, add these custom attributes to log common data too
}

// Logging metrics that are generated at connect response
Expand Down
Loading