@@ -22,6 +22,9 @@ def initialize
22
22
# Supported two states (unannounced & announced)
23
23
@state = :unannounced
24
24
25
+ # Store the pid from process boot so we can detect forks
26
+ @pid = Process . pid
27
+
25
28
# Snapshot data is collected once per process but resent
26
29
# every 10 minutes along side process metrics.
27
30
@snapshot = take_snapshot
@@ -39,8 +42,9 @@ def initialize
39
42
@announce_timer = nil
40
43
@collect_timer = nil
41
44
42
- # Detect if we're on linux or not (used in host_agent_ready?)
45
+ # Detect platform flags
43
46
@is_linux = ( RUBY_PLATFORM =~ /linux/i ) ? true : false
47
+ @is_osx = ( RUBY_PLATFORM =~ /darwin/i ) ? true : false
44
48
45
49
# In case we're running in Docker, have the default gateway available
46
50
# to check in case we're running in bridged network mode
@@ -53,23 +57,68 @@ def initialize
53
57
# The agent UUID returned from the host agent
54
58
@agent_uuid = nil
55
59
60
+ collect_process_info
61
+ end
62
+
63
+ # Used in class initialization and after a fork, this method
64
+ # collects up process information and stores it in @process
65
+ #
66
+ def collect_process_info
56
67
@process = { }
57
68
cmdline = ProcTable . ps ( Process . pid ) . cmdline . split ( "\0 " )
58
69
@process [ :name ] = cmdline . shift
59
70
@process [ :arguments ] = cmdline
60
- @process [ :original_pid ] = Process . pid
71
+
72
+ if @is_osx
73
+ # Handle OSX bug where env vars show up at the end of process name
74
+ # such as MANPATH etc..
75
+ @process [ :name ] . gsub! ( /[_A-Z]+=\S +/ , '' )
76
+ @process [ :name ] . rstrip!
77
+ end
78
+
79
+ @process [ :original_pid ] = @pid
61
80
# This is usually Process.pid but in the case of docker, the host agent
62
81
# will return to us the true host pid in which we use to report data.
63
82
@process [ :report_pid ] = nil
64
83
end
65
84
85
+ # Determine whether the pid has changed since Agent start.
86
+ #
87
+ # @ return [Boolean] true or false to indicate if forked
88
+ #
89
+ def forked?
90
+ @pid != Process . pid
91
+ end
92
+
93
+ # Used post fork to re-initialize state and restart communications with
94
+ # the host agent.
95
+ #
96
+ def after_fork
97
+ ::Instana . logger . debug "after_fork hook called. Falling back to unannounced state."
98
+
99
+ # Re-collect process information post fork
100
+ @pid = Process . pid
101
+ collect_process_info
102
+
103
+ # Set last snapshot to 10 minutes ago
104
+ # so we send a snapshot sooner than later
105
+ @last_snapshot = Time . now - 600
106
+
107
+ transition_to ( :unannounced )
108
+ start
109
+ end
110
+
66
111
# Sets up periodic timers and starts the agent in a background thread.
67
112
#
68
113
def start
69
114
# The announce timer
70
115
# We attempt to announce this ruby sensor to the host agent.
71
116
# In case of failure, we try again in 30 seconds.
72
117
@announce_timer = @timers . now_and_every ( 30 ) do
118
+ if forked?
119
+ after_fork
120
+ break
121
+ end
73
122
if host_agent_ready? && announce_sensor
74
123
::Instana . logger . debug "Announce successful. Switching to metrics collection."
75
124
transition_to ( :announced )
@@ -81,6 +130,10 @@ def start
81
130
# every ::Instana::Collector.interval seconds.
82
131
@collect_timer = @timers . every ( ::Instana ::Collector . interval ) do
83
132
if @state == :announced
133
+ if forked?
134
+ after_fork
135
+ break
136
+ end
84
137
unless ::Instana ::Collector . collect_and_report
85
138
# If report has been failing for more than 1 minute,
86
139
# fall back to unannounced state
0 commit comments