db_log_tag 0.0.1

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 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: []