db_log_tag 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bd902bdce242a671355a18146acde9967482666ad689a2ca51e961b08d0714de
4
+ data.tar.gz: 4ee6cc7a5a096829d98a1cbdc40251aa8d5c411a02ec838e9e26160a4a5b04fc
5
+ SHA512:
6
+ metadata.gz: 3f6c7db7eeffca09b74c4258e7c7f7fde486c835c124d8d63b4cf9f1b6e0c922669dbf63bce3c7d7b483c6f32568efcd49fbaae1289e18ac5f42fb08f7514928
7
+ data.tar.gz: cb93a42802989964abeb42441699bd02b7109e1348825f71efcf671c666b6781ee4e33f9476e99c17439bce58fdd8852a64cb07babe9aed8999a57bb4b534d5c
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DbLogTag
4
+ module Colors
5
+ module_function
6
+
7
+ def colorize?
8
+ ActiveSupport::LogSubscriber.colorize_logging
9
+ end
10
+
11
+ # TODO: support more colors ?
12
+ def get_color_code(color)
13
+ "ActiveRecord::LogSubscriber::#{color.to_s.upcase}".constantize
14
+ end
15
+
16
+ FONT_MODE = {
17
+ bold: 1,
18
+ italic: 3,
19
+ underline: 4,
20
+ }
21
+ CLEAR = "\e[0m".freeze
22
+
23
+ def get_font_code(font_mode)
24
+ font_mode ? "\e[#{FONT_MODE[font_mode]}m" : ""
25
+ end
26
+
27
+ def set_color(text, color, font_mode)
28
+ return text if color.nil? || !colorize?
29
+
30
+ color = get_color_code(color) if color.is_a?(Symbol)
31
+ weight = get_font_code(font_mode)
32
+ "#{weight}#{color}#{text}#{CLEAR}"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DbLogTag
4
+ class Configuration
5
+ attr_reader :envs
6
+
7
+ def initialize
8
+ reset
9
+ end
10
+
11
+ def reset
12
+ DbLogTag::MultipleDb.reset
13
+ end
14
+
15
+ def enable_environment=(envs)
16
+ DbLogTag.set_enable_environment(envs)
17
+ end
18
+
19
+ def db_tag(clazz = nil, **options, &block)
20
+ DbLogTag::MultipleDb.set_db_tag(clazz, block, **options)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module ActiveRecord::Querying
5
+ delegate :log_tag, to: :all
6
+ end
7
+
8
+ class Relation
9
+ Tags_Regex = /:tag:(.+):tag:/
10
+ Empty_Annotation = /\/\*\s*\*\//
11
+
12
+ attr_accessor :log_tags
13
+
14
+ def log_tag(tag_name=nil, **options)
15
+ return self unless DbLogTag.enable?
16
+
17
+ if block_given?
18
+ tag_name = yield(
19
+ klass.connection_pool.db_config.name,
20
+ ActiveRecord::Base.current_shard,
21
+ ActiveRecord::Base.current_role
22
+ )
23
+ end
24
+
25
+ tag_color = options.dig(:color)
26
+ tag_font = options.dig(:font) || :bold
27
+ tag_name = DbLogTag::Colors.set_color(tag_name, tag_color, tag_font) unless tag_color.nil?
28
+ self.annotate_values += [":tag:#{tag_name}:tag:"]
29
+
30
+ self
31
+ end
32
+
33
+ def remove_log_tags
34
+ self.annotate_values = self.annotate_values.reject do |annotate|
35
+ annotate.start_with?(":tag:")
36
+ end
37
+ self
38
+ end
39
+ end
40
+ end
41
+
@@ -0,0 +1,12 @@
1
+ module DbLogTag
2
+ module_function
3
+
4
+ def set_enable_environment(envs)
5
+ @@envs = envs.map(&:to_s)
6
+ end
7
+
8
+ def enable?
9
+ @@envs ||= ["development", "test"]
10
+ @@envs.include?(ENV["RAILS_ENV"])
11
+ end
12
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DbLogTag
4
+ module MultipleDb
5
+ module_function
6
+
7
+ def db_tags
8
+ @@db_tags ||= {
9
+ nil => {
10
+ proc: lambda { |db, shard, role| "[#{db}|#{shard}|#{role}]" }
11
+ }
12
+ }
13
+ end
14
+
15
+ def set_db_tag(clazz, format_tag_proc, **options)
16
+ tag_config = {
17
+ proc: format_tag_proc,
18
+ **options
19
+ }
20
+
21
+ if clazz.nil?
22
+ db_tags[nil] = tag_config
23
+ elsif clazz.is_a?(String) or clazz.is_a?(Symbol)
24
+ db_tags[clazz.to_s.classify] = tag_config
25
+ end
26
+ end
27
+
28
+ def reset
29
+ @@db_tags = nil
30
+ end
31
+
32
+ def db_info(clazz)
33
+ return unless db_tag_config = (db_tags[clazz] || db_tags[nil])
34
+
35
+ clazz_const = clazz.constantize
36
+ db_info_tag = db_tag_config[:proc].call(
37
+ clazz_const.connection_pool.db_config.name,
38
+ clazz_const.current_shard,
39
+ clazz_const.current_role
40
+ )
41
+
42
+ DbLogTag::Colors.set_color(db_info_tag, db_tag_config[:color], db_tag_config[:font] || :bold)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DbLogTag
4
+ # helper method to create refinement module
5
+ # that add refinement tag to all queries be called on refinement's scope
6
+ #
7
+ # ex:
8
+ # class PersonJob
9
+ # using DbLogTag.refinement_tag { |db, shard, role| "PersonJob" }
10
+ #
11
+ # now all queries in this job
12
+ # will be automatically prepend refinement tag "PersonJob"
13
+ #
14
+ def self.refinement_tag(refinement_proc, **options)
15
+ return Module.new {} unless DbLogTag.enable?
16
+
17
+ # init an anonymous module
18
+ # that will be `using`
19
+ Module.new do
20
+ refine ActiveRecord::Base.singleton_class do
21
+ # decorating all querying methods
22
+ # to add log_tag before call the origin query method
23
+ (ActiveRecord::Querying::QUERYING_METHODS + [:all]).each do |q|
24
+ define_method(q) do |*args, &block|
25
+ log_tag(**options) do |db, shard, role|
26
+ refinement_proc.call(db, shard, role)
27
+ end.send(q, *args, &block)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
data/lib/db_log_tag.rb ADDED
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "db_log_tag/enable"
4
+ require_relative "db_log_tag/colors"
5
+ require_relative "db_log_tag/dynamic"
6
+ require_relative "db_log_tag/refinement"
7
+ require_relative "db_log_tag/multiple_db"
8
+ require_relative "db_log_tag/configuration"
9
+
10
+ require_relative "rails/generators/db_log_tag/install_generator"
11
+
12
+ module DbLogTag
13
+ extend ActiveSupport::Concern
14
+
15
+ # global setting
16
+ class << self
17
+ def configuration
18
+ @configuration ||= DbLogTag::Configuration.new
19
+ end
20
+
21
+ def config
22
+ configuration.reset
23
+ yield(configuration)
24
+ end
25
+ end
26
+
27
+ included do
28
+ alias_method :origin_sql, :sql
29
+ def sql(event)
30
+ if DbLogTag.enable?
31
+ begin
32
+ db_log_tags(event)
33
+ parse_annotations_as_dynamic_tags(event)
34
+ rescue
35
+ end
36
+ end
37
+
38
+ origin_sql(event)
39
+ end
40
+
41
+ private
42
+
43
+ def parse_annotations_as_dynamic_tags(event)
44
+ tags = event.payload[:sql].scan(ActiveRecord::Relation::Tags_Regex).map(&:first).join(" ")
45
+
46
+ unless should_ignore_log?(event) || tags.nil?
47
+ event.payload[:name] = "#{tags} #{event.payload[:name]}"
48
+ end
49
+
50
+ event.payload[:sql] = event.payload[:sql].gsub(ActiveRecord::Relation::Tags_Regex, "")
51
+ # still keep normal annotations
52
+ event.payload[:sql] = event.payload[:sql].gsub(ActiveRecord::Relation::Empty_Annotation, "")
53
+ end
54
+
55
+ def db_log_tags(event)
56
+ return if should_ignore_log?(event)
57
+
58
+ clazz, _ = event.payload[:name].split(" ")
59
+ _db_info = DbLogTag::MultipleDb.db_info(clazz)
60
+ event.payload[:name] = "#{_db_info} #{event.payload[:name]}"
61
+ end
62
+
63
+ def should_ignore_log?(event)
64
+ ActiveRecord::LogSubscriber::IGNORE_PAYLOAD_NAMES.include?(event.payload[:name])
65
+ end
66
+ end
67
+ end
68
+
69
+ ActiveSupport.on_load(:active_record) do
70
+ ActiveRecord::LogSubscriber.send(:include, DbLogTag)
71
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ require "rails/generators"
3
+
4
+ module DbLogTag
5
+ class InstallGenerator < ::Rails::Generators::Base
6
+ source_root File.expand_path("../templates", __FILE__)
7
+
8
+ def create_initializer
9
+ copy_file "initializer.rb", "config/initializers/db_log_tag.rb"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ DbLogTag.config do |config|
2
+ # config.enable_environment = [:development, :test]
3
+
4
+ # # default for all
5
+ # config.db_tag do |db, shard, role|
6
+ # "[#{db}|#{shard}|#{role}]"
7
+ # end
8
+
9
+ # # for only User
10
+ # config.db_tag :user, color: :red do |db, shard, role|
11
+ # "[#{db}|#{shard}|#{role}]"
12
+ # end
13
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: db_log_tag
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Lam Phan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-03-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '6.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '6.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Allow to prepend prefix tags before query logs to track name, shard and
70
+ role of the database.
71
+ email: theforestvn88@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - lib/db_log_tag.rb
77
+ - lib/db_log_tag/colors.rb
78
+ - lib/db_log_tag/configuration.rb
79
+ - lib/db_log_tag/dynamic.rb
80
+ - lib/db_log_tag/enable.rb
81
+ - lib/db_log_tag/multiple_db.rb
82
+ - lib/db_log_tag/refinement.rb
83
+ - lib/rails/generators/db_log_tag/install_generator.rb
84
+ - lib/rails/generators/db_log_tag/templates/initializer.rb
85
+ homepage: https://github.com/theforestvn88/rails_db_log_tag
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubygems_version: 3.5.4
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: rails database log tags
108
+ test_files: []