access_watch_rails 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/
|