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

Set custom log attributes using newrelic.yml or environment variables #2087

Merged
merged 5 commits into from
Jun 20, 2023
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
19 changes: 13 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## dev

Version <dev> of the agent adds log-level filtering, an API to add custom attributes to logs, and updated instrumentation for Action Cable. It also provides fixes for how `Fiber` args are treated, Code-Level Metrics, and `NewRelic::Agent::Logging::DecoratingFormatter#clear_tags!` being incorrectly private.
Version <dev> of the agent adds log-level filtering, adds custom attributes for log events, and updates instrumentation for Action Cable. It also provides fixes for how `Fiber` args are treated, Code-Level Metrics, and `NewRelic::Agent::Logging::DecoratingFormatter#clear_tags!` being incorrectly private.

- **Feature: Filter forwarded logs based on level**

Expand All @@ -14,15 +14,22 @@ Version <dev> of the agent adds log-level filtering, an API to add custom attrib

This setting uses [Ruby's Logger::Severity constants integer values](https://github.com/ruby/ruby/blob/master/lib/logger/severity.rb#L6-L17) to determine precedence.

- **Feature: Custom attributes for logs API**
- **Feature: Custom attributes for logs**

You can now add custom attributes to your log events using `NewRelic::Agent.add_custom_log_attributes`.
You can now add custom attributes to log events forwarded to New Relic! You can pass these attributes using an API and/or a configuration option.

For example: `NewRelic::Agent.add_custom_log_attributes(dyno: ENV['DYNO'], pod_name: ENV['POD_NAME'])`, will add the attributes `dyno` and `pod_name` to your log events. Attributes passed to this API will be added to all log events.
| Configuration name | Default | Behavior |
| --------------------------- | ------- | ------------------------------------------------------ |
| `application_logging.forwarding.custom_attributes` | `{}` | A hash with key/value pairs to add as custom attributes to all log events forwarded to New Relic. If sending using an environment variable, the value must be formatted like: "key1=value1,key2=value2" |


Call the API using `NewRelic::Agent.add_custom_log_attributes` and passing your attributes as a hash. For example, you could call: `NewRelic::Agent.add_custom_log_attributes(dyno: ENV['DYNO'], pod_name: ENV['POD_NAME'])`, to add the attributes `dyno` and `pod_name` to your log events.

Attributes passed to the API or the configuration will be added to all log events.

Thanks to [@rajpawar02](https://github.com/rajpawar02) for raising this issue and [@askreet](https://github.com/askreet) for helping us with the solution. [Issue#1141](https://github.com/newrelic/newrelic-ruby-agent/issues/1141), [PR#2084](https://github.com/newrelic/newrelic-ruby-agent/pull/2084)
Thanks to [@rajpawar02](https://github.com/rajpawar02) for raising this issue and [@askreet](https://github.com/askreet) for helping us with the solution. [Issue#1141](https://github.com/newrelic/newrelic-ruby-agent/issues/1141), [PR#2084](https://github.com/newrelic/newrelic-ruby-agent/pull/2084), [PR#2087](https://github.com/newrelic/newrelic-ruby-agent/pull/2087)

- **Feature: Instrument transmit_subscription_* Action Cable actions**
- **Feature: Instrument transmit_subscription-related Action Cable actions**
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The formatting for this one appeared strangely due to the * in the title.


This change subscribes the agent to the Active Support notifications for:
* `transmit_subscription_confirmation.action_cable`
Expand Down
24 changes: 24 additions & 0 deletions lib/new_relic/agent/configuration/default_source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,22 @@ def self.convert_to_list(value)
end
end

def self.convert_to_hash(value)
return value if value.is_a?(Hash)

if value.is_a?(String)
return value.split(',').each_with_object({}) do |item, hash|
key, value = item.split('=')
hash[key] = value
end
end

raise ArgumentError.new(
"Config value '#{value}' of " \
"class #{value.class} couldn't be turned into a Hash."
)
end

SEMICOLON = ';'.freeze
def self.convert_to_list_on_semicolon(value)
case value
Expand Down Expand Up @@ -771,6 +787,14 @@ def self.enforce_fallback(allowed_values: nil, fallback: nil)
* "unknown"
DESCRIPTION
},
:'application_logging.forwarding.custom_attributes' => {
:default => {},
:public => true,
:type => Hash,
:transform => DefaultSource.method(:convert_to_hash),
:allowed_from_server => false,
:description => 'A hash with key/value pairs to add as custom attributes to all log events forwarded to New Relic. If sending using an environment variable, the value must be formatted like: "key1=value1,key2=value2"'
},
:'application_logging.forwarding.max_samples_stored' => {
:default => 10000,
:public => true,
Expand Down
3 changes: 3 additions & 0 deletions lib/new_relic/agent/log_event_aggregator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class LogEventAggregator < EventAggregator
FORWARDING_ENABLED_KEY = :'application_logging.forwarding.enabled'
DECORATING_ENABLED_KEY = :'application_logging.local_decorating.enabled'
LOG_LEVEL_KEY = :'application_logging.forwarding.log_level'
CUSTOM_ATTRIBUTES_KEY = :'application_logging.forwarding.custom_attributes'

attr_reader :attributes

Expand Down Expand Up @@ -181,6 +182,8 @@ def register_for_done_configuring(events)
record_configuration_metric(METRICS_SUPPORTABILITY_FORMAT, METRICS_ENABLED_KEY)
record_configuration_metric(FORWARDING_SUPPORTABILITY_FORMAT, FORWARDING_ENABLED_KEY)
record_configuration_metric(DECORATING_SUPPORTABILITY_FORMAT, DECORATING_ENABLED_KEY)

add_custom_attributes(NewRelic::Agent.config[CUSTOM_ATTRIBUTES_KEY])
end
end

Expand Down
19 changes: 19 additions & 0 deletions test/new_relic/agent/configuration/default_source_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,25 @@ def test_instrumentation_logger_matches_application_logging_disabled
end
end

def test_convert_to_hash_returns_hash
result = {'key1' => 'value1', 'key2' => 'value2'}

assert_equal(DefaultSource.convert_to_hash(result), result)
end

def test_convert_to_hash_with_string
value = 'key1=value1,key2=value2'
result = {'key1' => 'value1', 'key2' => 'value2'}

assert_equal(DefaultSource.convert_to_hash(value), result)
end

def test_convert_to_hash_raises_error_with_wrong_data_type
value = [1, 2, 3]

assert_raises(ArgumentError) { DefaultSource.convert_to_hash(value) }
end

def get_config_value_class(value)
type = value.class

Expand Down
13 changes: 13 additions & 0 deletions test/new_relic/agent/log_event_attributes_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -211,5 +211,18 @@ def test_drops_attribute_pair_if_invalid_value_class
logger.verify
end
end

def test_log_attributes_from_config
key = 'configured'
value = 'value'

with_config(
:'application_logging.forwarding.custom_attributes' => {key => value}
) do
NewRelic::Agent.config.notify_server_source_added

assert_includes(common_attributes_from_melt, key)
end
end
end
end
Loading