|
| 1 | +# This file is distributed under New Relic's license terms. |
| 2 | +# See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details. |
| 3 | +# frozen_string_literal: true |
| 4 | + |
| 5 | +module NewRelic::Agent::Instrumentation |
| 6 | + module Parallel |
| 7 | + module Instrumentation |
| 8 | + # This runs inside of the new process that was forked by Parallel |
| 9 | + def worker_with_tracing(channel_id, &block) |
| 10 | + NewRelic::Agent.after_fork( |
| 11 | + :report_to_channel => channel_id, |
| 12 | + :report_instance_busy => false |
| 13 | + ) |
| 14 | + |
| 15 | + setup_for_txn_metric_merge_at_exit |
| 16 | + |
| 17 | + yield |
| 18 | + end |
| 19 | + |
| 20 | + def setup_for_txn_metric_merge_at_exit |
| 21 | + # Clear out any existing transaction metrics to prevent duplicates |
| 22 | + # when merging metrics back in at the end of the forked process |
| 23 | + if (txn = NewRelic::Agent::Tracer.current_transaction) |
| 24 | + txn.instance_variable_set(:@metrics, NewRelic::Agent::TransactionMetrics.new) |
| 25 | + end |
| 26 | + |
| 27 | + # Install at_exit hook only once per process |
| 28 | + unless @parallel_at_exit_installed |
| 29 | + @parallel_at_exit_installed = true |
| 30 | + at_exit do |
| 31 | + # Merge all newly recorded metrics back into the parent process |
| 32 | + # It's a little weird, but needed because the transaction does not |
| 33 | + # finish in the child processes, so without this the metrics would be lost. |
| 34 | + if (txn = NewRelic::Agent::Tracer.current_transaction) |
| 35 | + NewRelic::Agent.agent.stats_engine.merge_transaction_metrics!( |
| 36 | + txn.metrics, |
| 37 | + txn.best_name |
| 38 | + ) |
| 39 | + end |
| 40 | + |
| 41 | + # force data to be sent back to the parent process |
| 42 | + NewRelic::Agent.agent&.stop_event_loop |
| 43 | + NewRelic::Agent.agent&.flush_pipe_data |
| 44 | + end |
| 45 | + end |
| 46 | + end |
| 47 | + end |
| 48 | + end |
| 49 | +end |
0 commit comments