yake 0.3.0 → 0.4.3

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
  SHA256:
3
- metadata.gz: 498a95a56043103e5ab1315fefef95a6f55a27136fe5013df544e3fe83ed77dc
4
- data.tar.gz: 92dfac92a9036c96ea622228795e268b906f156b526b1a1cb46313fa2f4af0c8
3
+ metadata.gz: 2d64b926e9680f75a892e5de6c68062242801d184bdbd24595a10210fbc7f22a
4
+ data.tar.gz: bf82c77421cec7c5b5d30020b15895ec111d8e53c0122ef6e62fa26856acb7ca
5
5
  SHA512:
6
- metadata.gz: b26c78cfe69bb588cf37bafeeacc53314e40106eb38416d6b52dd652e2a954c3767fb5c4f5852ea3d132558f69a6d512cfbc48f6c11f766e3a099a5bb7c95697
7
- data.tar.gz: c063851aac6c3554dd36a05db53e846d835019bf973c0b060b6cf673697350eeeba6d3ddb0585eaeed92fd165bf1767cf0f9fb0e514ef49c16de604f04783f03
6
+ metadata.gz: a99122212c84d638874ebd25e07d9f7305568fbdd18f95d04c8d44df1c337b75a81b37c55840d2366adf8ea05fe2cff35fbf876c082ab82dbf5f98b3511d8293
7
+ data.tar.gz: a76262d29fb1a173cb9293af7c5ce34e1089d181112aaf80d2d6a6b117141c89c63322b24074287d6b655d04e6d68d6499b51d46bae20555735ffd344b199761
data/README.md CHANGED
@@ -9,7 +9,7 @@ Write your AWS Lambda function handlers using a Rake-like declarative syntax:
9
9
 
10
10
  ```ruby
11
11
  # ./lambda_function.rb
12
- require "yake"
12
+ require 'yake'
13
13
 
14
14
  handler :lambda_handler do |event|
15
15
  # Your code here
@@ -22,11 +22,11 @@ You can even declare Sinatra-like API Gateway routes for a main entrypoint:
22
22
 
23
23
  ```ruby
24
24
  # ./lambda_function.rb
25
- require "yake/api"
25
+ require 'yake/api'
26
26
 
27
- header "content-type" => "application/json"
27
+ header 'content-type' => 'application/json'
28
28
 
29
- get "/fizz" do
29
+ get '/fizz' do
30
30
  respond 200, { ok: true }.to_json
31
31
  end
32
32
 
@@ -44,7 +44,7 @@ end
44
44
  Add this line to your application's Gemfile:
45
45
 
46
46
  ```ruby
47
- gem "yake"
47
+ gem 'yake'
48
48
  ```
49
49
 
50
50
  And then execute:
@@ -82,10 +82,12 @@ REPORT RequestId: 149c500f-028a-4b57-8977-0ef568cf8caf Duration: 43.97 ms Billed
82
82
 
83
83
  Logging the request ID in this way makes gathering logs lines for a particular execution in CloudWatch much easier.
84
84
 
85
- This feature can be disabled by adding a declaration in your handler file:
85
+ You can customize or disable the logger:
86
86
 
87
87
  ```ruby
88
- logging :off
88
+ logging :off # disables logging entirely
89
+ logging pretty: false # Logs event/result in compact JSON
90
+ logging :on, MyLogger.new # Use a custom logger
89
91
  ```
90
92
 
91
93
  Include `Yake::Logger` on a class to access this logger:
@@ -108,35 +110,35 @@ Requiring the `yake/api` module will add the API-specific DSL into your handler.
108
110
  Define API routes using Sinatra-like syntax
109
111
 
110
112
  ```ruby
111
- any "/…" do |event|
113
+ any '/…' do |event|
112
114
  # Handle 'ANY /…' route key events
113
115
  end
114
116
 
115
- delete "/…" do |event|
117
+ delete '/…' do |event|
116
118
  # Handle 'DELETE /…' route key events
117
119
  end
118
120
 
119
- get "/…" do |event|
121
+ get '/…' do |event|
120
122
  # Handle 'GET /…' route key events
121
123
  end
122
124
 
123
- head "/…" do |event|
125
+ head '/…' do |event|
124
126
  # Handle 'HEAD /…' route key events
125
127
  end
126
128
 
127
- options "/…" do |event|
129
+ options '/…' do |event|
128
130
  # Handle 'OPTIONS /…' route key events
129
131
  end
130
132
 
131
- patch "/…" do |event|
133
+ patch '/…' do |event|
132
134
  # Handle 'PATCH /…' route key events
133
135
  end
134
136
 
135
- post "/…" do |event|
137
+ post '/…' do |event|
136
138
  # Handle 'POST /…' route key events
137
139
  end
138
140
 
139
- put "/…" do |event|
141
+ put '/…' do |event|
140
142
  # Handle 'PUT /…' route key events
141
143
  end
142
144
  ```
@@ -146,14 +148,14 @@ Helper methods are also made available to help produce a response for API Gatewa
146
148
  Set a default header for ALL responses:
147
149
 
148
150
  ```ruby
149
- header "content-type" => "application/json; charset=utf-8"
150
- header "x-custom-header" => "fizz"
151
+ header 'content-type' => 'application/json; charset=utf-8'
152
+ header 'x-custom-header' => 'fizz'
151
153
  ```
152
154
 
153
155
  Produce an API Gateway-style response object:
154
156
 
155
157
  ```ruby
156
- respond 200, { ok: true }.to_json, "x-extra-header" => "buzz"
158
+ respond 200, { ok: true }.to_json, 'x-extra-header' => 'buzz'
157
159
  # {
158
160
  # "statusCode" => 200,
159
161
  # "body" => '{"ok":true}',
@@ -177,11 +179,35 @@ end
177
179
 
178
180
  Finally, `yake` does not depend on any other gems, using the Ruby stdlib only. This helps keep your Lambda packages slim & speedy.
179
181
 
180
- ## Development
182
+ ## Datadog Integration
183
+
184
+ As of `~> 0.4`, `yake` comes with a helper for writing Lambdas that integrate with Datadog's `datadog-ruby` gem.
181
185
 
182
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
186
+ Creating a Lambda handler that wraps the Datadog tooling is easy:
187
+
188
+ ```ruby
189
+ require 'aws-sdk-someservice'
190
+ require 'yake/datadog'
191
+
192
+ # Configure Datadog to use AWS tracing
193
+ Datadog::Lambda.configure_apm { |config| config.use :aws }
194
+
195
+ datadog :handler do |event|
196
+ # …
197
+ end
198
+ ```
199
+
200
+ ## Deployment
201
+
202
+ After writing your Lambda handler code you can deploy it to AWS using any number of tools. I recommend the following tools:
203
+
204
+ - [Terraform](https://www.terraform.io) — my personal favorite Infrastructure-as-Code tool
205
+ - [AWS SAM](https://aws.amazon.com/serverless/sam/) — a great alternative with less configuration than Terraform
206
+ - [Serverless](https://www.serverless.com) — Supposedly the most popular option, though I have not used it
207
+
208
+ ## Development
183
209
 
184
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
210
+ After checking out the repo, run `bundle` to install dependencies. Then, run `rake spec` to run the tests.
185
211
 
186
212
  ## Contributing
187
213
 
data/lib/yake/api.rb CHANGED
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "base64"
4
- require "json"
3
+ require 'base64'
4
+ require 'json'
5
5
 
6
- require "yake"
7
- require_relative "errors"
6
+ require 'yake'
7
+ require_relative 'errors'
8
8
 
9
9
  module Yake
10
10
  module API
@@ -13,20 +13,21 @@ module Yake
13
13
  # Proxy handler for HTTP requests from Slack
14
14
  def route(event, context = nil, &block)
15
15
  # Extract route method
16
- method = event["routeKey"]
16
+ method = event['routeKey']
17
17
  raise Yake::Errors::UndeclaredRoute, method unless respond_to?(method)
18
18
 
19
19
  # Normalize headers
20
- event["headers"]&.transform_keys!(&:downcase)
20
+ event['headers']&.transform_keys!(&:downcase)
21
21
 
22
22
  # Decode body if Base64-encoded
23
- if event["isBase64Encoded"]
24
- body = Base64.strict_decode64(event["body"])
25
- event.update("body" => body, "isBase64Encoded" => false)
23
+ if event['isBase64Encoded']
24
+ body = Base64.strict_decode64(event['body'])
25
+ event.update('body' => body, 'isBase64Encoded' => false)
26
26
  end
27
27
 
28
28
  # Execute request
29
- send(method, event, context).then { |res| block_given? ? yield(res) : res }
29
+ res = send(method, event, context)
30
+ block_given? ? yield(res) : res
30
31
  end
31
32
 
32
33
  ##
@@ -37,10 +38,10 @@ module Yake
37
38
  Yake.logger&.send(status_code.to_i >= 400 ? :error : :info, log)
38
39
 
39
40
  # Set headers
40
- content_length = (body&.length || 0).to_s
41
+ content_length = (body&.bytesize || 0).to_s
41
42
  to_s_downcase = -> (key) { key.to_s.downcase }
42
43
  headers = {
43
- "content-length" => content_length,
44
+ 'content-length' => content_length,
44
45
  **(@headers || {}),
45
46
  **headers,
46
47
  }.transform_keys(&to_s_downcase).compact
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+ require 'logger'
3
+
4
+ require 'datadog/lambda'
5
+ require 'yake'
6
+
7
+ module Yake
8
+ module Datadog
9
+ class Formatter < ::Logger::Formatter
10
+ Format = "[%s] %s %s %s %s\n"
11
+
12
+ def call(severity, time, progname, msg)
13
+ Format % [
14
+ severity,
15
+ time.utc.strftime('%Y-%m-%dT%H:%M:%S.%LZ'),
16
+ progname.nil? ? '-' : progname.split.last,
17
+ ::Datadog.tracer.active_correlation,
18
+ msg2str(msg).strip,
19
+ ]
20
+ end
21
+ end
22
+
23
+ class MockContext < Struct.new(
24
+ :clock_diff,
25
+ :deadline_ms,
26
+ :aws_request_id,
27
+ :invoked_function_arn,
28
+ :log_group_name,
29
+ :log_stream_name,
30
+ :function_name,
31
+ :memory_limit_in_mb,
32
+ :function_version)
33
+
34
+ def invoked_function_arn
35
+ @invoked_function_arn ||= begin
36
+ region = ENV['AWS_REGION'] || ENV['AWS_DEFAULT_REGION'] || 'us-east-1'
37
+ "arn:aws:lambda:#{region}:123456789012:function-name"
38
+ end
39
+ end
40
+ end
41
+
42
+ module DSL
43
+ include Yake::DSL
44
+
45
+ ##
46
+ # Datadog handler wrapper
47
+ def datadog(name, &block)
48
+ define_method(name) do |event:nil, context:nil|
49
+ context ||= MockContext.new
50
+ ::Datadog::Lambda.wrap(event, context) do
51
+ Yake.wrap(event, context, &block)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ logger.formatter = Datadog::Formatter.new
59
+ end
60
+
61
+ extend Yake::Datadog::DSL
data/lib/yake/dsl.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "json"
3
+ require 'json'
4
4
 
5
- require_relative "logger"
5
+ require_relative 'logger'
6
6
 
7
7
  module Yake
8
8
  module DSL
@@ -22,7 +22,8 @@ module Yake
22
22
 
23
23
  ##
24
24
  # Turn logging on/off
25
- def logging(switch, logger = nil)
25
+ def logging(switch = :on, logger = nil, pretty: true)
26
+ Yake.pretty = pretty
26
27
  if switch == :on
27
28
  Yake.logger = logger
28
29
  elsif switch == :off
data/lib/yake/errors.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Yake
2
4
  module Errors
3
5
  class Error < StandardError; end
data/lib/yake/logger.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "json"
4
- require "logger"
3
+ require 'json'
4
+ require 'logger'
5
5
 
6
6
  module Yake
7
7
  module Logger
8
- attr_accessor :logger
8
+ attr_writer :logger
9
9
 
10
10
  def logger
11
11
  @logger ||= Yake.logger
@@ -21,23 +21,30 @@ module Yake
21
21
  Format = "%s %s %s\n"
22
22
 
23
23
  def call(severity, time, progname, msg)
24
- Format % [ severity, progname.nil? ? "-" : "RequestId: #{ progname }", msg2str(msg).strip ]
24
+ Format % [ severity, progname.nil? ? '-' : "RequestId: #{ progname }", msg2str(msg).strip ]
25
25
  end
26
26
  end
27
27
  end
28
28
 
29
29
  class << self
30
- attr_accessor :logger
30
+ attr_writer :logger, :pretty
31
31
 
32
32
  def logger
33
33
  @logger ||= Logger.new
34
34
  end
35
35
 
36
+ def pretty?
37
+ @pretty != false
38
+ end
39
+
36
40
  def wrap(event = nil, context = nil, &block)
37
41
  original_progname = logger.progname
38
- logger.progname = context&.aws_request_id
39
- logger.info("EVENT #{ event.to_json }")
40
- yield(event, context).tap { |res| logger.info("RETURN #{ res.to_json }") }
42
+ logger.progname = context&.aws_request_id
43
+ jsonify = -> (obj) { pretty? ? JSON.pretty_generate(obj) : obj.to_json }
44
+ logger.info("EVENT #{ jsonify === event }")
45
+ yield(event, context).tap do |res|
46
+ logger.info("RETURN #{ jsonify === res }")
47
+ end
41
48
  ensure
42
49
  logger.progname = original_progname
43
50
  end
data/lib/yake/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Yake
4
- VERSION = "0.3.0"
4
+ VERSION = '0.4.3'
5
5
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yake
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Mancevice
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-28 00:00:00.000000000 Z
11
+ date: 2021-11-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description:
13
+ description:
14
14
  email:
15
15
  - alexander.mancevice@hey.com
16
16
  executables: []
@@ -18,10 +18,10 @@ extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
20
  - LICENSE
21
- - LICENSE.txt
22
21
  - README.md
23
22
  - lib/yake.rb
24
23
  - lib/yake/api.rb
24
+ - lib/yake/datadog.rb
25
25
  - lib/yake/dsl.rb
26
26
  - lib/yake/errors.rb
27
27
  - lib/yake/logger.rb
@@ -30,7 +30,7 @@ homepage: https://github.com/amancevice/yake
30
30
  licenses:
31
31
  - MIT
32
32
  metadata: {}
33
- post_install_message:
33
+ post_install_message:
34
34
  rdoc_options: []
35
35
  require_paths:
36
36
  - lib
@@ -45,8 +45,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0'
47
47
  requirements: []
48
- rubygems_version: 3.1.6
49
- signing_key:
48
+ rubygems_version: 3.2.32
49
+ signing_key:
50
50
  specification_version: 4
51
51
  summary: Rake-like DSL for declaring AWS Lambda function handlers
52
52
  test_files: []
data/LICENSE.txt DELETED
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2021 Alexander Mancevice
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.