hyperprobe-agent 1.2.27.pre.1 → 1.2.27.pre.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +316 -87
- data/lib/hyperprobe/agent.rb +243 -144
- data/lib/hyperprobe/core/broker.rb +58 -88
- data/lib/hyperprobe/core/evaluator.rb +358 -68
- data/lib/hyperprobe/core/lexical_scope.rb +222 -0
- data/lib/hyperprobe/core/logger.rb +33 -12
- data/lib/hyperprobe/core/monitoring_engine.rb +294 -120
- data/lib/hyperprobe/core/safe_ast_validator.rb +140 -61
- data/lib/hyperprobe/core/safety.rb +92 -15
- data/lib/hyperprobe/core/serializer.rb +354 -342
- data/lib/hyperprobe/core/transports/java_grpc.rb +57 -0
- data/lib/hyperprobe/lambda.rb +44 -42
- data/lib/hyperprobe/protos/agent_descriptor.rb +7 -0
- data/lib/hyperprobe/protos/java_messages.rb +199 -0
- data/lib/hyperprobe/protos.rb +7 -7
- data/lib/hyperprobe/railtie.rb +6 -0
- data/lib/hyperprobe/version.rb +1 -1
- data/lib/hyperprobe.rb +149 -20
- metadata +25 -9
|
@@ -2,17 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
require 'securerandom'
|
|
4
4
|
require 'socket'
|
|
5
|
-
|
|
5
|
+
require 'json'
|
|
6
6
|
|
|
7
7
|
if RUBY_PLATFORM !~ /java/
|
|
8
|
-
|
|
9
|
-
require 'grpc'
|
|
10
|
-
rescue LoadError
|
|
11
|
-
# Handled gracefully if grpc gem is absent
|
|
12
|
-
end
|
|
8
|
+
require 'grpc'
|
|
13
9
|
else
|
|
14
|
-
|
|
10
|
+
require_relative 'transports/java_grpc'
|
|
15
11
|
end
|
|
12
|
+
require_relative '../protos'
|
|
16
13
|
|
|
17
14
|
module HyperProbe
|
|
18
15
|
module Core
|
|
@@ -34,19 +31,24 @@ module HyperProbe
|
|
|
34
31
|
@commit_sha = commit_sha.to_s
|
|
35
32
|
@agent_id = agent_id || SecureRandom.uuid
|
|
36
33
|
@agent_version = agent_version.to_s
|
|
37
|
-
@rpc_timeout_sec = rpc_timeout_sec
|
|
34
|
+
@rpc_timeout_sec = valid_timeout(rpc_timeout_sec)
|
|
38
35
|
@hostname = ENV['HOSTNAME'] || Socket.gethostname rescue 'unknown'
|
|
39
36
|
@is_jruby = RUBY_PLATFORM =~ /java/
|
|
40
|
-
@log = Logger.get_logger('hyperprobe:broker')
|
|
41
37
|
|
|
42
38
|
if @is_jruby
|
|
43
|
-
|
|
39
|
+
@transport = Transports::JavaGrpc.new(broker_url, @service_id, enable_keep_alive)
|
|
44
40
|
else
|
|
45
|
-
|
|
41
|
+
@calls_mutex = Mutex.new
|
|
42
|
+
@active_calls = []
|
|
43
|
+
@closed = false
|
|
44
|
+
target, creds, channel_args = parse_broker_url(broker_url, enable_keep_alive)
|
|
45
|
+
@channel = GRPC::Core::Channel.new(target, channel_args, creds)
|
|
46
|
+
@stub = Hyperprobe::Agent::V1::AgentBroker::Stub.new(target, creds, channel_override: @channel)
|
|
46
47
|
end
|
|
47
48
|
end
|
|
48
49
|
|
|
49
50
|
def get_probes(timeout_sec = nil)
|
|
51
|
+
deadline = calculate_deadline(timeout_sec || @rpc_timeout_sec)
|
|
50
52
|
req = Hyperprobe::Agent::V1::GetProbesRequest.new(
|
|
51
53
|
agent_id: @agent_id,
|
|
52
54
|
service_id: @service_id,
|
|
@@ -58,96 +60,66 @@ module HyperProbe
|
|
|
58
60
|
)
|
|
59
61
|
|
|
60
62
|
if @is_jruby
|
|
61
|
-
call_jruby_rpc('
|
|
63
|
+
call_jruby_rpc('hyperprobe.agent.v1.AgentBroker/GetProbes', req, Hyperprobe::Agent::V1::GetProbesResponse, deadline)
|
|
62
64
|
else
|
|
63
|
-
|
|
64
|
-
metadata = { 'x-hp-service-id' => @service_id }
|
|
65
|
-
@stub.get_probes(req, metadata: metadata, deadline: deadline)
|
|
65
|
+
call_cruby_rpc(:get_probes, req, deadline)
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
def report_telemetry(events, timeout_sec = nil)
|
|
70
70
|
return [] if events.nil? || events.empty?
|
|
71
71
|
|
|
72
|
+
deadline = calculate_deadline(timeout_sec || @rpc_timeout_sec)
|
|
72
73
|
proto_events = events.map { |evt| build_telemetry_event_proto(evt) }
|
|
73
|
-
batch = Hyperprobe::Agent::V1::TelemetryBatch.new(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
else
|
|
82
|
-
deadline = calculate_deadline(timeout_sec || @rpc_timeout_sec)
|
|
83
|
-
metadata = { 'x-hp-service-id' => @service_id }
|
|
84
|
-
response = @stub.report_telemetry(batch, metadata: metadata, deadline: deadline)
|
|
85
|
-
response.finished_probe_ids.to_a
|
|
86
|
-
end
|
|
74
|
+
batch = Hyperprobe::Agent::V1::TelemetryBatch.new(agent_id: @agent_id, events: proto_events)
|
|
75
|
+
|
|
76
|
+
response = if @is_jruby
|
|
77
|
+
call_jruby_rpc('hyperprobe.agent.v1.AgentBroker/ReportTelemetry', batch, Hyperprobe::Agent::V1::TelemetryResponse, deadline)
|
|
78
|
+
else
|
|
79
|
+
call_cruby_rpc(:report_telemetry, batch, deadline)
|
|
80
|
+
end
|
|
81
|
+
response.finished_probe_ids.to_a
|
|
87
82
|
end
|
|
88
83
|
|
|
89
84
|
def estimate_event_size(event)
|
|
90
85
|
proto = build_telemetry_event_proto(event)
|
|
91
|
-
proto.to_proto.bytesize
|
|
86
|
+
proto.respond_to?(:serialized_size) ? proto.serialized_size : proto.to_proto.bytesize
|
|
92
87
|
rescue StandardError
|
|
93
88
|
JSON.generate(event).bytesize rescue 512
|
|
94
89
|
end
|
|
95
90
|
|
|
96
91
|
def shutdown
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
private
|
|
101
|
-
|
|
102
|
-
def init_cruby_client(broker_url, enable_keep_alive)
|
|
103
|
-
target, creds, channel_args = parse_broker_url(broker_url, enable_keep_alive)
|
|
104
|
-
@stub = Hyperprobe::Agent::V1::AgentBroker::Stub.new(
|
|
105
|
-
target,
|
|
106
|
-
creds,
|
|
107
|
-
channel_args: channel_args
|
|
108
|
-
)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def init_jruby_client(broker_url)
|
|
112
|
-
raw_url = broker_url.to_s.strip
|
|
113
|
-
if raw_url.start_with?('http://', 'https://')
|
|
114
|
-
@base_url = raw_url
|
|
92
|
+
if @is_jruby
|
|
93
|
+
@transport.shutdown
|
|
115
94
|
else
|
|
116
|
-
|
|
95
|
+
calls = @calls_mutex.synchronize do
|
|
96
|
+
@closed = true
|
|
97
|
+
@active_calls.dup
|
|
98
|
+
end
|
|
99
|
+
# Closing a C-core channel alone does not cancel outstanding Ruby operations.
|
|
100
|
+
calls.each(&:cancel)
|
|
101
|
+
@channel.close
|
|
117
102
|
end
|
|
118
|
-
|
|
119
|
-
timeout_ms = (@rpc_timeout_sec * 1000).to_i
|
|
120
|
-
@http_client = java.net.http.HttpClient.newBuilder
|
|
121
|
-
.version(java.net.http.HttpClient::Version::HTTP_2)
|
|
122
|
-
.connectTimeout(java.time.Duration.ofMillis(timeout_ms))
|
|
123
|
-
.build
|
|
124
103
|
end
|
|
125
104
|
|
|
126
|
-
|
|
127
|
-
raw_bytes = request_proto.to_proto
|
|
128
|
-
framed = "\x00" + [raw_bytes.bytesize].pack('N') + raw_bytes
|
|
129
|
-
|
|
130
|
-
uri = java.net.URI.create("#{@base_url}#{method_path}")
|
|
131
|
-
body_publisher = java.net.http.HttpRequest::BodyPublishers.ofByteArray(framed.to_java_bytes)
|
|
105
|
+
private
|
|
132
106
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
.POST(body_publisher)
|
|
107
|
+
def call_cruby_rpc(method, request, deadline)
|
|
108
|
+
operation = @stub.public_send(method, request, metadata: { 'x-hp-service-id' => @service_id },
|
|
109
|
+
deadline: deadline, return_op: true)
|
|
110
|
+
@calls_mutex.synchronize do
|
|
111
|
+
raise IOError, 'Broker transport is shut down' if @closed
|
|
139
112
|
|
|
140
|
-
|
|
141
|
-
if effective_timeout && effective_timeout.positive?
|
|
142
|
-
req_builder.timeout(java.time.Duration.ofMillis((effective_timeout * 1000).to_i))
|
|
113
|
+
@active_calls << operation
|
|
143
114
|
end
|
|
115
|
+
operation.execute
|
|
116
|
+
ensure
|
|
117
|
+
@calls_mutex.synchronize { @active_calls.delete(operation) }
|
|
118
|
+
end
|
|
144
119
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
# Strip 5-byte gRPC prefix header (1 byte compression flag + 4 bytes length)
|
|
149
|
-
proto_payload = response_bytes.length >= 5 ? response_bytes[5..-1] : ''
|
|
150
|
-
response_class.decode(proto_payload)
|
|
120
|
+
def call_jruby_rpc(method_path, request_proto, response_class, deadline)
|
|
121
|
+
payload = request_proto.to_proto
|
|
122
|
+
response_class.decode(@transport.call(method_path, payload, deadline))
|
|
151
123
|
end
|
|
152
124
|
|
|
153
125
|
def build_telemetry_event_proto(evt)
|
|
@@ -180,15 +152,20 @@ module HyperProbe
|
|
|
180
152
|
end
|
|
181
153
|
|
|
182
154
|
def calculate_deadline(timeout_sec)
|
|
183
|
-
|
|
155
|
+
now = @is_jruby ? Process.clock_gettime(Process::CLOCK_MONOTONIC) : Time.now
|
|
156
|
+
now + valid_timeout(timeout_sec)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def valid_timeout(value)
|
|
160
|
+
timeout = Float(value)
|
|
161
|
+
raise ArgumentError, 'RPC timeout must be finite and positive' unless timeout.finite? && timeout.positive?
|
|
184
162
|
|
|
185
|
-
|
|
163
|
+
timeout
|
|
186
164
|
end
|
|
187
165
|
|
|
188
166
|
def parse_broker_url(url, enable_keep_alive)
|
|
189
167
|
raw_url = url.to_s.strip
|
|
190
168
|
channel_args = {}
|
|
191
|
-
|
|
192
169
|
if enable_keep_alive
|
|
193
170
|
channel_args['grpc.keepalive_time_ms'] = 60_000
|
|
194
171
|
channel_args['grpc.keepalive_timeout_ms'] = 20_000
|
|
@@ -196,16 +173,9 @@ module HyperProbe
|
|
|
196
173
|
end
|
|
197
174
|
|
|
198
175
|
if raw_url.start_with?('https://')
|
|
199
|
-
|
|
200
|
-
creds = GRPC::Core::ChannelCredentials.new
|
|
201
|
-
[target, creds, channel_args]
|
|
202
|
-
elsif raw_url.start_with?('http://')
|
|
203
|
-
target = raw_url.sub('http://', '')
|
|
204
|
-
creds = :this_channel_is_insecure
|
|
205
|
-
[target, creds, channel_args]
|
|
176
|
+
[raw_url.sub('https://', ''), GRPC::Core::ChannelCredentials.new, channel_args]
|
|
206
177
|
else
|
|
207
|
-
|
|
208
|
-
[raw_url, creds, channel_args]
|
|
178
|
+
[raw_url.sub(/\Ahttp:\/\//, ''), :this_channel_is_insecure, channel_args]
|
|
209
179
|
end
|
|
210
180
|
end
|
|
211
181
|
end
|