salestation 0.1.0 → 0.1.1

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
  SHA1:
3
- metadata.gz: 7af82fc0b7698f3f66945b5291d2a2d9ccf869bd
4
- data.tar.gz: e0f635d0e541cb790124900cc7c6b2cc10a8fc5e
3
+ metadata.gz: 8ebf9157080bc595e5627ac9dd0a63a24afd3f12
4
+ data.tar.gz: 06f85ef72b8cf37c248129448e9466040016c6c2
5
5
  SHA512:
6
- metadata.gz: deab697cdfd27d779bdf67e09508e0dbadb602e0351b6727592f9d695e54de121223133f01d8e92af3ca818fe5952b3f8831f49c776b5e508ea8f61c23081db5
7
- data.tar.gz: 818726078b70b2e9a44b6af528e81a8e2aaef8ceffba89ec299b61c345c67a002152d164f6200fd31dfa5f33ca46f584118760728c70ad8fd713f6cca194f0b3
6
+ metadata.gz: a1ceaacece5be4693ce08f0542486b86e7c4462b273b8e9efebe958f30ac3471e21e3f95e77f7b90b7f77a01f64861b5a63b9ac7f9599dcfa86c2f91304925e2
7
+ data.tar.gz: 54fd1b4f4a7dca1e60959d3f213f2a33d2178ca400c3e4170bfab88a43ab1356775ad25075519aadbdb7b7c164c7f9bfcb2e03f83a392e68135a3b4355dfa3ed
data/README.md CHANGED
@@ -73,6 +73,32 @@ Salestation allows and recommends you to define your own custom errors. This is
73
73
  })
74
74
  ```
75
75
 
76
+ ### Using a logger
77
+
78
+ Salestation provides a rack logging middleware which can be used to log structured objects.
79
+
80
+ ```ruby
81
+ class Webapp < Sinatra::Base
82
+ # ...
83
+ use Salestation::Web::RequestLogger, my_logger
84
+ end
85
+ ```
86
+
87
+ ### Using StatsD
88
+
89
+ Salestation provides a StatsD middleware which can be used record request
90
+ execution time. A `timing` call with elapsed seconds is made to the provided
91
+ StatsD instance with `path`, `method`, `status` tags.
92
+
93
+ ```ruby
94
+ class Webapp < Sinatra::Base
95
+ # ...
96
+ use Salestation::Web::StatsdMiddleware,
97
+ Statsd.new(host, port),
98
+ metric: 'my-metric'
99
+ end
100
+ ```
101
+
76
102
  ## Development
77
103
 
78
104
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,91 @@
1
+ module Salestation
2
+ class Web < Module
3
+ class RequestLogger
4
+
5
+ REMOTE_ADDR = 'REMOTE_ADDR'.freeze
6
+ REQUEST_URI = 'REQUEST_URI'.freeze
7
+ REQUEST_METHOD = 'REQUEST_METHOD'.freeze
8
+ QUERY_STRING = 'QUERY_STRING'.freeze
9
+ CONTENT_TYPE = 'CONTENT_TYPE'.freeze
10
+ HTTP_USER_AGENT = 'HTTP_USER_AGENT'.freeze
11
+ HTTP_ACCEPT = 'HTTP_ACCEPT'.freeze
12
+ SERVER_NAME = 'SERVER_NAME'.freeze
13
+ JSON_CONTENT_TYPE = 'application/json'.freeze
14
+
15
+ def initialize(app, logger)
16
+ @app = app
17
+ @logger = logger
18
+ end
19
+
20
+ def call(env)
21
+ request_id = SecureRandom.hex(4)
22
+ request_logger = Logger.new(@logger, request_id)
23
+
24
+ env['request_logger'] = request_logger
25
+ began_at = Time.now
26
+
27
+ request_logger.info('Received request', request_log(env))
28
+ @app.call(env).tap do |status, headers, body|
29
+ type = status >= 500 ? :info : :error
30
+ request_logger.public_send(type, 'Processed request', response_log(env, status, headers, body, began_at))
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def request_log(env)
37
+ {
38
+ remote_addr: env[REMOTE_ADDR],
39
+ method: env[REQUEST_METHOD],
40
+ path: env[REQUEST_URI],
41
+ query: env[QUERY_STRING],
42
+ content_type: env[CONTENT_TYPE],
43
+ http_agent: env[HTTP_USER_AGENT],
44
+ http_accept: env[HTTP_ACCEPT],
45
+ server_name: env[SERVER_NAME]
46
+ }
47
+ end
48
+
49
+ def response_log(env, status, headers, body, began_at)
50
+ response_payload =
51
+ if status >= 400
52
+ { error: parse_body(body) }
53
+ else
54
+ { body: parse_body(body) }
55
+ end
56
+
57
+ {
58
+ path: env[REQUEST_URI],
59
+ method: env[REQUEST_METHOD],
60
+ status: status,
61
+ duration: Time.now - began_at,
62
+ headers: headers.slice(
63
+ 'Location', 'Content-Length', 'Content-Type'
64
+ )
65
+ }.merge(response_payload)
66
+ end
67
+
68
+ def parse_body(body)
69
+ begin
70
+ # Rack body is an array
71
+ JSON.parse(body.join())
72
+ rescue Exception
73
+ {error: "Failed to parse response body"}
74
+ end
75
+ end
76
+
77
+ class Logger
78
+ def initialize(logger, request_id)
79
+ @logger = logger
80
+ @request_id = request_id
81
+ end
82
+
83
+ [:debug, :info, :warn, :error].each do |name|
84
+ define_method(name) do |msg, metadata = {}|
85
+ @logger.public_send(name, msg, metadata.merge(request_id: @request_id))
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,28 @@
1
+ module Salestation
2
+ class Web < Module
3
+ class StatsdMiddleware
4
+
5
+ def initialize(app, statsd, metric:)
6
+ @app = app
7
+ @statsd = statsd
8
+ @metric = metric
9
+ end
10
+
11
+ def call(env)
12
+ start = Time.now
13
+
14
+ status, header, body = @app.call env
15
+
16
+ method, path = env['sinatra.route'].split
17
+
18
+ @statsd.timing(@metric, (Time.now - start) * 1000, tags: [
19
+ "path:#{ path }",
20
+ "method:#{ method }",
21
+ "status:#{ status }"
22
+ ])
23
+
24
+ [status, header, body]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -33,3 +33,5 @@ end
33
33
  require_relative './web/responses'
34
34
  require_relative './web/error_mapper'
35
35
  require_relative './result_helper'
36
+ require_relative './web/request_logger'
37
+ require_relative './web/statsd_middleware'
data/salestation.gemspec CHANGED
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "salestation"
7
- spec.version = "0.1.0"
7
+ spec.version = "0.1.1"
8
8
  spec.authors = ["SaleMove TechMovers"]
9
9
  spec.email = ["techmovers@salemove.com"]
10
10
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: salestation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - SaleMove TechMovers
@@ -116,7 +116,9 @@ files:
116
116
  - lib/salestation/result_helper.rb
117
117
  - lib/salestation/web.rb
118
118
  - lib/salestation/web/error_mapper.rb
119
+ - lib/salestation/web/request_logger.rb
119
120
  - lib/salestation/web/responses.rb
121
+ - lib/salestation/web/statsd_middleware.rb
120
122
  - salestation.gemspec
121
123
  homepage: ''
122
124
  licenses: