functions_framework 0.4.1 → 0.7.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 +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +11 -11
- data/bin/functions-framework +4 -1
- data/bin/functions-framework-ruby +1 -1
- data/docs/deploying-functions.md +22 -13
- data/docs/overview.md +6 -6
- data/docs/testing-functions.md +59 -11
- data/docs/writing-functions.md +202 -13
- data/lib/functions_framework.rb +41 -10
- data/lib/functions_framework/cli.rb +97 -22
- data/lib/functions_framework/function.rb +142 -47
- data/lib/functions_framework/legacy_event_converter.rb +10 -11
- data/lib/functions_framework/registry.rb +36 -12
- data/lib/functions_framework/server.rb +27 -22
- data/lib/functions_framework/testing.rb +123 -24
- data/lib/functions_framework/version.rb +1 -1
- metadata +24 -16
- data/lib/functions_framework/cloud_events.rb +0 -45
- data/lib/functions_framework/cloud_events/content_type.rb +0 -222
- data/lib/functions_framework/cloud_events/errors.rb +0 -42
- data/lib/functions_framework/cloud_events/event.rb +0 -84
- data/lib/functions_framework/cloud_events/event/field_interpreter.rb +0 -150
- data/lib/functions_framework/cloud_events/event/v0.rb +0 -236
- data/lib/functions_framework/cloud_events/event/v1.rb +0 -223
- data/lib/functions_framework/cloud_events/http_binding.rb +0 -310
- data/lib/functions_framework/cloud_events/json_format.rb +0 -173
data/lib/functions_framework.rb
CHANGED
@@ -14,7 +14,8 @@
|
|
14
14
|
|
15
15
|
require "logger"
|
16
16
|
|
17
|
-
require "
|
17
|
+
require "cloud_events"
|
18
|
+
|
18
19
|
require "functions_framework/function"
|
19
20
|
require "functions_framework/legacy_event_converter"
|
20
21
|
require "functions_framework/registry"
|
@@ -44,10 +45,6 @@ require "functions_framework/version"
|
|
44
45
|
#
|
45
46
|
# Here is a roadmap to the internal modules in the Ruby functions framework.
|
46
47
|
#
|
47
|
-
# * {FunctionsFramework::CloudEvents} provides an implementation of the
|
48
|
-
# [CloudEvents](https://cloudevents.io) specification. In particular, if
|
49
|
-
# you define an event function, you will receive the event as a
|
50
|
-
# {FunctionsFramework::CloudEvents::Event} object.
|
51
48
|
# * {FunctionsFramework::CLI} is the implementation of the
|
52
49
|
# `functions-framework-ruby` executable. Most apps will not need to interact
|
53
50
|
# with this class directly.
|
@@ -74,7 +71,7 @@ require "functions_framework/version"
|
|
74
71
|
#
|
75
72
|
module FunctionsFramework
|
76
73
|
@global_registry = Registry.new
|
77
|
-
@logger = ::Logger.new
|
74
|
+
@logger = ::Logger.new $stderr
|
78
75
|
@logger.level = ::Logger::INFO
|
79
76
|
|
80
77
|
##
|
@@ -94,6 +91,12 @@ module FunctionsFramework
|
|
94
91
|
#
|
95
92
|
DEFAULT_SOURCE = "./app.rb".freeze
|
96
93
|
|
94
|
+
##
|
95
|
+
# The CloudEvents implementation was extracted to become the official
|
96
|
+
# CloudEvents SDK. This alias is left here for backward compatibility.
|
97
|
+
#
|
98
|
+
CloudEvents = ::CloudEvents
|
99
|
+
|
97
100
|
class << self
|
98
101
|
##
|
99
102
|
# The "global" registry that holds events defined by the
|
@@ -144,7 +147,8 @@ module FunctionsFramework
|
|
144
147
|
#
|
145
148
|
# You must provide a name for the function, and a block that implemets the
|
146
149
|
# function. The block should take one argument: the event object of type
|
147
|
-
#
|
150
|
+
# [`CloudEvents::Event`](https://cloudevents.github.io/sdk-ruby/latest/CloudEvents/Event).
|
151
|
+
# Any return value is ignored.
|
148
152
|
#
|
149
153
|
# ## Example
|
150
154
|
#
|
@@ -162,8 +166,30 @@ module FunctionsFramework
|
|
162
166
|
end
|
163
167
|
|
164
168
|
##
|
165
|
-
#
|
166
|
-
#
|
169
|
+
# Define a server startup task. This is useful for initializing shared
|
170
|
+
# resources that should be accessible across all function invocations in
|
171
|
+
# this Ruby VM.
|
172
|
+
#
|
173
|
+
# Startup tasks are run just before a server starts. All startup tasks are
|
174
|
+
# guaranteed to complete before any function executes. However, they are
|
175
|
+
# run only when preparing to run functions. They are not run, for example,
|
176
|
+
# if an app is loaded to verify its integrity during deployment.
|
177
|
+
#
|
178
|
+
# Startup tasks are passed the {FunctionsFramework::Function} identifying
|
179
|
+
# the function to execute, and have no return value.
|
180
|
+
#
|
181
|
+
# @param block [Proc] The startup task
|
182
|
+
# @return [self]
|
183
|
+
#
|
184
|
+
def on_startup &block
|
185
|
+
global_registry.add_startup_task(&block)
|
186
|
+
self
|
187
|
+
end
|
188
|
+
|
189
|
+
##
|
190
|
+
# Run startup tasks, then start the functions framework server in the
|
191
|
+
# background. The startup tasks and target function will be looked up in
|
192
|
+
# the global registry.
|
167
193
|
#
|
168
194
|
# @param target [FunctionsFramework::Function,String] The function to run,
|
169
195
|
# or the name of the function to look up in the global registry.
|
@@ -179,7 +205,12 @@ module FunctionsFramework
|
|
179
205
|
function = global_registry[target]
|
180
206
|
raise ::ArgumentError, "Undefined function: #{target.inspect}" if function.nil?
|
181
207
|
end
|
182
|
-
|
208
|
+
globals = function.populate_globals
|
209
|
+
server = Server.new function, globals, &block
|
210
|
+
global_registry.startup_tasks.each do |task|
|
211
|
+
task.call function, globals: globals, logger: server.config.logger
|
212
|
+
end
|
213
|
+
globals.freeze
|
183
214
|
server.respond_to_signals
|
184
215
|
server.start
|
185
216
|
end
|
@@ -42,8 +42,31 @@ module FunctionsFramework
|
|
42
42
|
@detailed_errors = nil
|
43
43
|
@signature_type = ::ENV["FUNCTION_SIGNATURE_TYPE"]
|
44
44
|
@logging_level = init_logging_level
|
45
|
+
@what_to_do = nil
|
46
|
+
@error_message = nil
|
47
|
+
@exit_code = 0
|
45
48
|
end
|
46
49
|
|
50
|
+
##
|
51
|
+
# Determine if an error has occurred
|
52
|
+
#
|
53
|
+
# @return [boolean]
|
54
|
+
#
|
55
|
+
def error?
|
56
|
+
!@error_message.nil?
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# @return [Integer] The current exit status.
|
61
|
+
#
|
62
|
+
attr_reader :exit_code
|
63
|
+
|
64
|
+
##
|
65
|
+
# @return [String] The current error message.
|
66
|
+
# @return [nil] if no error has occurred.
|
67
|
+
#
|
68
|
+
attr_reader :error_message
|
69
|
+
|
47
70
|
##
|
48
71
|
# Parse the given command line arguments.
|
49
72
|
# Exits if argument parsing failed.
|
@@ -52,7 +75,7 @@ module FunctionsFramework
|
|
52
75
|
# @return [self]
|
53
76
|
#
|
54
77
|
def parse_args argv # rubocop:disable Metrics/MethodLength
|
55
|
-
option_parser = ::OptionParser.new do |op| # rubocop:disable Metrics/BlockLength
|
78
|
+
@option_parser = ::OptionParser.new do |op| # rubocop:disable Metrics/BlockLength
|
56
79
|
op.on "-t", "--target TARGET",
|
57
80
|
"Set the name of the function to execute (defaults to #{DEFAULT_TARGET})" do |val|
|
58
81
|
@target = val
|
@@ -84,55 +107,92 @@ module FunctionsFramework
|
|
84
107
|
op.on "--[no-]detailed-errors", "Set whether to show error details" do |val|
|
85
108
|
@detailed_errors = val
|
86
109
|
end
|
110
|
+
op.on "--verify", "Verify the app only, but do not run the server." do
|
111
|
+
@what_to_do ||= :verify
|
112
|
+
end
|
87
113
|
op.on "-v", "--verbose", "Increase log verbosity" do
|
88
114
|
@logging_level -= 1
|
89
115
|
end
|
90
116
|
op.on "-q", "--quiet", "Decrease log verbosity" do
|
91
117
|
@logging_level += 1
|
92
118
|
end
|
119
|
+
op.on "--version", "Display the framework version" do
|
120
|
+
@what_to_do ||= :version
|
121
|
+
end
|
93
122
|
op.on "--help", "Display help" do
|
94
|
-
|
95
|
-
exit
|
123
|
+
@what_to_do ||= :help
|
96
124
|
end
|
97
125
|
end
|
98
|
-
|
99
|
-
|
126
|
+
begin
|
127
|
+
@option_parser.parse! argv
|
128
|
+
error! "Unrecognized arguments: #{argv}\n#{@option_parser}", 2 unless argv.empty?
|
129
|
+
rescue ::OptionParser::ParseError => e
|
130
|
+
error! "#{e.message}\n#{@option_parser}", 2
|
131
|
+
end
|
100
132
|
self
|
101
133
|
end
|
102
134
|
|
103
135
|
##
|
104
|
-
#
|
105
|
-
#
|
136
|
+
# Perform the requested function.
|
137
|
+
#
|
138
|
+
# * If the `--version` flag was given, display the version.
|
139
|
+
# * If the `--help` flag was given, display online help.
|
140
|
+
# * If the `--verify` flag was given, load and verify the function,
|
141
|
+
# displaying any errors, then exit without starting a server.
|
142
|
+
# * Otherwise, start the configured server and block until it stops.
|
106
143
|
#
|
107
144
|
# @return [self]
|
108
145
|
#
|
109
146
|
def run
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
147
|
+
return self if error?
|
148
|
+
case @what_to_do
|
149
|
+
when :version
|
150
|
+
puts ::FunctionsFramework::VERSION
|
151
|
+
when :help
|
152
|
+
puts @option_parser
|
153
|
+
when :verify
|
154
|
+
begin
|
155
|
+
load_function
|
156
|
+
puts "OK"
|
157
|
+
rescue ::StandardError => e
|
158
|
+
error! e.message
|
159
|
+
end
|
160
|
+
else
|
161
|
+
begin
|
162
|
+
start_server.wait_until_stopped
|
163
|
+
rescue ::StandardError => e
|
164
|
+
error! e.message
|
165
|
+
end
|
114
166
|
end
|
115
|
-
server.wait_until_stopped
|
116
167
|
self
|
117
168
|
end
|
118
169
|
|
119
170
|
##
|
120
|
-
#
|
171
|
+
# Finish the CLI, displaying any error status and exiting with the current
|
172
|
+
# exit code. Never returns.
|
173
|
+
#
|
174
|
+
def complete
|
175
|
+
warn @error_message if @error_message
|
176
|
+
exit @exit_code
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# Load the source and get and verify the requested function.
|
121
181
|
# If a validation error occurs, raise an exception.
|
122
|
-
# This is used for testing the CLI.
|
123
182
|
#
|
124
|
-
# @return [FunctionsFramework::
|
183
|
+
# @return [FunctionsFramework::Function]
|
125
184
|
#
|
126
185
|
# @private
|
127
186
|
#
|
128
|
-
def
|
187
|
+
def load_function
|
129
188
|
::FunctionsFramework.logger.level = @logging_level
|
130
|
-
::FunctionsFramework.logger.info "FunctionsFramework v#{VERSION}
|
189
|
+
::FunctionsFramework.logger.info "FunctionsFramework v#{VERSION}"
|
131
190
|
::ENV["FUNCTION_TARGET"] = @target
|
132
191
|
::ENV["FUNCTION_SOURCE"] = @source
|
133
192
|
::ENV["FUNCTION_SIGNATURE_TYPE"] = @signature_type
|
134
193
|
::FunctionsFramework.logger.info "FunctionsFramework: Loading functions from #{@source.inspect}..."
|
135
194
|
load @source
|
195
|
+
::FunctionsFramework.logger.info "FunctionsFramework: Looking for function name #{@target.inspect}..."
|
136
196
|
function = ::FunctionsFramework.global_registry[@target]
|
137
197
|
raise "Undefined function: #{@target.inspect}" if function.nil?
|
138
198
|
unless @signature_type.nil? ||
|
@@ -140,6 +200,20 @@ module FunctionsFramework
|
|
140
200
|
["cloudevent", "event"].include?(@signature_type) && function.type == :cloud_event
|
141
201
|
raise "Function #{@target.inspect} does not match type #{@signature_type}"
|
142
202
|
end
|
203
|
+
function
|
204
|
+
end
|
205
|
+
|
206
|
+
##
|
207
|
+
# Start the configured server and return the running server object.
|
208
|
+
# If a validation error occurs, raise an exception.
|
209
|
+
#
|
210
|
+
# @return [FunctionsFramework::Server]
|
211
|
+
#
|
212
|
+
# @private
|
213
|
+
#
|
214
|
+
def start_server
|
215
|
+
function = load_function
|
216
|
+
::FunctionsFramework.logger.info "FunctionsFramework: Starting server..."
|
143
217
|
::FunctionsFramework.start function do |config|
|
144
218
|
config.rack_env = @env
|
145
219
|
config.port = @port
|
@@ -160,12 +234,13 @@ module FunctionsFramework
|
|
160
234
|
end
|
161
235
|
|
162
236
|
##
|
163
|
-
#
|
164
|
-
# @param message [String]
|
237
|
+
# Set the error status.
|
238
|
+
# @param message [String] Error message.
|
239
|
+
# @param code [Integer] Exit code, defaults to 1.
|
165
240
|
#
|
166
|
-
def error message
|
167
|
-
|
168
|
-
|
241
|
+
def error! message, code = 1
|
242
|
+
@error_message = message
|
243
|
+
@exit_code = code
|
169
244
|
end
|
170
245
|
end
|
171
246
|
end
|
@@ -18,43 +18,91 @@ module FunctionsFramework
|
|
18
18
|
#
|
19
19
|
# A function has a name, a type, and an implementation.
|
20
20
|
#
|
21
|
+
# ## Function implementations
|
22
|
+
#
|
21
23
|
# The implementation in general is an object that responds to the `call`
|
22
|
-
# method.
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
# {FunctionsFramework::
|
27
|
-
#
|
24
|
+
# method.
|
25
|
+
#
|
26
|
+
# * For a function of type `:http`, the `call` method takes a single
|
27
|
+
# `Rack::Request` argument and returns one of various HTTP response
|
28
|
+
# types. See {FunctionsFramework::Registry.add_http}.
|
29
|
+
# * For a function of type `:cloud_event`, the `call` method takes a single
|
30
|
+
# [CloudEvent](https://cloudevents.github.io/sdk-ruby/latest/CloudEvents/Event)
|
31
|
+
# argument, and does not return a value. See
|
32
|
+
# {FunctionsFramework::Registry.add_cloud_event}.
|
33
|
+
# * For a function of type `:startup_task`, the `call` method takes a
|
34
|
+
# single {FunctionsFramework::Function} argument, and does not return a
|
35
|
+
# value. See {FunctionsFramework::Registry.add_startup_task}.
|
28
36
|
#
|
29
|
-
#
|
30
|
-
# every function execution. Note that this means it may be called multiple
|
31
|
-
# times concurrently in separate threads.
|
37
|
+
# The implementation can be specified in one of three ways:
|
32
38
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
+
# * A callable object can be passed in the `callable` keyword argument. The
|
40
|
+
# object's `call` method will be invoked for every function execution.
|
41
|
+
# Note that this means it may be called multiple times concurrently in
|
42
|
+
# separate threads.
|
43
|
+
# * A callable _class_ can be passed in the `callable` keyword argument.
|
44
|
+
# This class should subclass {FunctionsFramework::Function::Callable} and
|
45
|
+
# define the `call` method. A separate instance of this class will be
|
46
|
+
# created for each function invocation.
|
47
|
+
# * A block can be provided. It will be used to define the `call` method in
|
48
|
+
# an anonymous subclass of {FunctionsFramework::Function::Callable}.
|
49
|
+
# Thus, providing a block is really just syntactic sugar for providing a
|
50
|
+
# class. (This means, for example, that the `return` keyword will work
|
51
|
+
# as expected within the block because it is treated as a method.)
|
39
52
|
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
53
|
+
# When the implementation is provided as a callable class or block, it is
|
54
|
+
# executed in the context of a {FunctionsFramework::Function::Callable}
|
55
|
+
# object. This object provides a convenience accessor for the Logger, and
|
56
|
+
# access to _globals_, which are data defined by the application startup
|
57
|
+
# process and available to each function invocation. Typically, globals are
|
58
|
+
# used for shared global resources such as service connections and clients.
|
46
59
|
#
|
47
60
|
class Function
|
61
|
+
##
|
62
|
+
# Create a new HTTP function definition.
|
63
|
+
#
|
64
|
+
# @param name [String] The function name
|
65
|
+
# @param callable [Class,#call] A callable object or class.
|
66
|
+
# @param block [Proc] The function code as a block.
|
67
|
+
# @return [FunctionsFramework::Function]
|
68
|
+
#
|
69
|
+
def self.http name, callable: nil, &block
|
70
|
+
new name, :http, callable: callable, &block
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Create a new CloudEvents function definition.
|
75
|
+
#
|
76
|
+
# @param name [String] The function name
|
77
|
+
# @param callable [Class,#call] A callable object or class.
|
78
|
+
# @param block [Proc] The function code as a block.
|
79
|
+
# @return [FunctionsFramework::Function]
|
80
|
+
#
|
81
|
+
def self.cloud_event name, callable: nil, &block
|
82
|
+
new name, :cloud_event, callable: callable, &block
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Create a new startup task function definition.
|
87
|
+
#
|
88
|
+
# @param callable [Class,#call] A callable object or class.
|
89
|
+
# @param block [Proc] The function code as a block.
|
90
|
+
# @return [FunctionsFramework::Function]
|
91
|
+
#
|
92
|
+
def self.startup_task callable: nil, &block
|
93
|
+
new nil, :startup_task, callable: callable, &block
|
94
|
+
end
|
95
|
+
|
48
96
|
##
|
49
97
|
# Create a new function definition.
|
50
98
|
#
|
51
99
|
# @param name [String] The function name
|
52
|
-
# @param type [Symbol] The type of function. Valid types are `:http
|
53
|
-
# `:cloud_event`.
|
100
|
+
# @param type [Symbol] The type of function. Valid types are `:http`,
|
101
|
+
# `:cloud_event`, and `:startup_task`.
|
54
102
|
# @param callable [Class,#call] A callable object or class.
|
55
103
|
# @param block [Proc] The function code as a block.
|
56
104
|
#
|
57
|
-
def initialize name, type, callable
|
105
|
+
def initialize name, type, callable: nil, &block
|
58
106
|
@name = name
|
59
107
|
@type = type
|
60
108
|
@callable = @callable_class = nil
|
@@ -63,7 +111,7 @@ module FunctionsFramework
|
|
63
111
|
elsif callable.is_a? ::Class
|
64
112
|
@callable_class = callable
|
65
113
|
elsif block_given?
|
66
|
-
@callable_class = ::Class.new
|
114
|
+
@callable_class = ::Class.new Callable do
|
67
115
|
define_method :call, &block
|
68
116
|
end
|
69
117
|
else
|
@@ -82,18 +130,38 @@ module FunctionsFramework
|
|
82
130
|
attr_reader :type
|
83
131
|
|
84
132
|
##
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
133
|
+
# Populate the given globals hash with this function's info.
|
134
|
+
#
|
135
|
+
# @param globals [Hash] Initial globals hash (optional).
|
136
|
+
# @return [Hash] A new globals hash with this function's info included.
|
137
|
+
#
|
138
|
+
def populate_globals globals = nil
|
139
|
+
result = { function_name: name, function_type: type }
|
140
|
+
result.merge! globals if globals
|
141
|
+
result
|
142
|
+
end
|
143
|
+
|
144
|
+
##
|
145
|
+
# Call the function given a set of arguments. Set the given logger and/or
|
146
|
+
# globals in the context if the callable supports it.
|
147
|
+
#
|
148
|
+
# If the given arguments exceeds what the function will accept, the args
|
149
|
+
# are silently truncated. However, if the function requires more arguments
|
150
|
+
# than are provided, an ArgumentError is raised.
|
151
|
+
#
|
152
|
+
# @param args [Array] Argument to pass to the function.
|
153
|
+
# @param logger [Logger] Logger for use by function executions.
|
154
|
+
# @param globals [Hash] Globals for the function execution context
|
155
|
+
# @return [Object] The function return value.
|
156
|
+
#
|
157
|
+
def call *args, globals: nil, logger: nil
|
158
|
+
callable = @callable || @callable_class.new(globals: globals, logger: logger)
|
159
|
+
params = callable.method(:call).parameters.map(&:first)
|
160
|
+
unless params.include? :rest
|
161
|
+
max_params = params.count(:req) + params.count(:opt)
|
162
|
+
args = args.take max_params
|
163
|
+
end
|
164
|
+
callable.call(*args)
|
97
165
|
end
|
98
166
|
|
99
167
|
##
|
@@ -101,29 +169,56 @@ module FunctionsFramework
|
|
101
169
|
#
|
102
170
|
# An object of this class is `self` while a function block is running.
|
103
171
|
#
|
104
|
-
class
|
172
|
+
class Callable
|
105
173
|
##
|
106
174
|
# Create a callable object with the given context.
|
107
175
|
#
|
108
|
-
# @param
|
109
|
-
#
|
110
|
-
# implementations should be prepared to accept any abritrary keys.
|
176
|
+
# @param globals [Hash] A set of globals available to the call.
|
177
|
+
# @param logger [Logger] A logger for use by the function call.
|
111
178
|
#
|
112
|
-
def initialize
|
113
|
-
@
|
179
|
+
def initialize globals: nil, logger: nil
|
180
|
+
@__globals = globals || {}
|
181
|
+
@__logger = logger || FunctionsFramework.logger
|
114
182
|
end
|
115
183
|
|
116
184
|
##
|
117
|
-
#
|
185
|
+
# Get the given named global.
|
186
|
+
#
|
187
|
+
# For most function calls, the following globals will be defined:
|
118
188
|
#
|
119
|
-
# * **:logger** (`Logger`) A logger for use by this function call.
|
120
189
|
# * **:function_name** (`String`) The name of the running function.
|
121
190
|
# * **:function_type** (`Symbol`) The type of the running function,
|
122
191
|
# either `:http` or `:cloud_event`.
|
123
192
|
#
|
124
|
-
#
|
193
|
+
# You can also set additional globals from a startup task.
|
194
|
+
#
|
195
|
+
# @param key [Symbol,String] The name of the global to get.
|
196
|
+
# @return [Object]
|
125
197
|
#
|
126
|
-
|
198
|
+
def global key
|
199
|
+
@__globals[key]
|
200
|
+
end
|
201
|
+
|
202
|
+
##
|
203
|
+
# Set a global. This can be called from startup tasks, but the globals
|
204
|
+
# are frozen when the server starts, so this call will raise an exception
|
205
|
+
# if called from a normal function.
|
206
|
+
#
|
207
|
+
# @param key [Symbol,String]
|
208
|
+
# @param value [Object]
|
209
|
+
#
|
210
|
+
def set_global key, value
|
211
|
+
@__globals[key] = value
|
212
|
+
end
|
213
|
+
|
214
|
+
##
|
215
|
+
# A logger for use by this call.
|
216
|
+
#
|
217
|
+
# @return [Logger]
|
218
|
+
#
|
219
|
+
def logger
|
220
|
+
@__logger
|
221
|
+
end
|
127
222
|
end
|
128
223
|
end
|
129
224
|
end
|