-
Notifications
You must be signed in to change notification settings - Fork 375
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
Enable crashtracking without profiler #3826
Changes from all commits
e1f6424
6dafb7a
1788fe8
2ee80c4
6cb7c4c
208ef61
029a0dc
1ebf56b
a1bc94f
9ac6f1e
51c88e2
556c705
016f5ac
72499cd
9682847
6f3c5fe
85bd6b8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative '../configuration/ext' | ||
|
||
module Datadog | ||
module Core | ||
module Crashtracking | ||
# This module provides a method to resolve the base URL of the agent | ||
module AgentBaseUrl | ||
def self.resolve(agent_settings) | ||
case agent_settings.adapter | ||
when Datadog::Core::Configuration::Ext::Agent::HTTP::ADAPTER | ||
"#{agent_settings.ssl ? 'https' : 'http'}://#{agent_settings.hostname}:#{agent_settings.port}/" | ||
when Datadog::Core::Configuration::Ext::Agent::UnixSocket::ADAPTER | ||
"unix://#{agent_settings.uds_path}" | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'libdatadog' | ||
|
||
require_relative 'tag_builder' | ||
require_relative 'agent_base_url' | ||
require_relative '../utils/only_once' | ||
require_relative '../utils/at_fork_monkey_patch' | ||
|
||
module Datadog | ||
module Core | ||
module Crashtracking | ||
# Used to report Ruby VM crashes. | ||
# | ||
# NOTE: The crashtracker native state is a singleton; | ||
# so even if you create multiple instances of `Crashtracking::Component` and start them, | ||
# it only works as "last writer wins". Same for stop -- there's only one state, so calling stop | ||
# on it will stop the crash tracker, regardless of which instance started it. | ||
# | ||
# Methods prefixed with _native_ are implemented in `crashtracker.c` | ||
class Component | ||
LIBDATADOG_API_FAILURE = | ||
begin | ||
require "libdatadog_api.#{RUBY_VERSION[/\d+.\d+/]}_#{RUBY_PLATFORM}" | ||
nil | ||
rescue LoadError => e | ||
e.message | ||
end | ||
|
||
ONLY_ONCE = Core::Utils::OnlyOnce.new | ||
|
||
def self.build(settings, agent_settings, logger:) | ||
tags = TagBuilder.call(settings) | ||
agent_base_url = AgentBaseUrl.resolve(agent_settings) | ||
logger.warn('Missing agent base URL; cannot enable crash tracking') unless agent_base_url | ||
|
||
ld_library_path = ::Libdatadog.ld_library_path | ||
logger.warn('Missing ld_library_path; cannot enable crash tracking') unless ld_library_path | ||
|
||
path_to_crashtracking_receiver_binary = ::Libdatadog.path_to_crashtracking_receiver_binary | ||
unless path_to_crashtracking_receiver_binary | ||
logger.warn('Missing path_to_crashtracking_receiver_binary; cannot enable crash tracking') | ||
end | ||
|
||
return unless agent_base_url | ||
return unless ld_library_path | ||
return unless path_to_crashtracking_receiver_binary | ||
|
||
new( | ||
tags: tags, | ||
agent_base_url: agent_base_url, | ||
ld_library_path: ld_library_path, | ||
path_to_crashtracking_receiver_binary: path_to_crashtracking_receiver_binary, | ||
logger: logger | ||
).tap(&:start) | ||
end | ||
|
||
def initialize(tags:, agent_base_url:, ld_library_path:, path_to_crashtracking_receiver_binary:, logger:) | ||
@tags = tags | ||
@agent_base_url = agent_base_url | ||
@ld_library_path = ld_library_path | ||
@path_to_crashtracking_receiver_binary = path_to_crashtracking_receiver_binary | ||
@logger = logger | ||
end | ||
|
||
def start | ||
Utils::AtForkMonkeyPatch.apply! | ||
|
||
start_or_update_on_fork(action: :start) | ||
ONLY_ONCE.run do | ||
Utils::AtForkMonkeyPatch.at_fork(:child) do | ||
# Must NOT reference `self` here, as only the first instance will | ||
# be captured by the ONLY_ONCE and we want to pick the latest active one | ||
# (which may have different tags or agent config) | ||
Datadog.send(:components).crashtracker&.update_on_fork | ||
end | ||
end | ||
end | ||
|
||
def update_on_fork | ||
start_or_update_on_fork(action: :update_on_fork) | ||
end | ||
|
||
def stop | ||
self.class._native_stop | ||
logger.debug('Crash tracking stopped successfully') | ||
rescue => e | ||
logger.error("Failed to stop crash tracking: #{e.message}") | ||
end | ||
|
||
private | ||
|
||
attr_reader :tags, :agent_base_url, :ld_library_path, :path_to_crashtracking_receiver_binary, :logger | ||
|
||
def start_or_update_on_fork(action:) | ||
self.class._native_start_or_update_on_fork( | ||
action: action, | ||
exporter_configuration: [:agent, agent_base_url], | ||
path_to_crashtracking_receiver_binary: path_to_crashtracking_receiver_binary, | ||
ld_library_path: ld_library_path, | ||
tags_as_array: tags.to_a, | ||
upload_timeout_seconds: 1 | ||
ivoanjo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
) | ||
logger.debug("Crash tracking #{action} successfully") | ||
rescue => e | ||
logger.error("Failed to #{action} crash tracking: #{e.message}") | ||
end | ||
end | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative '../utils' | ||
require_relative '../environment/socket' | ||
require_relative '../environment/identity' | ||
require_relative '../environment/git' | ||
|
||
module Datadog | ||
module Core | ||
module Crashtracking | ||
# This module builds a hash of tags | ||
module TagBuilder | ||
def self.call(settings) | ||
hash = { | ||
'host' => Environment::Socket.hostname, | ||
'process_id' => Process.pid.to_s, | ||
'runtime_engine' => Environment::Identity.lang_engine, | ||
'runtime-id' => Environment::Identity.id, | ||
'runtime_platform' => Environment::Identity.lang_platform, | ||
'runtime_version' => Environment::Identity.lang_version, | ||
'env' => settings.env, | ||
'service' => settings.service, | ||
'version' => settings.version, | ||
'git.repository_url' => Environment::Git.git_repository_url, | ||
'git.commit.sha' => Environment::Git.git_commit_sha, | ||
'is_crash' => true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice catch! I was talking with @sanchda about this yesterday and he mentioned libdatadog wasn't adding these automatically. In Python we also add |
||
}.compact | ||
|
||
# Make sure everything is an utf-8 string, to avoid encoding issues in downstream | ||
settings.tags.merge(hash).each_with_object({}) do |(key, value), h| | ||
h[Utils.utf8_encode(key)] = Utils.utf8_encode(value) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also get this check by setting the
DD_FAIL_INSTALL_IF_MISSING_EXTENSION
env variable to"true"
when callinggem install
:)