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 +4 -4
- data/CHANGELOG.md +16 -25
- data/lib/nexaas/queue_time/middleware.rb +35 -13
- data/lib/nexaas/queue_time/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87997f283ea190bbdcba83290a11d23dbc446db1a11c32d48b51d8b3bc110219
|
4
|
+
data.tar.gz: 57746b20d94c1ddd326b405906ba6dfc887089cb3f43c66d89e6d9131beec209
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
[
|
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
|
-
|
16
|
-
|
17
|
-
|
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
|
25
|
-
|
26
|
-
|
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
|
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.
|
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-
|
11
|
+
date: 2019-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dogstatsd-ruby
|