access_watch_rails 0.0.6 → 0.1.0
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 +12 -4
- data/access_watch_rails.gemspec +1 -1
- data/lib/access_watch/logger.rb +23 -1
- data/lib/access_watch/rack_logger.rb +86 -0
- data/lib/access_watch/rails_loader.rb +18 -0
- data/lib/access_watch/rails_version.rb +1 -1
- data/lib/access_watch_rails.rb +6 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c771a0d72ea5fd1d9abef9afa700e8fd2d0ca14
|
4
|
+
data.tar.gz: 2508fb05f8192b23daeba64d5ec79c0836462cc7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bc134a59d2196038d4a2c6818832f6d7635f63943870e60ded809a54ab7f9a2d868af031ecc204de7a6a639275ad967127fe8eee331ba77df0ac0b520a6c9a8
|
7
|
+
data.tar.gz: 5a933d609219a04bb6c605972b24b92e61d1120298e6b18140338706b51fd402d67e4a9c18cab38c49a202571f978f1975022f09c169fd1d011395277821ee93
|
data/README.md
CHANGED
@@ -14,12 +14,20 @@ You will need an API key.
|
|
14
14
|
|
15
15
|
To get an API key, send us an email at api@access.watch and we will come back to you.
|
16
16
|
|
17
|
-
Then
|
17
|
+
Then create the following file `config/access_watch.yml` and restart/deploy your app.
|
18
|
+
|
19
|
+
```yaml
|
20
|
+
development:
|
21
|
+
api_key: API_KEY
|
22
|
+
|
23
|
+
production:
|
24
|
+
api_key: API_KEY
|
25
|
+
```
|
26
|
+
|
27
|
+
Or if you prefere add the following line in `config/application.rb` and restart/deploy your app.
|
18
28
|
|
19
29
|
```ruby
|
20
|
-
|
21
|
-
after_action { AccessWatch::Logger.new(api_key: API_KEY).record(request, response) }
|
22
|
-
end
|
30
|
+
config.middleware.use "AccessWatch::RackLogger", api_key: API_KEY
|
23
31
|
```
|
24
32
|
|
25
33
|
API documentation is here: https://access.watch/api-documentation/#request-logging
|
data/access_watch_rails.gemspec
CHANGED
data/lib/access_watch/logger.rb
CHANGED
@@ -10,7 +10,6 @@ module AccessWatch
|
|
10
10
|
post_request(
|
11
11
|
time: Time.now.utc,
|
12
12
|
address: request.remote_ip,
|
13
|
-
host: request.host,
|
14
13
|
request: {
|
15
14
|
protocol: request.headers["Version"],
|
16
15
|
method: request.method,
|
@@ -21,6 +20,7 @@ module AccessWatch
|
|
21
20
|
headers: extract_http_headers(request.headers)
|
22
21
|
},
|
23
22
|
response: {status: response.status},
|
23
|
+
context: {memory_usage: memory_usage_in_bytes},
|
24
24
|
)
|
25
25
|
end
|
26
26
|
|
@@ -50,5 +50,27 @@ module AccessWatch
|
|
50
50
|
def post_async(path, data)
|
51
51
|
Thread.new { client.post(path, data) }
|
52
52
|
end
|
53
|
+
|
54
|
+
def memory_usage_in_bytes
|
55
|
+
linux_process_memory_usage_in_bytes(Process.pid)
|
56
|
+
end
|
57
|
+
|
58
|
+
def linux_process_status(pid)
|
59
|
+
path = "/proc/#{pid}/status"
|
60
|
+
return unless File.readable?(path)
|
61
|
+
File.read(path).split("\n").reduce({}) do |hash, line|
|
62
|
+
name, value = line.split(":")
|
63
|
+
hash[name] = value.strip
|
64
|
+
hash
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
MEMORY_CONVERSIONS = {"kb" => 1024, "mb" => 1024 * 1024, "gb" => 1024 * 1024 * 1024}
|
69
|
+
|
70
|
+
def linux_process_memory_usage_in_bytes(pid)
|
71
|
+
return unless status = linux_process_status(pid)
|
72
|
+
value, unit = status["VmRSS"].split
|
73
|
+
value.to_i * MEMORY_CONVERSIONS[unit.downcase]
|
74
|
+
end
|
53
75
|
end
|
54
76
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module AccessWatch
|
2
|
+
class RackLogger
|
3
|
+
attr_reader :app, :client
|
4
|
+
|
5
|
+
def initialize(app, config)
|
6
|
+
@app, @client = app, AccessWatch::Client.new(config)
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
started_at = Time.now.utc
|
11
|
+
status, headers, body = app.call(env)
|
12
|
+
record(env, status, started_at, Time.now.utc)
|
13
|
+
[status, headers, body]
|
14
|
+
end
|
15
|
+
|
16
|
+
def record(env, status, started_at, finished_at)
|
17
|
+
post_request(
|
18
|
+
time: started_at.iso8601(3),
|
19
|
+
address: env["REMOTE_ADDR"],
|
20
|
+
request: {
|
21
|
+
protocol: env["HTTP_VERSION"],
|
22
|
+
method: env["REQUEST_METHOD"],
|
23
|
+
scheme: env["rack.url_scheme"],
|
24
|
+
host: env["HTTP_HOST"],
|
25
|
+
port: env["SERVER_PORT"],
|
26
|
+
url: env["ORIGINAL_FULLPATH"],
|
27
|
+
headers: extract_http_headers(env),
|
28
|
+
},
|
29
|
+
response: {status: status},
|
30
|
+
context: {
|
31
|
+
execution_time: finished_at - started_at,
|
32
|
+
memory_usage: memory_usage_in_bytes,
|
33
|
+
},
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
#######################
|
38
|
+
### Private methods ###
|
39
|
+
#######################
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def extract_http_headers(headers)
|
44
|
+
headers.reduce({}) do |hash, (name, value)|
|
45
|
+
if name.index("HTTP_") == 0 && name != "HTTP_COOKIE"
|
46
|
+
hash[format_header_name(name)] = value
|
47
|
+
end
|
48
|
+
hash
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def format_header_name(name)
|
53
|
+
name.sub(/^HTTP_/, '').sub("_", " ").titleize.sub(" ", "-")
|
54
|
+
end
|
55
|
+
|
56
|
+
def post_request(data)
|
57
|
+
post_async("log".freeze, data)
|
58
|
+
end
|
59
|
+
|
60
|
+
def post_async(path, data)
|
61
|
+
Thread.new { client.post(path, data) }
|
62
|
+
end
|
63
|
+
|
64
|
+
def memory_usage_in_bytes
|
65
|
+
linux_process_memory_usage_in_bytes(Process.pid)
|
66
|
+
end
|
67
|
+
|
68
|
+
def linux_process_status(pid)
|
69
|
+
path = "/proc/#{pid}/status"
|
70
|
+
return unless File.readable?(path)
|
71
|
+
File.read(path).split("\n").reduce({}) do |hash, line|
|
72
|
+
name, value = line.split(":")
|
73
|
+
hash[name] = value.strip
|
74
|
+
hash
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
MEMORY_CONVERSIONS = {"kb" => 1024, "mb" => 1024 * 1024, "gb" => 1024 * 1024 * 1024}
|
79
|
+
|
80
|
+
def linux_process_memory_usage_in_bytes(pid)
|
81
|
+
return unless status = linux_process_status(pid)
|
82
|
+
value, unit = status["VmRSS"].split
|
83
|
+
value.to_i * MEMORY_CONVERSIONS[unit.downcase]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module AccessWacth
|
2
|
+
class RailsLoader
|
3
|
+
def self.start
|
4
|
+
return if !defined?(Rails)
|
5
|
+
Rails::Railtie.initializer "access_watch.detect_config_file" do
|
6
|
+
if (path = Rails.root.join("config/access_watch.yml")).exist?
|
7
|
+
if config = AccessWacth::RailsLoader.load_config_file(path)[Rails.env]
|
8
|
+
Rails.application.config.middleware.use(AccessWatch::RackLogger, config.symbolize_keys)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.load_config_file(path)
|
15
|
+
YAML.load(ERB.new(path.read).result)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/access_watch_rails.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: access_watch_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexis Bernard
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.0.
|
47
|
+
version: 0.0.5
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.0.
|
54
|
+
version: 0.0.5
|
55
55
|
description: A Rails library to log and analyse Rails HTTP requests using the Access
|
56
56
|
Watch cloud service.
|
57
57
|
email:
|
@@ -64,6 +64,8 @@ files:
|
|
64
64
|
- README.md
|
65
65
|
- access_watch_rails.gemspec
|
66
66
|
- lib/access_watch/logger.rb
|
67
|
+
- lib/access_watch/rack_logger.rb
|
68
|
+
- lib/access_watch/rails_loader.rb
|
67
69
|
- lib/access_watch/rails_version.rb
|
68
70
|
- lib/access_watch_rails.rb
|
69
71
|
homepage: https://access.watch/
|