google_logger 1.0.0
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 +7 -0
- data/lib/google_logger.rb +114 -0
- data/lib/google_logger/configuration.rb +58 -0
- data/lib/google_logger/controller_logging.rb +32 -0
- data/lib/google_logger/loggers/base.rb +13 -0
- data/lib/google_logger/loggers/cloud_logger.rb +42 -0
- data/lib/google_logger/loggers/local_logger.rb +44 -0
- data/lib/google_logger/params_replacer.rb +32 -0
- data/lib/google_logger/version.rb +5 -0
- metadata +86 -0
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,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
|
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: []
|