appengine 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -29
- data/lib/appengine.rb +2 -1
- data/lib/appengine/env.rb +4 -14
- data/lib/appengine/railtie.rb +1 -38
- data/lib/appengine/version.rb +1 -1
- data/test/test_env.rb +5 -25
- metadata +26 -8
- data/lib/appengine/logger.rb +0 -188
- data/test/test_logger.rb +0 -151
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4841b00bed08c35d62dfd337ccd15cf5df775de9
|
4
|
+
data.tar.gz: a3158e01aaccb61471b504d7a66983c24a58a560
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27445f16fa0d99b081992a8ea08427730dc4375b05f7a083763c5e6f9ee338652a6e8798eb47bc5293e51d9a4a22fe3c79322ca934284973826c3f7f6faf5741
|
7
|
+
data.tar.gz: 734a601f646ee785f5af7f9cbdf77af271a6e2bc25ae80abeaad0a8c92a26562462d2be953fa981ea4a04b48b1646c316dc08022658ad4d954e755dc5fb48406
|
data/README.md
CHANGED
@@ -9,7 +9,14 @@ environment.
|
|
9
9
|
|
10
10
|
Currently, it includes:
|
11
11
|
|
12
|
-
*
|
12
|
+
* Automatic Stackdriver instrumentation for Rails apps. This means logs,
|
13
|
+
error reports, and latency traces are reported to the cloud console.
|
14
|
+
* A placeholder for a class that provides app engine environment information
|
15
|
+
such as project ID and VM info.
|
16
|
+
|
17
|
+
Planned for the near future:
|
18
|
+
|
19
|
+
* Streamlined implementation of health checks and other lifecycle hooks.
|
13
20
|
|
14
21
|
For more information on using Google Cloud Platform to deploy Ruby apps,
|
15
22
|
please visit http://cloud.google.com/ruby
|
@@ -27,34 +34,18 @@ may need to include the line:
|
|
27
34
|
require "appengine"
|
28
35
|
|
29
36
|
in your `config/application.rb` file if you aren't already requiring all
|
30
|
-
bundled gems.
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
tools to make that happen.
|
43
|
-
|
44
|
-
If you are using Ruby on Rails, and you do not otherwise customize your
|
45
|
-
Rails logger, then the provided Railtie will direct your logs to the Cloud
|
46
|
-
Console "out of the box". Normally, this is configured to take effect when
|
47
|
-
running in the `production` environment, but you may also configure it for
|
48
|
-
other environments. See the documentation for the `AppEngine::Railtie` class
|
49
|
-
for more details.
|
50
|
-
|
51
|
-
If you are running a different Rack-based framework such as Sinatra, you
|
52
|
-
should install the provided `AppEngine::Logger::Middleware` in your middleware
|
53
|
-
stack. This should be installed instead of the normal `Rack::Logger`. It will
|
54
|
-
automatically create a logger that directs entries to the Cloud Console, and
|
55
|
-
will make it available via the standard `Rack::RACK_LOGGER` key in the Rack
|
56
|
-
environment. You may also create your own logger directly using the
|
57
|
-
`AppEngine::Logger.create()` method.
|
37
|
+
bundled gems.
|
38
|
+
|
39
|
+
## Logging and monitoring
|
40
|
+
|
41
|
+
This library automatically installs the "stackdriver" gem, which instruments
|
42
|
+
your application to report logs, unhandled exceptions, and latency traces to
|
43
|
+
your project's Google Cloud Console. For more information on the application
|
44
|
+
monitoring features of Google App Engine, see:
|
45
|
+
|
46
|
+
* [google-cloud-logging instrumentation](http://googlecloudplatform.github.io/google-cloud-ruby/#/docs/google-cloud-logging/latest/guides/instrumentation)
|
47
|
+
* [google-cloud-error_reporting instrumentation](http://googlecloudplatform.github.io/google-cloud-ruby/#/docs/google-cloud-error_reporting/latest/guides/instrumentation)
|
48
|
+
* [google-cloud-trace instrumentation](http://googlecloudplatform.github.io/google-cloud-ruby/#/docs/google-cloud-trace/latest/guides/instrumentation)
|
58
49
|
|
59
50
|
## Development and support
|
60
51
|
|
data/lib/appengine.rb
CHANGED
data/lib/appengine/env.rb
CHANGED
@@ -16,25 +16,15 @@
|
|
16
16
|
|
17
17
|
module AppEngine
|
18
18
|
|
19
|
-
|
20
|
-
#
|
19
|
+
##
|
20
|
+
# A collection of functions for extracting App Engine environment information.
|
21
21
|
#
|
22
|
-
# A collection of functions for extracting App Engine environment information
|
23
|
-
# from the Rack environment
|
24
|
-
|
25
22
|
module Env
|
26
23
|
|
27
|
-
|
28
|
-
|
29
|
-
# ID was found.
|
30
|
-
|
31
|
-
def self.extract_trace_id(env)
|
32
|
-
trace_context = env['HTTP_X_CLOUD_TRACE_CONTEXT'].to_s
|
33
|
-
return nil if trace_context.empty?
|
34
|
-
return trace_context.sub(/\/.*/, '')
|
24
|
+
def self.app_engine?
|
25
|
+
::ENV["GAE_INSTANCE"] ? true : false
|
35
26
|
end
|
36
27
|
|
37
|
-
|
38
28
|
end
|
39
29
|
|
40
30
|
end
|
data/lib/appengine/railtie.rb
CHANGED
@@ -31,25 +31,7 @@ module AppEngine
|
|
31
31
|
#
|
32
32
|
# === Configuration
|
33
33
|
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
# [<tt>config.appengine.use_cloud_logger</tt>]
|
37
|
-
# Set to true to cause the Rails logger to log to Google Cloud Console.
|
38
|
-
# By default, this is true in the production environment and false in
|
39
|
-
# all other environments. You may override this setting in individual
|
40
|
-
# environment config files.
|
41
|
-
#
|
42
|
-
# [<tt>config.appengine.logfile</tt>]
|
43
|
-
# The path to the log file when <tt>use_cloud_logger</tt> is active.
|
44
|
-
# You should normally leave this as the default when deploying to Google
|
45
|
-
# App Engine, but you may set it to a different path if you want to test
|
46
|
-
# logging in a development environment.
|
47
|
-
#
|
48
|
-
# [<tt>config.appengine.trace_id_var</tt>]
|
49
|
-
# The name of a fiber-local variable to store the current request's trace
|
50
|
-
# ID. This is used to communicate request and trace information between
|
51
|
-
# Rack and the cloud logger. You may change it if you need to control
|
52
|
-
# fiber-local variable names.
|
34
|
+
# This is a placeholder for now.
|
53
35
|
|
54
36
|
class Railtie < ::Rails::Railtie
|
55
37
|
|
@@ -57,25 +39,6 @@ module AppEngine
|
|
57
39
|
|
58
40
|
config.appengine = ::ActiveSupport::OrderedOptions.new
|
59
41
|
|
60
|
-
config.appengine.use_cloud_logger = ::Rails.env.to_s == 'production'
|
61
|
-
config.appengine.logfile = ::AppEngine::Logger::DEFAULT_LOG_FILENAME
|
62
|
-
config.appengine.trace_id_var = ::AppEngine::Logger::DEFAULT_TRACE_ID_VAR
|
63
|
-
|
64
|
-
|
65
|
-
initializer 'google.appengine.logger', before: :initialize_logger do |app|
|
66
|
-
if app.config.appengine.use_cloud_logger
|
67
|
-
app.config.logger = ::AppEngine::Logger.create(
|
68
|
-
logfile: app.config.appengine.logfile,
|
69
|
-
trace_id_var: app.config.appengine.trace_id_var)
|
70
|
-
app.config.log_formatter = app.config.logger.formatter
|
71
|
-
|
72
|
-
app.middleware.insert_before(::Rails::Rack::Logger,
|
73
|
-
::AppEngine::Logger::Middleware,
|
74
|
-
logger: app.config.logger,
|
75
|
-
trace_id_var: app.config.appengine.trace_id_var)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
42
|
# :startdoc:
|
80
43
|
|
81
44
|
end
|
data/lib/appengine/version.rb
CHANGED
data/test/test_env.rb
CHANGED
@@ -23,31 +23,11 @@ module AppEngine
|
|
23
23
|
class TestEnv < ::Minitest::Test # :nodoc:
|
24
24
|
|
25
25
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
def test_extract_trace_id_empty
|
34
|
-
env = {'HTTP_X_CLOUD_TRACE_CONTEXT' => ''}
|
35
|
-
trace_id = Env.extract_trace_id(env)
|
36
|
-
assert_nil(trace_id)
|
37
|
-
end
|
38
|
-
|
39
|
-
|
40
|
-
def test_extract_trace_id_simple
|
41
|
-
env = {'HTTP_X_CLOUD_TRACE_CONTEXT' => 'abcdefg'}
|
42
|
-
trace_id = Env.extract_trace_id(env)
|
43
|
-
assert_equal('abcdefg', trace_id)
|
44
|
-
end
|
45
|
-
|
46
|
-
|
47
|
-
def test_extract_trace_id_with_suffix
|
48
|
-
env = {'HTTP_X_CLOUD_TRACE_CONTEXT' => 'abcdefg/hijk/lmnop'}
|
49
|
-
trace_id = Env.extract_trace_id(env)
|
50
|
-
assert_equal('abcdefg', trace_id)
|
26
|
+
def test_app_engine
|
27
|
+
::ENV["GAE_INSTANCE"] = "instance-123"
|
28
|
+
assert Env.app_engine?
|
29
|
+
::ENV.delete "GAE_INSTANCE"
|
30
|
+
refute Env.app_engine?
|
51
31
|
end
|
52
32
|
|
53
33
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appengine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Tanner
|
@@ -9,22 +9,42 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2017-02-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: stackdriver
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0.4'
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.4.1
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- - "~>"
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0.4'
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.4.1
|
14
34
|
- !ruby/object:Gem::Dependency
|
15
35
|
name: bundler
|
16
36
|
requirement: !ruby/object:Gem::Requirement
|
17
37
|
requirements:
|
18
38
|
- - "~>"
|
19
39
|
- !ruby/object:Gem::Version
|
20
|
-
version: '1.
|
40
|
+
version: '1.14'
|
21
41
|
type: :development
|
22
42
|
prerelease: false
|
23
43
|
version_requirements: !ruby/object:Gem::Requirement
|
24
44
|
requirements:
|
25
45
|
- - "~>"
|
26
46
|
- !ruby/object:Gem::Version
|
27
|
-
version: '1.
|
47
|
+
version: '1.14'
|
28
48
|
- !ruby/object:Gem::Dependency
|
29
49
|
name: minitest
|
30
50
|
requirement: !ruby/object:Gem::Requirement
|
@@ -69,7 +89,7 @@ dependencies:
|
|
69
89
|
version: '4.2'
|
70
90
|
description: The appengine gem is a set of classes, plugins, and tools for integration
|
71
91
|
with Google App Engine. It provides access to the App Engine runtime environment,
|
72
|
-
including logging to the Google Cloud Console and
|
92
|
+
including logging to the Google Cloud Console and interrogation of hosting properties.
|
73
93
|
However, it is not required for deploying your Ruby application to App Engine.
|
74
94
|
email:
|
75
95
|
- adamtanner@google.com
|
@@ -85,11 +105,9 @@ files:
|
|
85
105
|
- Rakefile
|
86
106
|
- lib/appengine.rb
|
87
107
|
- lib/appengine/env.rb
|
88
|
-
- lib/appengine/logger.rb
|
89
108
|
- lib/appengine/railtie.rb
|
90
109
|
- lib/appengine/version.rb
|
91
110
|
- test/test_env.rb
|
92
|
-
- test/test_logger.rb
|
93
111
|
homepage: https://github.com/GoogleCloudPlatform/appengine-ruby
|
94
112
|
licenses:
|
95
113
|
- Apache 2.0
|
@@ -110,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
110
128
|
version: '0'
|
111
129
|
requirements: []
|
112
130
|
rubyforge_project:
|
113
|
-
rubygems_version: 2.
|
131
|
+
rubygems_version: 2.6.8
|
114
132
|
signing_key:
|
115
133
|
specification_version: 4
|
116
134
|
summary: Google App Engine integration tools
|
data/lib/appengine/logger.rb
DELETED
@@ -1,188 +0,0 @@
|
|
1
|
-
# Copyright 2016 Google Inc. All rights reserved.
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at
|
6
|
-
#
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
#
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
# See the License for the specific language governing permissions and
|
13
|
-
# limitations under the License.
|
14
|
-
;
|
15
|
-
|
16
|
-
require 'json'
|
17
|
-
require 'logger'
|
18
|
-
|
19
|
-
|
20
|
-
module AppEngine
|
21
|
-
|
22
|
-
|
23
|
-
# == AppEngine Logger integration
|
24
|
-
#
|
25
|
-
# A collection of tools for talking to the StackDriver logs in the Google
|
26
|
-
# Cloud Console.
|
27
|
-
#
|
28
|
-
# For logs to appear in the Google Cloud Console, they must be written in
|
29
|
-
# JSON format to files matching the pattern "/var/log/app_engine/app*.json".
|
30
|
-
# We provide an appropriate formatter, and a LogDevice that omits the
|
31
|
-
# log header line.
|
32
|
-
#
|
33
|
-
# Logs should also be annotated with the request's Trace ID. We provide
|
34
|
-
# a Rack Middleware to extract that ID from the environment and annotate
|
35
|
-
# log entries. It uses a fiber-local variable to store the Trace ID for
|
36
|
-
# the current request being handled by that fiber.
|
37
|
-
|
38
|
-
module Logger
|
39
|
-
|
40
|
-
|
41
|
-
# The name of a fiber-local variable storing the trace ID for the current
|
42
|
-
# request.
|
43
|
-
DEFAULT_TRACE_ID_VAR = :_google_appengine_trace_id
|
44
|
-
|
45
|
-
# The default path to the log file.
|
46
|
-
DEFAULT_LOG_FILENAME = '/var/log/app_engine/app-ruby.json'
|
47
|
-
|
48
|
-
# A map from Ruby severity names to Google Cloud severity names.
|
49
|
-
SEV_MAP = {
|
50
|
-
'DEBUG' => 'DEBUG',
|
51
|
-
'INFO' => 'INFO',
|
52
|
-
'WARN' => 'WARNING',
|
53
|
-
'ERROR' => 'ERROR',
|
54
|
-
'FATAL' => 'CRITICAL'
|
55
|
-
}
|
56
|
-
|
57
|
-
|
58
|
-
# == AppEngie Formatter
|
59
|
-
#
|
60
|
-
# A formatter that generates the appropriate JSON format for log entries.
|
61
|
-
# Pulls the trace ID from the fiber-local variable, if present.
|
62
|
-
#
|
63
|
-
# (see ::Logger::Formatter)
|
64
|
-
|
65
|
-
class Formatter
|
66
|
-
|
67
|
-
|
68
|
-
# Create a new formatter. You may optionally override the fiber-local
|
69
|
-
# variable name used for the trace ID.
|
70
|
-
|
71
|
-
def initialize(trace_id_var: DEFAULT_TRACE_ID_VAR)
|
72
|
-
@trace_id_var = trace_id_var
|
73
|
-
end
|
74
|
-
|
75
|
-
|
76
|
-
def call(severity, time, progname, msg) # :nodoc:
|
77
|
-
msg = msg.to_s
|
78
|
-
return '' if msg.empty?
|
79
|
-
entry = {
|
80
|
-
message: (progname.to_s != '') ? "#{progname}: #{msg}" : msg,
|
81
|
-
timestamp: {seconds: time.to_i, nanos: time.nsec},
|
82
|
-
severity: SEV_MAP.fetch(severity.to_s, 'CRITICAL')
|
83
|
-
}
|
84
|
-
trace_id = ::Thread.current[@trace_id_var]
|
85
|
-
if trace_id
|
86
|
-
entry[:traceId] = trace_id.to_s
|
87
|
-
end
|
88
|
-
::JSON.generate(entry) + "\n"
|
89
|
-
end
|
90
|
-
|
91
|
-
end
|
92
|
-
|
93
|
-
|
94
|
-
# == AppEngine LogDevice
|
95
|
-
#
|
96
|
-
# A ::Logger::LogDevice subclass that omits the log header line.
|
97
|
-
|
98
|
-
class LogDevice < ::Logger::LogDevice
|
99
|
-
|
100
|
-
def add_log_header(file) # :nodoc:
|
101
|
-
end
|
102
|
-
|
103
|
-
end
|
104
|
-
|
105
|
-
|
106
|
-
# == Rack Middleware for AppEngine logger
|
107
|
-
#
|
108
|
-
# A Rack middleware that sets the logger in the Rack environment, and
|
109
|
-
# stashes the trace ID for the current request in a fiber-local variable
|
110
|
-
# for the logger to use when formatting log entries.
|
111
|
-
#
|
112
|
-
# In a standard Rack application, you should use this middleware instead
|
113
|
-
# of the standard ::Rack::Logger.
|
114
|
-
|
115
|
-
class Middleware
|
116
|
-
|
117
|
-
|
118
|
-
# Create a new AppEngine logging Middleware.
|
119
|
-
# The argument is an options hash supporting the following keys:
|
120
|
-
#
|
121
|
-
# [<tt>:logger</tt>]
|
122
|
-
# A global logger to use. This should generally be a logger created
|
123
|
-
# by AppEngine::Logger.create(). The middleware sets env["rack.logger"]
|
124
|
-
# accordingly. If omitted, a default logger is created automatically
|
125
|
-
# when the middleware is constructed.
|
126
|
-
# [<tt>:trace_id_var</tt>]
|
127
|
-
# The name of the fiber-local variable to use to stack the trace ID.
|
128
|
-
# Defaults to the value of DEFAULT_TRACE_ID_VAR. You generally should
|
129
|
-
# not need to modify this value unless you need to control fiber-local
|
130
|
-
# variable names.
|
131
|
-
# [<tt>:logfile</tt>]
|
132
|
-
# If you do not specify a <tt>:logger</tt>, a logger is created that
|
133
|
-
# opens this file. Defaults to the value of DEFAULT_LOG_FILENAME.
|
134
|
-
# Generally, you should leave this setting to the default for
|
135
|
-
# deployments, because App Engine expects log files in a particular
|
136
|
-
# location. However, if you want to test log generation into a
|
137
|
-
# different directory in development, you may set it here.
|
138
|
-
|
139
|
-
def initialize(app,
|
140
|
-
logger: nil,
|
141
|
-
trace_id_var: DEFAULT_TRACE_ID_VAR,
|
142
|
-
logfile: DEFAULT_LOG_FILENAME)
|
143
|
-
@app = app
|
144
|
-
@trace_id_var = trace_id_var
|
145
|
-
@logger = logger || Logger.create(trace_id_var: trace_id_var, logfile: logfile)
|
146
|
-
end
|
147
|
-
|
148
|
-
|
149
|
-
def call(env) # :nodoc:
|
150
|
-
env['rack.logger'] = @logger
|
151
|
-
::Thread.current[@trace_id_var] = Env.extract_trace_id(env)
|
152
|
-
begin
|
153
|
-
@app.call(env)
|
154
|
-
ensure
|
155
|
-
::Thread.current[@trace_id_var] = nil
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
end
|
160
|
-
|
161
|
-
|
162
|
-
# Creates a new logger for AppEngine that writes to the correct location
|
163
|
-
# using the correct formatting.
|
164
|
-
# The argument is an options hash supporting the following keys:
|
165
|
-
#
|
166
|
-
# [<tt>:trace_id_var</tt>]
|
167
|
-
# The name of the fiber-local variable to use to stack the trace ID.
|
168
|
-
# Defaults to the value of DEFAULT_TRACE_ID_VAR. You generally should
|
169
|
-
# not need to modify this value unless you need to control fiber-local
|
170
|
-
# variable names.
|
171
|
-
# [<tt>:logfile</tt>]
|
172
|
-
# Log file to write to. Defaults to the value of DEFAULT_LOG_FILENAME.
|
173
|
-
# Generally, you should leave this setting to the default for
|
174
|
-
# deployments, because App Engine expects log files in a particular
|
175
|
-
# location. However, if you want to test log generation into a
|
176
|
-
# different directory in development, you may set it here.
|
177
|
-
|
178
|
-
def self.create(trace_id_var: DEFAULT_TRACE_ID_VAR, logfile: DEFAULT_LOG_FILENAME)
|
179
|
-
if logfile.kind_of?(::String)
|
180
|
-
::FileUtils.mkdir_p(::File.dirname(logfile))
|
181
|
-
end
|
182
|
-
logger = ::Logger.new(LogDevice.new(logfile))
|
183
|
-
logger.formatter = Formatter.new(trace_id_var: trace_id_var)
|
184
|
-
logger
|
185
|
-
end
|
186
|
-
|
187
|
-
end
|
188
|
-
end
|
data/test/test_logger.rb
DELETED
@@ -1,151 +0,0 @@
|
|
1
|
-
# Copyright 2016 Google Inc. All rights reserved.
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at
|
6
|
-
#
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
#
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
# See the License for the specific language governing permissions and
|
13
|
-
# limitations under the License.
|
14
|
-
;
|
15
|
-
|
16
|
-
require 'minitest/autorun'
|
17
|
-
require 'appengine'
|
18
|
-
|
19
|
-
|
20
|
-
module AppEngine
|
21
|
-
module Tests # :nodoc:
|
22
|
-
|
23
|
-
class TestFormatter < ::Minitest::Test # :nodoc:
|
24
|
-
|
25
|
-
|
26
|
-
def setup
|
27
|
-
@time_sec = 1461544128
|
28
|
-
@time_nsec = 580791000
|
29
|
-
@time = ::Time.at(@time_sec, @time_nsec / 1000)
|
30
|
-
@trace_id = 'a1b2c3d4e5f6'
|
31
|
-
::Thread.current[::AppEngine::Logger::DEFAULT_TRACE_ID_VAR] = @trace_id
|
32
|
-
@formatter = ::AppEngine::Logger::Formatter.new
|
33
|
-
end
|
34
|
-
|
35
|
-
|
36
|
-
def test_format_empty
|
37
|
-
result = @formatter.call('ERROR', @time, 'prog', '')
|
38
|
-
assert_equal('', result)
|
39
|
-
end
|
40
|
-
|
41
|
-
|
42
|
-
def test_format_with_progname
|
43
|
-
result = @formatter.call('ERROR', @time, 'prog', 'this message')
|
44
|
-
assert_equal(
|
45
|
-
"{\"message\":\"prog: this message\"," +
|
46
|
-
"\"timestamp\":{\"seconds\":#{@time_sec},\"nanos\":#{@time_nsec}}," +
|
47
|
-
"\"severity\":\"ERROR\"," +
|
48
|
-
"\"traceId\":\"#{@trace_id}\"}\n",
|
49
|
-
result)
|
50
|
-
end
|
51
|
-
|
52
|
-
|
53
|
-
def test_format_with_no_trace_id
|
54
|
-
::Thread.current[::AppEngine::Logger::DEFAULT_TRACE_ID_VAR] = nil
|
55
|
-
result = @formatter.call('ERROR', @time, '', 'this message')
|
56
|
-
assert_equal(
|
57
|
-
"{\"message\":\"this message\"," +
|
58
|
-
"\"timestamp\":{\"seconds\":#{@time_sec},\"nanos\":#{@time_nsec}}," +
|
59
|
-
"\"severity\":\"ERROR\"}\n",
|
60
|
-
result)
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
def test_format_with_warning_severity
|
65
|
-
result = @formatter.call('WARN', @time, '', 'this message')
|
66
|
-
assert_equal(
|
67
|
-
"{\"message\":\"this message\"," +
|
68
|
-
"\"timestamp\":{\"seconds\":#{@time_sec},\"nanos\":#{@time_nsec}}," +
|
69
|
-
"\"severity\":\"WARNING\"," +
|
70
|
-
"\"traceId\":\"#{@trace_id}\"}\n",
|
71
|
-
result)
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
def test_format_with_critical_severity
|
76
|
-
result = @formatter.call('FATAL', @time, '', 'this message')
|
77
|
-
assert_equal(
|
78
|
-
"{\"message\":\"this message\"," +
|
79
|
-
"\"timestamp\":{\"seconds\":#{@time_sec},\"nanos\":#{@time_nsec}}," +
|
80
|
-
"\"severity\":\"CRITICAL\"," +
|
81
|
-
"\"traceId\":\"#{@trace_id}\"}\n",
|
82
|
-
result)
|
83
|
-
end
|
84
|
-
|
85
|
-
|
86
|
-
def test_format_with_unknown_severity
|
87
|
-
result = @formatter.call('UNKNOWN', @time, '', 'this message')
|
88
|
-
assert_equal(
|
89
|
-
"{\"message\":\"this message\"," +
|
90
|
-
"\"timestamp\":{\"seconds\":#{@time_sec},\"nanos\":#{@time_nsec}}," +
|
91
|
-
"\"severity\":\"CRITICAL\"," +
|
92
|
-
"\"traceId\":\"#{@trace_id}\"}\n",
|
93
|
-
result)
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
|
-
end
|
98
|
-
|
99
|
-
|
100
|
-
class TestLogger < ::Minitest::Test # :nodoc:
|
101
|
-
|
102
|
-
|
103
|
-
def test_no_logging
|
104
|
-
lines = run_test do |logger|
|
105
|
-
end
|
106
|
-
assert_equal([], lines)
|
107
|
-
end
|
108
|
-
|
109
|
-
|
110
|
-
def test_basic_log
|
111
|
-
trace_id = "tracetrace"
|
112
|
-
lines = run_test(trace_id) do |logger|
|
113
|
-
logger.progname = "rails"
|
114
|
-
logger.info("Hello")
|
115
|
-
logger.warn("This is a warning")
|
116
|
-
end
|
117
|
-
assert_equal(2, lines.size)
|
118
|
-
assert_log_entry("rails: Hello", "INFO", trace_id, lines[0])
|
119
|
-
assert_log_entry("rails: This is a warning", "WARNING", trace_id, lines[1])
|
120
|
-
end
|
121
|
-
|
122
|
-
|
123
|
-
def assert_log_entry(expected_message, expected_severity, expected_trace_id, line)
|
124
|
-
if line =~ /^\{"message":"(.*)","timestamp":\{"seconds":\d+,"nanos":\d+\},"severity":"(\w+)"(,"traceId":"(\w+)")?\}\n$/
|
125
|
-
message = $1
|
126
|
-
severity = $2
|
127
|
-
trace_id = $4
|
128
|
-
assert_equal(expected_message, message)
|
129
|
-
assert_equal(expected_severity, severity)
|
130
|
-
assert_equal(expected_trace_id, trace_id)
|
131
|
-
else
|
132
|
-
flunk("Bad format: #{line.inspect}")
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
|
137
|
-
def run_test(trace_id=nil)
|
138
|
-
stringio = ::StringIO.new('', 'w')
|
139
|
-
app = ::Proc.new { |env|
|
140
|
-
yield(env['rack.logger'])
|
141
|
-
}
|
142
|
-
middleware = ::AppEngine::Logger::Middleware.new(app, logfile: stringio)
|
143
|
-
middleware.call({'HTTP_X_CLOUD_TRACE_CONTEXT' => trace_id})
|
144
|
-
::StringIO.new(stringio.string).each_line.to_a
|
145
|
-
end
|
146
|
-
|
147
|
-
|
148
|
-
end
|
149
|
-
|
150
|
-
end
|
151
|
-
end
|