neetodeploy-autoscale 2.1.2 → 2.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7c7841930ad563bfa0d372de339715f70ba9dba99e0ef61ec09fcc9f0624a683
4
- data.tar.gz: 1134df572ad17a7a6678770ac3a63227e4544f7d9b195489070ae14f3fead18d
3
+ metadata.gz: cdd8f665987aa730bfca4343fea2b9ae6f93bc5a4d6dcbc4152a7fb879165703
4
+ data.tar.gz: e0390da1428e2fa58547fc8045b7c769c824c502e37db945732833f2d3beb2b8
5
5
  SHA512:
6
- metadata.gz: 3a6eb8853074dc0029d1c8dbab103916fda6f1719206dc966d3dcd5f2ea43250ec8762e52c00a2b32efa2071af3b3e7e3d7ea35cc07a664e69383e354ee0a61f
7
- data.tar.gz: 55374376294d4c77f712423b16d5df3d9b5755ca99210697f225904a3d952dae6930e277d7ab2c8a3261d9cef978990943ffda50c95cfbb8e04b3d4440520a64
6
+ metadata.gz: a7e6a766486c6785ff2f53d7f0759bfaa1738b416c0f679df970ad2bcee1de9a1b1e97f0fedc61a6f94625ef30d14f7fdf5081eae0cb37bf1005a85b057bb34e
7
+ data.tar.gz: 2d843f184f0f3ba6acf8f0823e04860ded3c9e76fe6a1d512592e154507890c66021283a2087775387cdb153511412f3382fa0d0f83a47e124307616f1a898bf
@@ -8,12 +8,13 @@ module Neetodeploy
8
8
  class Metrics
9
9
  def initialize(env, config = Config.instance)
10
10
  @config = config
11
+ @env = env
11
12
  @request_start_header_raw = env["HTTP_X_REQUEST_START"]
12
13
  @request_start_header = @request_start_header_raw.to_i
13
14
  @network_time = env["puma.request_body_wait"].to_i
14
15
 
15
- # Debug: Log all HTTP headers to help diagnose
16
- if @request_start_header_raw.nil? || @request_start_header_raw.empty?
16
+ # Debug: Log all HTTP headers to help diagnose (only for non-health-check requests)
17
+ if (@request_start_header_raw.nil? || @request_start_header_raw.empty?) && !health_check_request?(env)
17
18
  # Get all HTTP_* headers (these are the request headers)
18
19
  http_headers = env.keys.grep(/^HTTP_/)
19
20
 
@@ -32,7 +33,14 @@ module Neetodeploy
32
33
  end
33
34
 
34
35
  def ignore?
35
- @config.gem_disabled?
36
+ @config.gem_disabled? || health_check_request?(@env)
37
+ end
38
+
39
+ def health_check_request?(env = @env)
40
+ # Ignore health check endpoints that don't go through Traefik
41
+ # These typically come from Kubernetes liveness/readiness probes
42
+ path = env["PATH_INFO"] || env["REQUEST_PATH"] || ""
43
+ path.match?(%r{/health_check|/health|/up|/ready|/live})
36
44
  end
37
45
 
38
46
  def queue_time
@@ -1,29 +1,69 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "singleton"
4
+ require "neetodeploy/autoscale/logger"
4
5
 
5
6
  module Neetodeploy
6
7
  module Rails
7
8
  class MetricsStore
8
9
  include Singleton
9
10
 
11
+ # Use sliding window: keep last 2 minutes of data (120 seconds)
12
+ # At 2s reporting interval, this gives us ~60 samples per window
13
+ # This ensures percentiles work correctly even with low traffic
14
+ WINDOW_SIZE_SECONDS = 120
15
+ MAX_SAMPLES = 1000 # Safety limit to prevent memory bloat
16
+
10
17
  attr_reader :metrics
11
18
 
12
19
  def initialize
13
- @metrics = []
20
+ @metrics = [] # Array of {time: timestamp, value: queue_time}
14
21
  @mutex = Mutex.new
15
22
  end
16
23
 
17
24
  def push(queue_time)
18
25
  @mutex.synchronize do
19
- @metrics << queue_time
26
+ now = Time.now.to_f
27
+ @metrics << { time: now, value: queue_time }
28
+
29
+ # Remove old data outside window
30
+ cutoff = now - WINDOW_SIZE_SECONDS
31
+ @metrics.reject! { |m| m[:time] < cutoff }
32
+
33
+ # Safety limit: keep only most recent samples
34
+ if @metrics.size > MAX_SAMPLES
35
+ @metrics = @metrics.last(MAX_SAMPLES)
36
+ end
37
+
38
+ # Log high queue times to help debug
39
+ if queue_time > 500
40
+ NeetoDeploy::Logger.logger.debug("MetricsStore: Pushed high queue_time=#{queue_time}ms (total in window: #{@metrics.size})")
41
+ end
42
+ end
43
+ end
44
+
45
+ # Get recent samples from the sliding window (last N seconds)
46
+ def get_recent(seconds = WINDOW_SIZE_SECONDS)
47
+ @mutex.synchronize do
48
+ cutoff = Time.now.to_f - seconds
49
+ @metrics.select { |m| m[:time] >= cutoff }.map { |m| m[:value] }
20
50
  end
21
51
  end
22
52
 
53
+ # Flush: return all values in window, but DON'T clear (sliding window)
54
+ # This allows high values to persist across multiple reporting cycles
23
55
  def flush
24
56
  @mutex.synchronize do
25
- result = @metrics
26
- @metrics = []
57
+ # Clean up old data first
58
+ cutoff = Time.now.to_f - WINDOW_SIZE_SECONDS
59
+ @metrics.reject! { |m| m[:time] < cutoff }
60
+
61
+ result = @metrics.map { |m| m[:value] }
62
+ size = result.size
63
+ max_val = result.max if result.any?
64
+ NeetoDeploy::Logger.logger.debug("MetricsStore: Reporting from sliding window: #{size} values, max=#{max_val}ms") if result.any?
65
+
66
+ # Return values but keep them in the window for next cycle
27
67
  result
28
68
  end
29
69
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Neetodeploy
4
4
  module Autoscale
5
- VERSION = "2.1.2"
5
+ VERSION = "2.1.4"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: neetodeploy-autoscale
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sreeram Venkitesh