Skip to content

Commit

Permalink
Merge pull request #2229 from newrelic/πŸ“¦πŸ‹
Browse files Browse the repository at this point in the history
  • Loading branch information
fallwith authored Sep 21, 2023
2 parents 2a86256 + fcb55e0 commit c714f98
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 0 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# New Relic Ruby Agent Release Notes

## dev

Version <dev> brings support for gleaning a Docker container id from cgroups v2 based containers.

- **Feature: Enhance Docker container id reporting**

Previously, the agent was only capable of determining a host Docker container's ID if the container was based on cgroups v1. Now, containers based on cgroups v2 will also have their container IDs reported to New Relic. [PR#2229](https://github.com/newrelic/newrelic-ruby-agent/issues/2229).

## v9.5.0

Version 9.5.0 introduces Stripe instrumentation, allows the agent to record additional response information on a transaction when middleware instrumentation is disabled, introduces new `:'sidekiq.args.include'` and `:'sidekiq.args.exclude:` configuration options to permit capturing only certain Sidekiq job arguments, updates Elasticsearch datastore instance metrics, and fixes a bug in `NewRelic::Rack::AgentHooks.needed?`.
Expand Down
24 changes: 24 additions & 0 deletions lib/new_relic/agent/system_info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,39 @@ def self.os_version
proc_try_read('/proc/version')
end

# When operating within a Docker container, attempt to obtain the
# container id.
#
# First look for `/proc/self/mountinfo` to exist on disk to signify
# cgroups v2. If that file exists, read it and expect it to contain one
# or more "/docker/containers/<container_id>/" lines from which the
# container id can be gleaned.
#
# Next look for `/proc/self/cgroup` to exist on disk to signify cgroup v1.
# If that file exists, read it and parse the "cpu" group info in the hope
# of finding a 64 character container id value.
#
# For non-cgroups based containers, use a `nil` value for the container
# id without generating any warnings or errors.
def self.docker_container_id
return unless ruby_os_identifier.include?('linux')

cgroupsv2_based_id = docker_container_id_for_cgroupsv2
return cgroupsv2_based_id if cgroupsv2_based_id

cgroup_info = proc_try_read('/proc/self/cgroup')
return unless cgroup_info

parse_docker_container_id(cgroup_info)
end

def self.docker_container_id_for_cgroupsv2
mountinfo = proc_try_read('/proc/self/mountinfo')
return unless mountinfo

Regexp.last_match(1) if mountinfo =~ %r{/docker/containers/([^/]+)/}
end

def self.parse_docker_container_id(cgroup_info)
cpu_cgroup = parse_cgroup_ids(cgroup_info)['cpu']
return unless cpu_cgroup
Expand Down
17 changes: 17 additions & 0 deletions test/new_relic/agent/system_info_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def setup
end
end

# BEGIN cgroups v1
container_id_test_dir = File.join(cross_agent_tests_dir, 'docker_container_id')
container_id_test_cases = load_cross_agent_test(File.join('docker_container_id', 'cases'))

Expand All @@ -86,6 +87,21 @@ def setup
end
end
end
# END cgroups v1

# BEGIN cgroups v2
def test_docker_container_id_is_gleaned_from_mountinfo_for_cgroups_v2
skip_unless_minitest5_or_above

container_id = "And Autumn leaves lie thick and still o'er land that is lost now"
mountinfo = "line1\nline2\n/docker/containers/#{container_id}/other/content\nline4\nline5"
NewRelic::Agent::SystemInfo.stub :ruby_os_identifier, 'linux' do
NewRelic::Agent::SystemInfo.stub :proc_try_read, mountinfo, %w[/proc/self/mountinfo] do
assert_equal container_id, NewRelic::Agent::SystemInfo.docker_container_id
end
end
end
# END cgroups v2

each_cross_agent_test :dir => 'proc_meminfo', :pattern => '*.txt' do |file|
if File.basename(file) =~ /^meminfo_(\d+)MB.txt$/
Expand Down Expand Up @@ -297,6 +313,7 @@ def test_system_info_bsd_predicate
def test_supportability_metric_recorded_when_docker_id_unavailable
NewRelic::Agent::SystemInfo.stubs(:ruby_os_identifier).returns('linux')
cgroup_info = File.read(File.join(cross_agent_tests_dir, 'docker_container_id', 'invalid-length.txt'))
NewRelic::Agent::SystemInfo.expects(:proc_try_read).with('/proc/self/mountinfo').returns(cgroup_info)
NewRelic::Agent::SystemInfo.expects(:proc_try_read).with('/proc/self/cgroup').returns(cgroup_info)

in_transaction('txn') do
Expand Down

0 comments on commit c714f98

Please sign in to comment.