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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c5603a0560a10f3f6d0c6a6cd9a35ad8dcec9965
4
- data.tar.gz: 92d67d00bfb992d723ccb5628f4f3f53c75e1a48
3
+ metadata.gz: 4841b00bed08c35d62dfd337ccd15cf5df775de9
4
+ data.tar.gz: a3158e01aaccb61471b504d7a66983c24a58a560
5
5
  SHA512:
6
- metadata.gz: 381abeeea878aa676f40fbd444c022f2639f05d175c6457efd02e26c0eaa54ade5b1e032ac2dd553aa067afc594cb790be2828c230122d121a9d221dcc239657
7
- data.tar.gz: 880a1741725629a5588795d1d7f38bbd340cd3a814a93e597bacdfa595080d191ecc25e1313aa2fd8e931406fb74415227ca561d3794c7bca6d0a8fbfb79433f
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
- * A way to configure the Logger to log to the Google Cloud Console.
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. You may provide additional configuration via the
31
- `config.appengine` object. See below for more details.
32
-
33
- If you are using a different Rack-based framework such as
34
- [Sinatra](http://sinatrarb.com/), you can use the provided middlewares. See
35
- the more detailed instructions below.
36
-
37
- ## Google Cloud Console logger integration
38
-
39
- In order for your application logs to appear in the Google Cloud Console with
40
- the correct severities and other metadata, they should be written in a
41
- specific format to a specific location. The logger module in this gem provides
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
@@ -24,5 +24,6 @@ end
24
24
 
25
25
  require 'appengine/version'
26
26
  require 'appengine/env'
27
- require 'appengine/logger'
28
27
  require 'appengine/railtie' if defined?(::Rails)
28
+
29
+ require "stackdriver"
data/lib/appengine/env.rb CHANGED
@@ -16,25 +16,15 @@
16
16
 
17
17
  module AppEngine
18
18
 
19
-
20
- # == Environment information
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
- # Returns the Trace ID string from a Rack environment, or nil if no trace
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
@@ -31,25 +31,7 @@ module AppEngine
31
31
  #
32
32
  # === Configuration
33
33
  #
34
- # The following configuration parameters are supported.
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
@@ -16,6 +16,6 @@
16
16
  module AppEngine
17
17
 
18
18
  # The current version of this gem, as a string.
19
- VERSION = '0.2.0'.freeze
19
+ VERSION = '0.3.0'.freeze
20
20
 
21
21
  end
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 test_extract_trace_id_absent
27
- env = {}
28
- trace_id = Env.extract_trace_id(env)
29
- assert_nil(trace_id)
30
- end
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.2.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: 2016-05-04 00:00:00.000000000 Z
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.11'
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.11'
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 interpretation of App Engine headers.
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.4.5.1
131
+ rubygems_version: 2.6.8
114
132
  signing_key:
115
133
  specification_version: 4
116
134
  summary: Google App Engine integration tools
@@ -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