google_logger 1.0.0

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: 6d992358263779aad83ebfcc34161a69d2ccad81ac6dba67dd36ac110a2b5d3c
4
+ data.tar.gz: 34612d6398a35047a3bba53fc83f59afd0ea58b84226c8b60f2c572c63a6b3df
5
+ SHA512:
6
+ metadata.gz: d54e6e687f4afb7059bb366b198cd53ffc8a19882a88dda84d39efbd637eb77fced4a963a2df7c76e39612e5d9b2469eab8740b74f1c327fcb906863a5c19272
7
+ data.tar.gz: 11509739cfacf03d16a94722b63527d6d971c8ffd3b0be3df9c95d25026e45ff8c917c112aacfd90d94ca0c8e27eb57f0d7288a5e06b863aa72188e7f3a39f56
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'stackdriver'
4
+ require 'google_logger/version'
5
+ require 'google_logger/configuration'
6
+ require 'google_logger/loggers/cloud_logger'
7
+ require 'google_logger/loggers/local_logger'
8
+ require 'google_logger/loggers/base'
9
+ require 'google_logger/controller_logging'
10
+ require 'google_logger/params_replacer'
11
+
12
+ # Main module which should serve as an interface to all functionalities
13
+ module GoogleLogger
14
+ class Error < StandardError; end
15
+
16
+ class InvalidConfigurationError < Error; end
17
+
18
+ class << self
19
+ attr_writer :configuration
20
+
21
+ # Returns GoogleLogger configuration
22
+ #
23
+ # @return [GoogleLogger::Configuration] current GoogleLogger configuration
24
+ def configuration
25
+ @configuration ||= Configuration.new
26
+ end
27
+
28
+ # Yields the cofiguration class
29
+ #
30
+ # @yield [GoogleLogger::Configuration] current GoogleLogger configuration
31
+ #
32
+ # @return [GoogleLogger::Configuration] GoogleLogger configuration with assigned values
33
+ def configure
34
+ yield(configuration) if block_given?
35
+
36
+ configuration.validate!
37
+
38
+ configuration
39
+ end
40
+
41
+ # Creates a new entry
42
+ #
43
+ # @param [String, Hash] payload content of the log
44
+ # @param [String] log_name log_name which can be used to filter logs
45
+ # @param [Symbol] severity severity of the log
46
+ #
47
+ # return [Boolean] `true` if the entry was successfully written
48
+ def create_entry(payload, log_name: 'default_log', severity: :DEFAULT)
49
+ logger_instance = logger
50
+ entry = logger_instance.build_entry(payload, log_name: log_name, severity: severity)
51
+ logger_instance.write_entry(entry)
52
+ end
53
+
54
+ # Creates a new entry for an exception which includes exception message, class and backtrace
55
+ #
56
+ # @param [StandardError] exception exception to be logged
57
+ #
58
+ # return [Boolean] `true` if the entry was successfully written
59
+ def log_exception(exception)
60
+ payload = {
61
+ message: exception.message,
62
+ exception: exception.class.name,
63
+ bactrace: exception.backtrace&.first(5)
64
+ }
65
+
66
+ create_entry(payload, log_name: 'error', severity: :ERROR)
67
+ rescue StandardError => e
68
+ log_google_logger_error(e)
69
+ end
70
+
71
+ # Creates a new entry for a controller request, the entry includes params,
72
+ # request URL, client ip address and http method
73
+ #
74
+ # @param [ActionDispatch::Request] request request to be logged
75
+ # @param [ActionController::StrongParameters] params parameters to be logged
76
+ #
77
+ # return [Boolean] `true` if the entry was successfully written
78
+ def log_request(request, params)
79
+ payload = {
80
+ params: params,
81
+ original_url: request.original_url,
82
+ ip: request.ip,
83
+ method: request.method
84
+ }
85
+
86
+ create_entry(payload, log_name: 'request', severity: :INFO)
87
+ rescue StandardError => e
88
+ log_google_logger_error(e)
89
+ end
90
+
91
+ # Returns the currently used logger
92
+ #
93
+ # @return [Object] GoogleLogger::Logger by default, local logger if `loc_locally` is set to true
94
+ def logger
95
+ if configuration.log_locally
96
+ Loggers::LocalLogger.new
97
+ else
98
+ Loggers::CloudLogger.new
99
+ end
100
+ end
101
+
102
+ # Log gem errors locally if local_logger is present
103
+ #
104
+ # @param [StandardError] exception the error that will be logged
105
+ def log_google_logger_error(exception)
106
+ local_logger = GoogleLogger.configuration.local_logger
107
+ local_logger.error "GOOGLE_LOGGER ERROR: #{exception.inspect}" if local_logger.present?
108
+ end
109
+
110
+ def deep_replace_secret_params(params)
111
+ ParamsReplacer.deep_replace_secret_params(params)
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GoogleLogger
4
+ class Configuration
5
+ attr_accessor(*%i[
6
+ async
7
+ resource_type
8
+ resource_labels
9
+ secret_params
10
+ secret_param_value
11
+ project_id
12
+ credentials
13
+ log_locally
14
+ local_logger
15
+ ])
16
+
17
+ # Creates a new instance with default configuration values
18
+ def initialize
19
+ @async = true
20
+ @resource_type = 'gae_app'
21
+ @resource_labels = {}
22
+ @secret_params = %i[password]
23
+ @secret_param_value = '<SECRET_PARAM>'
24
+ @log_locally = false
25
+ end
26
+
27
+ def validate!
28
+ if @log_locally
29
+ validate_local_logger
30
+ else
31
+ validate_credentials
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def validate_local_logger
38
+ raise_invalid!('"local_logger" must be provided if "log_locally" is set to "true"') if local_logger.nil?
39
+
40
+ log_levels = GoogleLogger::Loggers::LocalLogger::SEVERITY_MAPPING.values.uniq + [:unknown]
41
+
42
+ # make sure the logger responds to logger methods
43
+ log_levels.each do |log_level|
44
+ raise_invalid!("\"local_logger\" must respond to \"#{log_level}\"") unless local_logger.respond_to?(log_level)
45
+ end
46
+ end
47
+
48
+ def validate_credentials
49
+ return unless @project_id.nil? || @project_id == '' || @credentials.nil? || @credentials == ''
50
+
51
+ raise_invalid!('"project_id" and "credentials" cannot be blank')
52
+ end
53
+
54
+ def raise_invalid!(message)
55
+ raise InvalidConfigurationError, message
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+
5
+ module GoogleLogger
6
+ module ControllerLogging
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ protected
11
+
12
+ # Logs the request and any uncaught exceptions, acts as an `around_action` filter.
13
+ # Exceptions are propagated so that they can be caught in the application.
14
+ def log_request_to_google
15
+ GoogleLogger.log_request(request, google_log_params)
16
+ yield
17
+ rescue StandardError => e
18
+ GoogleLogger.log_exception(e)
19
+ raise
20
+ end
21
+
22
+ # Returns params which should be logged, secret params have their value hidden before being logged
23
+ #
24
+ # @return [Hash] params hash with secret values hidden
25
+ def google_log_params
26
+ params_to_log = params.to_unsafe_h
27
+ GoogleLogger.deep_replace_secret_params(params_to_log)
28
+ params_to_log
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GoogleLogger
4
+ module Loggers
5
+ class Base
6
+ protected
7
+
8
+ def configuration
9
+ GoogleLogger.configuration
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base'
4
+
5
+ module GoogleLogger
6
+ module Loggers
7
+ class CloudLogger < Base
8
+ # Creates a new logger with project_id and credentials specified in configuration
9
+ def initialize
10
+ @project = Google::Cloud::Logging.new(
11
+ project_id: configuration.project_id,
12
+ credentials: configuration.credentials
13
+ )
14
+ end
15
+
16
+ # Builds a new entry
17
+ #
18
+ # @param [String, Hash] payload content of the log
19
+ # @param [String] log_name log_name which can be used to filter logs
20
+ # @param [Symbol] severity severity of the log
21
+ #
22
+ # @return [Google::Cloud::Logging::Entry] entry with payload and default resource configuration
23
+ def build_entry(payload, log_name: 'default_log', severity: :DEFAULT)
24
+ entry = @project.entry(payload: payload, log_name: log_name, severity: severity, timestamp: Time.now)
25
+ entry.resource.type = configuration.resource_type
26
+ entry.resource.labels = configuration.resource_labels
27
+ entry
28
+ end
29
+
30
+ # Writes an entry to google cloud
31
+ #
32
+ # @param [Google::Cloud::Logging::Entry] entry entry to be written to google cloud
33
+ # defaults to configuration value
34
+ #
35
+ # return [Boolean] `true` if the entry was successfully written
36
+ def write_entry(entry)
37
+ log_writer = configuration.async ? @project : @project.async_writer
38
+ log_writer.write_entries(entry)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base'
4
+
5
+ module GoogleLogger
6
+ module Loggers
7
+ class LocalLogger < Base
8
+ SEVERITY_MAPPING = {
9
+ DEFAULT: :info,
10
+ DEBUG: :debug,
11
+ INFO: :info,
12
+ NOTICE: :info,
13
+ WARNING: :warn,
14
+ ERROR: :error,
15
+ CRITICAL: :fatal,
16
+ ALERT: :fatal,
17
+ EMERGENCY: :fatal
18
+ }.freeze
19
+
20
+ # Builds a new entry
21
+ #
22
+ # @param [String, Hash] payload content of the log
23
+ # @param [Hash] entry_args arguments which would normally be passed to google entry
24
+ #
25
+ # @return [Hash] entry with payload and default resource configuration
26
+ def build_entry(payload, entry_args = {})
27
+ entry_args[:payload] = payload
28
+ entry_args
29
+ end
30
+
31
+ # Writes an entry to google cloud
32
+ #
33
+ # @param [Hash] entry entry to be written to google cloud
34
+ #
35
+ # return [Boolean] `true` if the entry was successfully written
36
+ def write_entry(entry)
37
+ log_level = SEVERITY_MAPPING[entry[:severity]] || :unknown
38
+ configuration.local_logger.public_send(log_level, entry.inspect)
39
+
40
+ true
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GoogleLogger
4
+ class ParamsReplacer
5
+ def deep_replace_secret_params(arg)
6
+ case arg
7
+ when Hash
8
+ deep_replace_params_in_hash(arg)
9
+ when Array
10
+ deep_replace_params_in_array(arg)
11
+ end
12
+ end
13
+
14
+ def deep_replace_params_in_hash(hash)
15
+ hash.each do |key, value|
16
+ if GoogleLogger.configuration.secret_params.include?(key.to_sym)
17
+ hash[key] = GoogleLogger.configuration.secret_param_value
18
+ else
19
+ deep_replace_secret_params(value)
20
+ end
21
+ end
22
+ end
23
+
24
+ def deep_replace_params_in_array(array)
25
+ array.each { |item| deep_replace_secret_params(item) }
26
+ end
27
+
28
+ class << self
29
+ delegate :deep_replace_secret_params, to: :new
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GoogleLogger
4
+ VERSION = '1.0.0'
5
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: google_logger
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jan Hric
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-07-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.2.4.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.2.4.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: stackdriver
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.21.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.21.1
41
+ description: |-
42
+ Provides convenient methods to log all controller requests
43
+ and also provides a wrapper class which simplifies custom logging.
44
+ email:
45
+ - hric95@seznam.cz
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - lib/google_logger.rb
51
+ - lib/google_logger/configuration.rb
52
+ - lib/google_logger/controller_logging.rb
53
+ - lib/google_logger/loggers/base.rb
54
+ - lib/google_logger/loggers/cloud_logger.rb
55
+ - lib/google_logger/loggers/local_logger.rb
56
+ - lib/google_logger/params_replacer.rb
57
+ - lib/google_logger/version.rb
58
+ homepage: https://github.com/panter/google_logger
59
+ licenses:
60
+ - MIT
61
+ metadata:
62
+ homepage_uri: https://github.com/panter/google_logger
63
+ source_code_uri: https://github.com/panter/google_logger
64
+ post_install_message:
65
+ rdoc_options: []
66
+ require_paths:
67
+ - lib
68
+ - lib/google_logger
69
+ - lib/google_logger/loggers
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 2.5.0
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ requirements: []
81
+ rubyforge_project:
82
+ rubygems_version: 2.7.6.2
83
+ signing_key:
84
+ specification_version: 4
85
+ summary: Provides a simple interface to write logs to the google cloud platform.
86
+ test_files: []