nexaas-queue_time 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e48475f10c2bf68a6e0486bbf1d0c2c1b66f2e71d56ad35392707807ac158d66
4
- data.tar.gz: bad0970dfd5d9ee2496fec837a0fb7fb4e2b63ede476820682c80175ef2bbc17
3
+ metadata.gz: 87997f283ea190bbdcba83290a11d23dbc446db1a11c32d48b51d8b3bc110219
4
+ data.tar.gz: 57746b20d94c1ddd326b405906ba6dfc887089cb3f43c66d89e6d9131beec209
5
5
  SHA512:
6
- metadata.gz: 20cba9c3530a8e066ee0261486c69a486565dc6a1c86314bf3db4798662d1203bdde51625a4319e4cbe277a301342a6771ad32d3f7c04978d5cb6cdb040da787
7
- data.tar.gz: f7cf37772229044a1f72b0cd4dc1109e4fbd8a14469d2c25bfc48f0a6cbb927aa691b7908e2be2442a87057069da8602663b033431a619779b1f2c6536da3126
6
+ metadata.gz: ecb3f250ee9abb4caa347d1209e2696f89b4d2e4a977d11a5dd109d007d861ee8f0739d1792e693c213ce0487026974b3e0fccfab7705ec52d4f046112a59d63
7
+ data.tar.gz: 16467b32806ef5813cf070d4efe9d86171022caab30c2ecbd407e694ec0e24f1df8352f386172106785976b204d9ae954b921d52da38e43aebf28ebe7c598a10
data/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.3.0] - 2019-07-01
6
+
7
+ ### Added
8
+
9
+ - Document middleware class
10
+ - Test for header pattern before calculating `queue_time`
11
+
12
+ ### Changed
13
+
14
+ - Do not calculate `queue_time` if header is not present
15
+
16
+ ### Fixed
17
+
18
+ - Use `String =~` instead of `String#match?` due to Ruby 2.3
19
+
5
20
  ## [0.2.0] - 2019-06-28
6
21
 
7
22
  ### Fixed
@@ -15,28 +30,4 @@ All notable changes to this project will be documented in this file.
15
30
  - Initial implementation of the gem
16
31
 
17
32
 
18
- [6.0.0]: https://github.com/kickstarter/rack-attack/compare/v5.4.2...v6.0.0/
19
- [5.4.2]: https://github.com/kickstarter/rack-attack/compare/v5.4.1...v5.4.2/
20
- [5.4.1]: https://github.com/kickstarter/rack-attack/compare/v5.4.0...v5.4.1/
21
- [5.4.0]: https://github.com/kickstarter/rack-attack/compare/v5.3.2...v5.4.0/
22
- [5.3.2]: https://github.com/kickstarter/rack-attack/compare/v5.3.1...v5.3.2/
23
- [5.3.1]: https://github.com/kickstarter/rack-attack/compare/v5.3.0...v5.3.1/
24
- [5.3.0]: https://github.com/kickstarter/rack-attack/compare/v5.2.0...v5.3.0/
25
- [5.2.0]: https://github.com/kickstarter/rack-attack/compare/v5.1.0...v5.2.0/
26
- [5.1.0]: https://github.com/kickstarter/rack-attack/compare/v5.0.1...v5.1.0/
27
- [5.0.1]: https://github.com/kickstarter/rack-attack/compare/v5.0.0...v5.0.1/
28
- [5.0.0]: https://github.com/kickstarter/rack-attack/compare/v4.4.1...v5.0.0/
29
- [4.4.1]: https://github.com/kickstarter/rack-attack/compare/v4.4.0...v4.4.1/
30
- [4.4.0]: https://github.com/kickstarter/rack-attack/compare/v4.3.1...v4.4.0/
31
- [4.3.1]: https://github.com/kickstarter/rack-attack/compare/v4.3.0...v4.3.1/
32
- [4.3.0]: https://github.com/kickstarter/rack-attack/compare/v4.2.0...v4.3.0/
33
- [4.2.0]: https://github.com/kickstarter/rack-attack/compare/v4.1.1...v4.2.0/
34
- [4.1.1]: https://github.com/kickstarter/rack-attack/compare/v4.1.0...v4.1.1/
35
- [4.1.0]: https://github.com/kickstarter/rack-attack/compare/v4.0.1...v4.1.0/
36
- [4.0.1]: https://github.com/kickstarter/rack-attack/compare/v4.0.0...v4.0.1/
37
- [4.0.0]: https://github.com/kickstarter/rack-attack/compare/v3.0.0...v4.0.0/
38
- [3.0.0]: https://github.com/kickstarter/rack-attack/compare/v2.3.0...v3.0.0/
39
- [2.3.0]: https://github.com/kickstarter/rack-attack/compare/v2.2.1...v2.3.0/
40
- [2.2.1]: https://github.com/kickstarter/rack-attack/compare/v2.2.0...v2.2.1/
41
- [2.2.0]: https://github.com/kickstarter/rack-attack/compare/v2.1.1...v2.2.0/
42
-
33
+ [0.2.0]: https://github.com/myfreecomm/nexaas-queue_time/compare/v0.1.0...v0.2.0/
@@ -4,40 +4,62 @@ require 'datadog/statsd'
4
4
 
5
5
  module Nexaas
6
6
  module QueueTime
7
+ # This middleware calculates the time a request has been waiting
8
+ # in the queue before being served by the application server.
9
+ #
10
+ # It requires the header `X_REQUEST_START`. This header contains
11
+ # the timestamp of when the request first apperead in the stack.
12
+ # This header is usually set by a LoadBalancer, Reverse Proxy or Router.
13
+ #
14
+ # The format of the header **must** match:
15
+ # `t=TIMESTAMP`, where TIMESTAMP is the unix timestamp.
16
+ # This format is supported by APMs such as New Relic and Scout
7
17
  class Middleware
8
18
  METRIC_NAME = 'request.queue_time'
19
+ HEADER_FORMAT_PATTERN = /
20
+ ^ # Beginning of line
21
+ t= #
22
+ \d+ # At least 1 digit
23
+ \.? # Optionally a dot may be used for fractional timestamps
24
+ \d* # Optionally more digits after the dot
25
+ $ # End of line
26
+ /x
9
27
 
10
28
  def initialize(app)
11
29
  @app = app
12
30
  end
13
31
 
14
32
  def call(env)
15
- left_queue = Time.now.to_f
16
- metric = queue_time_in_ms(left_queue, env)
17
- send_metric(metric)
33
+ request_start_header = env['HTTP_X_REQUEST_START']
34
+ if request_start_header && request_start_header =~ HEADER_FORMAT_PATTERN
35
+ left_queue_at = Time.now.to_f
36
+ metric = calculate_queue_time_in_ms(left_queue_at, request_start_header)
37
+ send_metric(metric)
38
+ end
18
39
 
19
40
  @app.call(env)
20
41
  end
21
42
 
22
43
  private
23
44
 
24
- def queue_time_in_ms(left_queue, env)
25
- entered_queue = env['HTTP_X_REQUEST_START']
26
- return nil if entered_queue.nil?
27
-
28
- entered_queue = extract_timestamp(entered_queue)
29
- (left_queue - entered_queue.to_f) * 1000
45
+ def calculate_queue_time_in_ms(left_queue_at, request_start_header)
46
+ entered_queue_at = extract_timestamp(request_start_header)
47
+ (left_queue_at - entered_queue_at.to_f) * 1000
30
48
  end
31
49
 
32
- # The header actually comes as `t=1234567890`,
33
- # so we need to extract the timestamp.
34
50
  def extract_timestamp(entered_queue)
35
51
  entered_queue.delete('t=')
36
52
  end
37
53
 
54
+ # By default, Datadog::Statsd opens a UDP connection with a given host and port.
55
+ # Instead, we are giving it a socket path so it communicates with the statsd server via UDS.
56
+ #
57
+ # This approach is easier to setup in containerized environments since all it requires
58
+ # is the path to the socket file instead of the host address.
59
+ #
60
+ # UDS also performs better than UDP,
61
+ # although the app would need to receive huge traffic to actually feel the difference.
38
62
  def send_metric(metric)
39
- return unless metric
40
-
41
63
  Datadog::Statsd.open(nil, nil, socket_path: '/var/run/datadog/dsd.socket') do |statsd|
42
64
  statsd.timing(METRIC_NAME, metric.to_i, sample_rate: 1)
43
65
  end
@@ -1,5 +1,5 @@
1
1
  module Nexaas
2
2
  module QueueTime
3
- VERSION = '0.2.0'
3
+ VERSION = '0.3.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nexaas-queue_time
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Mansur
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-28 00:00:00.000000000 Z
11
+ date: 2019-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dogstatsd-ruby