queryable_logs 0.1.0 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23b8ae959b8c34959d0db89adfcba5e50b38011264947b4de53f626bd4d1bb64
4
- data.tar.gz: 1f9aeb0b1b2b5b8c40f0bb4245859ed06d72066f45abf6aac885f295cf0e6964
3
+ metadata.gz: 8022ed8aff78bfff25367198a3a95f95bfddb4b8c4596276e85634efe01cea67
4
+ data.tar.gz: 3f8d87a7bc9702831b6f0f4a4b0e4e90a0d025b680f422dbc4bf8cd4e5560958
5
5
  SHA512:
6
- metadata.gz: 13c600df1ba652861169e0b9495dd1d98a71723d8e663a8b219a4c8ad872f04d906453e593cfc70e3b8ef7d8d927bdca53666c08fa268b0cd0637cf3736dcc41
7
- data.tar.gz: 6cd4fb3c21e7e4e513e6df4a7aad840f34cb9512d5d79cc4d7004f83aa8896d89d66ad7ebb27dba3084e66421916c86c0e2ebbc856fd2062b84b2f3018db142a
6
+ metadata.gz: 6bd153ba202ae69f51fbbee6b6a3a5828c8c0c68321b8d4519ce08f526261a5035a2b49d64e8077cfc84e21a6f40f1d055d26e08d2ae25c387b65335b84ce9da
7
+ data.tar.gz: 0ccda5b146fdde3f8f9fa7276516213616b271840f76f69e6bd0f3c3fd92258d2a42b6e3bb9db3b6262a26682de172d3ca8f76c4625d2f255e80f34b0d4e59fd
data/Gemfile.lock CHANGED
@@ -1,105 +1,31 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- queryable_logs (0.1.0)
5
- rails (>= 4)
4
+ queryable_logs (0.1.2)
5
+ activerecord (>= 4)
6
+ activesupport (>= 4)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
9
10
  specs:
10
- actioncable (5.2.8.1)
11
- actionpack (= 5.2.8.1)
12
- nio4r (~> 2.0)
13
- websocket-driver (>= 0.6.1)
14
- actionmailer (5.2.8.1)
15
- actionpack (= 5.2.8.1)
16
- actionview (= 5.2.8.1)
17
- activejob (= 5.2.8.1)
18
- mail (~> 2.5, >= 2.5.4)
19
- rails-dom-testing (~> 2.0)
20
- actionpack (5.2.8.1)
21
- actionview (= 5.2.8.1)
22
- activesupport (= 5.2.8.1)
23
- rack (~> 2.0, >= 2.0.8)
24
- rack-test (>= 0.6.3)
25
- rails-dom-testing (~> 2.0)
26
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
27
- actionview (5.2.8.1)
28
- activesupport (= 5.2.8.1)
29
- builder (~> 3.1)
30
- erubi (~> 1.4)
31
- rails-dom-testing (~> 2.0)
32
- rails-html-sanitizer (~> 1.0, >= 1.0.3)
33
- activejob (5.2.8.1)
34
- activesupport (= 5.2.8.1)
35
- globalid (>= 0.3.6)
36
11
  activemodel (5.2.8.1)
37
12
  activesupport (= 5.2.8.1)
38
13
  activerecord (5.2.8.1)
39
14
  activemodel (= 5.2.8.1)
40
15
  activesupport (= 5.2.8.1)
41
16
  arel (>= 9.0)
42
- activestorage (5.2.8.1)
43
- actionpack (= 5.2.8.1)
44
- activerecord (= 5.2.8.1)
45
- marcel (~> 1.0.0)
46
17
  activesupport (5.2.8.1)
47
18
  concurrent-ruby (~> 1.0, >= 1.0.2)
48
19
  i18n (>= 0.7, < 2)
49
20
  minitest (~> 5.1)
50
21
  tzinfo (~> 1.1)
51
22
  arel (9.0.0)
52
- builder (3.2.4)
53
23
  concurrent-ruby (1.2.2)
54
- crass (1.0.6)
55
24
  diff-lcs (1.5.0)
56
- erubi (1.12.0)
57
- globalid (0.4.2)
58
- activesupport (>= 4.2.0)
59
25
  i18n (1.14.1)
60
26
  concurrent-ruby (~> 1.0)
61
- loofah (2.21.1)
62
- crass (~> 1.0.2)
63
- nokogiri (>= 1.5.9)
64
- mail (2.7.1)
65
- mini_mime (>= 0.1.1)
66
- marcel (1.0.2)
67
- method_source (1.0.0)
68
- mini_mime (1.1.2)
69
- mini_portile2 (2.4.0)
70
27
  minitest (5.15.0)
71
- nio4r (2.5.9)
72
- nokogiri (1.10.10)
73
- mini_portile2 (~> 2.4.0)
74
- rack (2.2.8)
75
- rack-test (2.1.0)
76
- rack (>= 1.3)
77
- rails (5.2.8.1)
78
- actioncable (= 5.2.8.1)
79
- actionmailer (= 5.2.8.1)
80
- actionpack (= 5.2.8.1)
81
- actionview (= 5.2.8.1)
82
- activejob (= 5.2.8.1)
83
- activemodel (= 5.2.8.1)
84
- activerecord (= 5.2.8.1)
85
- activestorage (= 5.2.8.1)
86
- activesupport (= 5.2.8.1)
87
- bundler (>= 1.3.0)
88
- railties (= 5.2.8.1)
89
- sprockets-rails (>= 2.0.0)
90
- rails-dom-testing (2.1.1)
91
- activesupport (>= 5.0.0)
92
- minitest
93
- nokogiri (>= 1.6)
94
- rails-html-sanitizer (1.5.0)
95
- loofah (~> 2.19, >= 2.19.1)
96
- railties (5.2.8.1)
97
- actionpack (= 5.2.8.1)
98
- activesupport (= 5.2.8.1)
99
- method_source
100
- rake (>= 0.8.7)
101
- thor (>= 0.19.0, < 2.0)
102
- rake (10.5.0)
28
+ rake (13.2.1)
103
29
  rspec (3.12.0)
104
30
  rspec-core (~> 3.12.0)
105
31
  rspec-expectations (~> 3.12.0)
@@ -113,29 +39,18 @@ GEM
113
39
  diff-lcs (>= 1.2.0, < 2.0)
114
40
  rspec-support (~> 3.12.0)
115
41
  rspec-support (3.12.0)
116
- sprockets (3.7.2)
117
- concurrent-ruby (~> 1.0)
118
- rack (> 1, < 3)
119
- sprockets-rails (3.2.2)
120
- actionpack (>= 4.0)
121
- activesupport (>= 4.0)
122
- sprockets (>= 3.0.0)
123
- thor (1.2.2)
124
42
  thread_safe (0.3.6)
125
43
  tzinfo (1.2.11)
126
44
  thread_safe (~> 0.1)
127
- websocket-driver (0.7.6)
128
- websocket-extensions (>= 0.1.0)
129
- websocket-extensions (0.1.5)
130
45
 
131
46
  PLATFORMS
132
47
  ruby
133
48
 
134
49
  DEPENDENCIES
135
- bundler (~> 1.17)
50
+ bundler (~> 2)
136
51
  queryable_logs!
137
- rake (~> 10.0)
52
+ rake (>= 13.0)
138
53
  rspec (~> 3.0)
139
54
 
140
55
  BUNDLED WITH
141
- 1.17.3
56
+ 2.6.7
data/README.md CHANGED
@@ -21,12 +21,54 @@ Or install it yourself as:
21
21
  Run
22
22
  `rails g queryable_logs`.
23
23
 
24
- This will generate a migration file and an initializer file. queryable_logs also logs the current user id. Let the gem know which method you are using to get the current user. Default is set to `current_user`.
24
+ This will generate a migration file.
25
+ ```ruby
26
+ class CreateTrailLogs < ActiveRecord::Migration
27
+ def change
28
+ create_table :trail_logs do |t|
29
+ t.integer :user_id
30
+ t.string :ip_address
31
+ t.string :controller
32
+ t.string :action
33
+ t.string :format
34
+ t.string :http_verb
35
+ t.text :params_hash
36
+ t.datetime :logged_at
37
+ t.string :response_code
38
+ t.string :request_url
39
+ t.string :sig
40
+
41
+ t.timestamps null: false
42
+ end
43
+ end
44
+ end
45
+ ```
46
+ and an initializer file.
47
+ ```ruby
48
+ class Trail
49
+ cattr_accessor :current_user_method, :logger, :saving_logs
50
+ LogFile = Rails.root.join('log', 'trail.log')
51
+ delegate :debug, :info, :warn, :error, :fatal, :to => :logger
52
+ end
53
+
54
+ Trail.logger = Logger.new(Trail::LogFile)
55
+ Trail.logger.level = 'info' # could be debug, info, warn, error or fatal
56
+ Trail.current_user_method = :current_user
57
+ ```
58
+ queryable_logs also logs the current user id. Let the gem know which method you are using to get the current user. Default is set to `current_user`.
59
+
60
+ Finally, include the `QueryableLogs::WriteLog` in the base controller, typically the `ApplicationController`.
61
+ ```ruby
62
+ class ApplicationController < ActionController::Base
63
+ include QueryableLogs::WriteLog
64
+ end
65
+ ```
66
+
67
+ Enter the following task to your crontab `rake parse:logs_to_db`
68
+
69
+ eg: `0 * * * * cd /Users/akshaytakkar/sample_rails_app && /Users/akshaytakkar/.rvm/wrappers/ruby-3.1.0/rake db:parse_log_and_save_trails >> /Users/akshaytakkar/sample_rails_app/log/worker.log 2>&1`
25
70
 
26
- Enter the following task to your crontab
27
- `rake parse:logs_to_db`
28
- eg:
29
- `* * * * * cd /Users/akshaytakkar/sample_rails_app && /Users/akshaytakkar/.rvm/wrappers/ruby-3.1.0/rake db:parse_log_and_save_trails >> /Users/akshaytakkar/sample_rails_app/log/worker.log 2>&1`
71
+ This will run the `rake parse:logs_to_db` rake task every hour and log any errors or output from the task to `worker.log` file.
30
72
 
31
73
  ## Usage
32
74
 
@@ -28,11 +28,6 @@ class QueryableLogsGenerator < Rails::Generators::Base
28
28
  end
29
29
 
30
30
  def self.next_migration_number(dirname)
31
- if ActiveRecord::Base.timestamped_migrations
32
- current_time = Time.now.utc
33
- current_time.strftime("%Y%m%d%H%M%S")
34
- else
35
- "%.3d" % (current_numeric_version(dirname) + 1)
36
- end
31
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
37
32
  end
38
33
  end
@@ -1,10 +1,9 @@
1
1
  class Trail
2
2
  cattr_accessor :current_user_method, :logger, :saving_logs
3
- LogFile = Rails.root.join('log', 'trail.log')
3
+ LogFile = Rails.root.join('log', "trail.log")
4
4
  delegate :debug, :info, :warn, :error, :fatal, :to => :logger
5
5
  end
6
6
 
7
- Trail.logger = Logger.new(Trail::LogFile)
7
+ Trail.logger = Logger.new(Trail::LogFile, 'daily', 7)
8
8
  Trail.logger.level = 'info' # could be debug, info, warn, error or fatal
9
- Trail.current_user_method = :current_user
10
- Trail.saving_logs = false
9
+ Trail.current_user_method = :current_user
@@ -7,7 +7,7 @@ class CreateTrailLogs < ActiveRecord::Migration<%= migration_version %>
7
7
  t.string :action
8
8
  t.string :format
9
9
  t.string :http_verb
10
- t.text :params_hash
10
+ t.json :params_hash
11
11
  t.datetime :logged_at
12
12
  t.string :response_code
13
13
  t.string :request_url
@@ -1,6 +1,8 @@
1
1
  namespace :db do
2
2
  desc "Parse trail log file and save to DB"
3
3
  task :parse_log_and_save_trails => :environment do
4
- QueryableLogs::TrailLog.parse_log_and_save_trails
4
+ file_name = ENV["FILE_NAME"] || "trail.log"
5
+ b = Benchmark.measure { QueryableLogs::TrailLog.parse_log_and_save_trails(file_name) }
6
+ puts "Trail file #{file_name} processed at #{Time.zone.now.strftime('%Y-%m-%d %H:%M')} in: #{'%.4f' % b.total}s"
5
7
  end
6
8
  end
@@ -1,33 +1,14 @@
1
1
  module QueryableLogs
2
2
  class TrailLog < ActiveRecord::Base
3
- serialize :params_hash, JSON
4
-
5
3
  def self.parse_log_and_save_trails(log_file_name="trail.log")
6
- trails_recorded = []
7
- lines = []
8
- bytes_to_read = 0
9
4
  log_file_path = "#{Rails.root}/log/#{log_file_name}"
10
-
11
- begin
12
- File.open(log_file_path, File::RDONLY) do |f|
13
- f.flock(File::LOCK_SH)
14
- bytes_to_read = File.size(log_file_path)
15
- f.flock(File::LOCK_UN)
16
- end
17
- rescue
18
- f.flock(File::LOCK_UN)
19
- return
20
- end
21
-
22
- return if bytes_to_read == 0
23
-
24
- File.open(log_file_path) do |f|
25
- lines = f.read(bytes_to_read).split("\n")
26
- end
5
+ lines = []
6
+ File.open(log_file_path) { |f| f.each_line { |line| lines << line } }
27
7
  lines.each do |line|
28
8
  next if line.match(/\A# Logfile created on/) != nil
29
9
  if m = line.match(/^I, \[(.+?)\] INFO -- : (.*)$/)
30
10
  request_time_and_pid, log_line = m[1..2]
11
+ next if TrailLog.where(sig: request_time_and_pid).count > 0
31
12
  log_line = log_line.sub(/ p:(.*)$/, '')
32
13
  log_params = {"p" => $1}
33
14
  log_params = log_params.merge(Hash[log_line.scan(/(\w+):(\S+)/)])
@@ -49,27 +30,7 @@ module QueryableLogs
49
30
  logged_at: request_time)
50
31
  end
51
32
  end
52
-
53
- if bytes_to_read > 0
54
- log_file_ptr = nil
55
- begin
56
- File.open(log_file_path, "r+") do |f|
57
- f.flock(File::LOCK_EX)
58
- f.seek(bytes_to_read + 1)
59
- fsize = File.size(log_file_path)
60
- buffer = f.read(fsize - bytes_to_read)
61
- f.seek(0)
62
- f.write(buffer)
63
- f.truncate(fsize - bytes_to_read)
64
- f.flock(File::LOCK_UN)
65
- end
66
- rescue Exception => e
67
- puts "msg = #{e.message}"
68
- puts "backtrace = #{e.backtrace}"
69
- log_file_ptr&.flock(File::LOCK_UN)
70
- return
71
- end
72
- end
33
+ QueryableLogs::ParsedTrailLogFile.create(file_name: log_file_name)
73
34
  end
74
35
  end
75
36
  end
@@ -1,3 +1,3 @@
1
1
  module QueryableLogs
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -9,7 +9,7 @@ module QueryableLogs
9
9
  def write_to_trail_log
10
10
  # vid, mid, ip, vrb, url, ctl, act, fmt, res, p (must be last)
11
11
  log_string = "uid:%{user_id} ip:%{ip_address} vrb:%{http_verb} url:%{url} ctl:%{controller} act:%{action} fmt:%{format} res:%{response_code} p:%{params_as_json}" % {
12
- user_id: send(Trail.current_user_method).try(:id) || '',
12
+ user_id: self.respond_to?(Trail.current_user_method) ? send(Trail.current_user_method).try(:id) : '',
13
13
  ip_address: request.remote_ip,
14
14
  http_verb: request.request_method,
15
15
  url: Nokogiri::HTML(request.fullpath).text.strip,
@@ -19,19 +19,8 @@ module QueryableLogs
19
19
  params_as_json: Nokogiri::HTML(params.to_json).text.strip,
20
20
  response_code: response.code
21
21
  }
22
-
23
- log_file_ptr = nil
24
- begin
25
- File.open(JSON.parse(Trail.logger.to_json)["logdev"]["filename"], File::RDWR) do |f|
26
- log_file_ptr = f
27
- f.flock(File::LOCK_EX)
28
- Trail.logger.info(log_string)
29
- f.flock(File::LOCK_UN)
30
- end
31
- rescue Exception => e
32
- puts "something went wrong ->>>>> #{e.message} #{e.backtrace}"
33
- puts "log_string = #{log_string}"
34
- log_file_ptr&.flock(File::LOCK_UN)
22
+
23
+ Trail.logger.info(log_string)
35
24
  end
36
25
  end
37
26
  end
@@ -36,8 +36,9 @@ Gem::Specification.new do |spec|
36
36
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
37
37
  spec.require_paths = ["lib"]
38
38
 
39
- spec.add_runtime_dependency "rails", ">= 4"
40
- spec.add_development_dependency "bundler", "~> 1.17"
41
- spec.add_development_dependency "rake", "~> 10.0"
39
+ spec.add_runtime_dependency "activerecord", ">= 4"
40
+ spec.add_runtime_dependency "activesupport", ">= 4"
41
+ spec.add_development_dependency "bundler", "~> 2"
42
+ spec.add_development_dependency "rake", ">= 13.0"
42
43
  spec.add_development_dependency "rspec", "~> 3.0"
43
44
  end
metadata CHANGED
@@ -1,17 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: queryable_logs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akshay Takkar
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-10 00:00:00.000000000 Z
11
+ date: 2025-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rails
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
15
29
  requirement: !ruby/object:Gem::Requirement
16
30
  requirements:
17
31
  - - ">="
@@ -30,28 +44,28 @@ dependencies:
30
44
  requirements:
31
45
  - - "~>"
32
46
  - !ruby/object:Gem::Version
33
- version: '1.17'
47
+ version: '2'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: '1.17'
54
+ version: '2'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - "~>"
59
+ - - ">="
46
60
  - !ruby/object:Gem::Version
47
- version: '10.0'
61
+ version: '13.0'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - "~>"
66
+ - - ">="
53
67
  - !ruby/object:Gem::Version
54
- version: '10.0'
68
+ version: '13.0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rspec
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -115,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
129
  - !ruby/object:Gem::Version
116
130
  version: '0'
117
131
  requirements: []
118
- rubygems_version: 3.0.4
132
+ rubygems_version: 3.4.1
119
133
  signing_key:
120
134
  specification_version: 4
121
135
  summary: Make logs queryable, just like you would query any other activerecord table