aws_lambda_ric 3.1.3 → 3.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3e8bc181a3186101100b6f17135c0db2e9a1b46e7df20fdd83c026fde47acc2f
4
- data.tar.gz: a16d3aaaab5fb3f0c5fcda6b3ca762cc38440f15b2ae2b0a07071d79a7bf2227
3
+ metadata.gz: aebcc51bb69e0146bf4fe0c2361e55967d773569e9a75b5edfee8e59926dca71
4
+ data.tar.gz: ee94ca25bd713f8dca2a08a876b6b8e9512a02953ade9d14cfa79c38b3eaee4b
5
5
  SHA512:
6
- metadata.gz: 4e1ab797c6dfbde6f84de8cae8de0dc3fcdeef5912218b5a3d45467ca8d2416e0be7e56d1a9755803cd2913e6380153796b918a63ea658a50c5418946083de44
7
- data.tar.gz: 3933a5ed56c6a6ac1e06e4fe5b3af87bef8f7d999a2054f3787f7ed0332c600ae12a9f76435b3dd14a9c52752d8c6999c59f84acacc9b896d25e8094810213a5
6
+ metadata.gz: 29f94ab802c88332d74581db2303c2b64b9864a3a5a2abdef0bdc7e1c4df810ed4248790d371d0dd55d934765928972a27a0b11976c66c86f468465b2bf62bb5
7
+ data.tar.gz: 82dada5e5cab9d9e85e0d0d44f65e8ccfbada3a633a491ccf25fb32b8ed0e812355be7c8fe6fa973c38e6cd0e6efeca81bf9b4a914f9a7d42b453fac50c35a57
data/README.md CHANGED
@@ -11,6 +11,17 @@ You can include this package in your preferred base image to make that base imag
11
11
 
12
12
  ## Requirements
13
13
  The Ruby Runtime Interface Client package currently supports ruby 3.0 and above.
14
+
15
+ ## Migration from 2.x to 3.x
16
+
17
+ **Important**: Version 2.x is deprecated. Please upgrade to version 3.x. For more information about Lambda runtime support, see the [AWS Lambda runtimes documentation](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html).
18
+
19
+ **Breaking Change**: Version 3.0.0 introduced a change in how the handler is specified:
20
+
21
+ - **Version 2.x**: Handler was passed as a command line argument
22
+ - **Version 3.x+**: Handler must be specified via the `_HANDLER` environment variable
23
+
24
+ If you're upgrading from 2.x, update your Dockerfile to use the `_HANDLER` environment variable instead of relying on `CMD` arguments.
14
25
 
15
26
  ## Usage
16
27
 
@@ -39,7 +50,9 @@ Or install it manually as:
39
50
 
40
51
  The next step would be to copy your Lambda function code into the image's working directory.
41
52
  You will need to set the `ENTRYPOINT` property of the Docker image to invoke the Runtime Interface Client and
42
- then set the `CMD` argument to specify the desired handler.
53
+ set the `_HANDLER` environment variable to specify the desired handler.
54
+
55
+ **Important**: The Runtime Interface Client requires the handler to be specified via the `_HANDLER` environment variable.
43
56
 
44
57
  Example Dockerfile:
45
58
  ```dockerfile
@@ -57,23 +70,16 @@ RUN gem install bundler
57
70
  # Install the Runtime Interface Client
58
71
  RUN gem install aws_lambda_ric
59
72
 
60
- # If you want to install Runtime Interface Client From Source, you can uncomment the following `ADD` and `RUN` layers.
61
- # Do not forget to comment/remove the above `RUN gem install aws_lambda_ric` command.
62
- # ADD https://github.com/aws/aws-lambda-ruby-runtime-interface-client.git /aws_lambda_ric
63
- # RUN cd /aws_lambda_ric && \
64
- # make init && \
65
- # make build && \
66
- # gem install --local /aws_lambda_ric/pkg/aws_lambda_ric-3.0.0.gem && \
67
- # rm -rf /aws_lambda_ric
68
-
69
73
  # Copy function code
70
74
  RUN mkdir -p ${FUNCTION_DIR}
71
75
  COPY app.rb ${FUNCTION_DIR}
72
76
 
73
77
  WORKDIR ${FUNCTION_DIR}
74
78
 
79
+ # Set the handler via environment variable
80
+ ENV _HANDLER="app.App::Handler.process"
81
+
75
82
  ENTRYPOINT ["/usr/local/bin/aws_lambda_ric"]
76
- CMD ["app.App::Handler.process"]
77
83
  ```
78
84
 
79
85
  Note that the `ENTRYPOINT` may differ based on the base image used. You can find the correct path by running an
@@ -119,9 +125,10 @@ mkdir -p ~/.aws-lambda-rie && \
119
125
 
120
126
  ```shell script
121
127
  docker run -d -v ~/.aws-lambda-rie:/aws-lambda -p 9000:8080 \
128
+ -e _HANDLER="app.App::Handler.process" \
122
129
  --entrypoint /aws-lambda/aws-lambda-rie \
123
130
  myfunction:latest \
124
- /usr/local/bin/aws_lambda_ric app.App::Handler.process
131
+ /usr/local/bin/aws_lambda_ric
125
132
  ```
126
133
 
127
134
  This runs the image as a container and starts up an endpoint locally at `http://localhost:9000/2015-03-31/functions/function/invocations`.
@@ -136,6 +143,28 @@ This command invokes the function running in the container image and returns a r
136
143
 
137
144
  *Alternately, you can also include RIE as a part of your base image. See the AWS documentation on how to [Build RIE into your base image](https://docs.aws.amazon.com/lambda/latest/dg/images-test.html#images-test-alternative).*
138
145
 
146
+ ### Automated Local Testing
147
+
148
+ For a simple approach to run your local RIC changes, use the one-command setup:
149
+
150
+ ```shell script
151
+ make run-local-ric
152
+ ```
153
+
154
+ This command will:
155
+ 1. Build a Docker image with your local RIC code
156
+ 2. Compile the gem inside the Linux container (avoiding OS compatibility issues)
157
+ 3. Start the Lambda Runtime Interface Emulator on port 9000
158
+ 4. Run a test Lambda function using your RIC
159
+
160
+ Once running, invoke the function from another terminal:
161
+
162
+ ```shell script
163
+ curl -X POST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
164
+ ```
165
+
166
+ Modify the test handler in `test/integration/test-handlers/echo/app.rb` to test different scenarios.
167
+
139
168
  ## Development
140
169
 
141
170
  ### Building the package
@@ -157,6 +186,16 @@ Then,
157
186
  * to run integration tests: `make test-integ`
158
187
  * to run smoke tests: `make test-smoke`
159
188
 
189
+ ### Running Dockerized Harness Tests
190
+
191
+ To run the containerized test harness locally, use:
192
+
193
+ ```shell script
194
+ make test-dockerized RUBY_VERSION=3.4
195
+ ```
196
+
197
+ This command builds your Lambda function in a Docker container using the specified Ruby version, sets up the containerized test runner, and executes the test suites defined in `test/dockerized/suites/`.
198
+
160
199
  ### Troubleshooting
161
200
  While running integration tests, you might encounter the Docker Hub rate limit error with the following body:
162
201
  ```
@@ -31,6 +31,7 @@ Gem::Specification.new do |spec|
31
31
  spec.executables = 'aws_lambda_ric'
32
32
  spec.require_paths = ['lib']
33
33
 
34
+ spec.add_runtime_dependency "logger", ">= 1.4", "< 2.0"
34
35
  spec.add_development_dependency 'bundler', '~> 2.0'
35
36
  spec.add_development_dependency 'minitest', '~> 5.0'
36
37
  spec.add_development_dependency 'rake', '~> 13.0'
@@ -1,12 +1,69 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
3
4
  require 'logger'
4
5
 
5
6
  class LogFormatter < Logger::Formatter
6
7
  FORMAT = '%<sev>s, [%<datetime>s #%<process>d] %<severity>5s %<request_id>s -- %<progname>s: %<msg>s'
7
8
 
8
9
  def call(severity, time, progname, msg)
9
- (FORMAT % {sev: severity[0..0], datetime: format_datetime(time), process: $$, severity: severity,
10
- request_id: $_global_aws_request_id, progname: progname, msg: msg2str(msg)}).encode!('UTF-8')
10
+ formatted = FORMAT % {
11
+ sev: severity[0..0],
12
+ datetime: format_datetime(time),
13
+ process: $$,
14
+ severity: severity,
15
+ request_id: $_global_aws_request_id,
16
+ progname: progname,
17
+ msg: msg2str(msg)
18
+ }
19
+ "#{formatted.encode('UTF-8', invalid: :replace, undef: :replace, replace: '�')}\n"
20
+ end
21
+ end
22
+
23
+ class JsonLogFormatter < Logger::Formatter
24
+ DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%6NZ'
25
+
26
+ def call(severity, time, progname, msg)
27
+ payload = {
28
+ timestamp: time.utc.strftime(DATETIME_FORMAT),
29
+ level: severity,
30
+ message: message_for(msg),
31
+ requestId: $_global_aws_request_id
32
+ }
33
+
34
+ logger_name = sanitize_utf8(progname) unless progname.nil?
35
+ payload[:logger] = logger_name unless logger_name.nil? || logger_name.empty?
36
+
37
+ if msg.is_a?(Exception)
38
+ payload[:errorType] = msg.class.to_s
39
+ payload[:errorMessage] = sanitize_utf8(msg.message)
40
+ payload[:stackTrace] = Array(msg.backtrace).map { |line| sanitize_utf8(line) }
41
+ location = location_for(msg)
42
+ payload[:location] = location unless location.nil?
43
+ end
44
+
45
+ "#{JSON.generate(payload.compact)}\n"
46
+ end
47
+
48
+ private
49
+
50
+ def message_for(msg)
51
+ result = msg.is_a?(Exception) ? msg.message : msg2str(msg)
52
+ sanitize_utf8(result)
53
+ end
54
+
55
+ def location_for(exception)
56
+ first_backtrace_line = exception.backtrace&.first
57
+ return nil if first_backtrace_line.nil?
58
+
59
+ sanitized_line = sanitize_utf8(first_backtrace_line)
60
+ matched = sanitized_line.match(/\A(?<file>.+):(?<line>\d+):in [`'](?<method>.+)'\z/)
61
+ return "#{matched[:file]}:#{matched[:method]}:#{matched[:line]}" if matched
62
+
63
+ sanitized_line
64
+ end
65
+
66
+ def sanitize_utf8(value)
67
+ value.to_s.encode('UTF-8', invalid: :replace, undef: :replace, replace: '�')
11
68
  end
12
69
  end
@@ -1,19 +1,57 @@
1
1
  # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
2
 
3
+ # frozen_string_literal: true
4
+
5
+ require 'logger'
6
+ require_relative 'lambda_log_formatter'
7
+
3
8
  module LoggerPatch
4
- def initialize(logdev, shift_age = 0, shift_size = 1048576, level: 'debug',
5
- progname: nil, formatter: nil, datetime_format: nil,
6
- binmode: false, shift_period_suffix: '%Y%m%d')
7
- logdev_lambda_override = logdev
8
- formatter_override = formatter
9
- # use unpatched constructor if logdev is a filename or an IO Object other than $stdout or $stderr
9
+ LOG_LEVEL_MAP = {
10
+ 'TRACE' => Logger::DEBUG,
11
+ 'DEBUG' => Logger::DEBUG,
12
+ 'INFO' => Logger::INFO,
13
+ 'WARN' => Logger::WARN,
14
+ 'ERROR' => Logger::ERROR,
15
+ 'FATAL' => Logger::FATAL
16
+ }.freeze
17
+
18
+ class << self
19
+ attr_reader :aws_lambda_log_format, :aws_lambda_log_level
20
+
21
+ def refresh_runtime_config!
22
+ @aws_lambda_log_format = ENV.fetch('AWS_LAMBDA_LOG_FORMAT', '').upcase
23
+ env_level = ENV.fetch('AWS_LAMBDA_LOG_LEVEL', nil)
24
+ @aws_lambda_log_level = LOG_LEVEL_MAP[env_level&.upcase]
25
+ end
26
+
27
+ def json_format?
28
+ @aws_lambda_log_format == 'JSON'
29
+ end
30
+ end
31
+
32
+ refresh_runtime_config!
33
+
34
+ # shift_size default to 1 megabyte, matching Ruby Logger's default log rotation size.
35
+ def initialize(logdev, shift_age = 0, shift_size = 1_048_576, **kwargs)
36
+ level_was_provided = kwargs.key?(:level)
37
+ kwargs = {
38
+ level: Logger::DEBUG,
39
+ progname: nil,
40
+ formatter: nil,
41
+ datetime_format: nil,
42
+ binmode: false,
43
+ shift_period_suffix: '%Y%m%d'
44
+ }.merge(kwargs)
45
+
46
+ logdev_override = logdev
47
+
10
48
  if !logdev || logdev == $stdout || logdev == $stderr
11
- logdev_lambda_override = AwsLambdaRIC::TelemetryLogger.telemetry_log_sink
12
- formatter_override = formatter_override || LogFormatter.new
49
+ telemetry_sink = AwsLambdaRIC::TelemetryLogger.telemetry_log_sink
50
+ logdev_override = telemetry_sink || logdev
51
+ kwargs[:formatter] ||= LoggerPatch.json_format? ? JsonLogFormatter.new : LogFormatter.new
52
+ kwargs[:level] = LoggerPatch.aws_lambda_log_level if !level_was_provided && LoggerPatch.aws_lambda_log_level
13
53
  end
14
54
 
15
- super(logdev_lambda_override, shift_age, shift_size, level: level, progname: progname,
16
- formatter: formatter_override, datetime_format: datetime_format,
17
- binmode: binmode, shift_period_suffix: shift_period_suffix)
55
+ super(logdev_override, shift_age, shift_size, **kwargs)
18
56
  end
19
57
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AwsLambdaRIC
4
- VERSION = '3.1.3'
4
+ VERSION = '3.2.0'
5
5
  end
@@ -131,10 +131,19 @@ module AwsLambdaRIC
131
131
  ENV_VAR_TELEMETRY_LOG_FD = '_LAMBDA_TELEMETRY_LOG_FD'
132
132
 
133
133
  class << self
134
- attr_accessor :telemetry_log_fd_file, :telemetry_log_sink
135
-
134
+ attr_accessor :telemetry_log_fd_file, :telemetry_log_sink, :logger_patch_applied
136
135
  def close
137
136
  telemetry_log_fd_file&.close
137
+ self.telemetry_log_fd_file = nil
138
+ end
139
+
140
+ def mutate_std_logger
141
+ return if logger_patch_applied
142
+
143
+ Logger.class_eval do
144
+ prepend LoggerPatch
145
+ end
146
+ self.logger_patch_applied = true
138
147
  end
139
148
  end
140
149
 
@@ -145,28 +154,28 @@ module AwsLambdaRIC
145
154
 
146
155
  AwsLambdaRIC::TelemetryLogger.telemetry_log_sink = TelemetryLogSink.new(file: AwsLambdaRIC::TelemetryLogger.telemetry_log_fd_file)
147
156
 
148
- mutate_std_logger
149
157
  mutate_kernel_puts
158
+
150
159
  rescue Errno::ENOENT, Errno::EBADF
151
- # If File.open() fails, then the mutation won't happen and the default behaviour (print to stdout) will prevail
160
+ AwsLambdaRIC::TelemetryLogger.telemetry_log_fd_file = nil
161
+ AwsLambdaRIC::TelemetryLogger.telemetry_log_sink = nil
152
162
  end
153
163
 
154
164
  def self.from_env()
155
- if ENV.key?(ENV_VAR_TELEMETRY_LOG_FD)
156
- fd = ENV.fetch(AwsLambdaRIC::TelemetryLogger::ENV_VAR_TELEMETRY_LOG_FD)
157
- ENV.delete(AwsLambdaRIC::TelemetryLogger::ENV_VAR_TELEMETRY_LOG_FD)
158
- AwsLambdaRIC::TelemetryLogger.new(fd)
159
- end
160
- end
161
165
 
162
- private
166
+ LoggerPatch.refresh_runtime_config!
167
+ mutate_std_logger
168
+ AwsLambdaRIC::TelemetryLogger.telemetry_log_sink = nil
163
169
 
164
- def mutate_std_logger
165
- Logger.class_eval do
166
- prepend LoggerPatch
167
- end
170
+ return unless ENV.key?(ENV_VAR_TELEMETRY_LOG_FD)
171
+
172
+ fd = ENV.fetch(AwsLambdaRIC::TelemetryLogger::ENV_VAR_TELEMETRY_LOG_FD)
173
+ ENV.delete(AwsLambdaRIC::TelemetryLogger::ENV_VAR_TELEMETRY_LOG_FD)
174
+ AwsLambdaRIC::TelemetryLogger.new(fd)
168
175
  end
169
176
 
177
+ private
178
+
170
179
  def mutate_kernel_puts
171
180
  Kernel.module_eval do
172
181
  def puts(*arg)
@@ -180,7 +189,6 @@ module AwsLambdaRIC
180
189
  end
181
190
  end
182
191
  end
183
-
184
192
  # Represents a single Lambda Invocation Request
185
193
  class LambdaInvocationRequest
186
194
 
metadata CHANGED
@@ -1,15 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws_lambda_ric
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.3
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - AWS Lambda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-07-03 00:00:00.000000000 Z
11
+ date: 2026-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: logger
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '1.4'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
13
33
  - !ruby/object:Gem::Dependency
14
34
  name: bundler
15
35
  requirement: !ruby/object:Gem::Requirement