funktor 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +7 -0
  7. data/Gemfile.lock +84 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +154 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/exe/funktor +13 -0
  14. data/exe/funktor-deploy +8 -0
  15. data/funktor.gemspec +38 -0
  16. data/lib/funktor.rb +63 -0
  17. data/lib/funktor/active_job_handler.rb +52 -0
  18. data/lib/funktor/aws/sqs/event.rb +20 -0
  19. data/lib/funktor/aws/sqs/record.rb +14 -0
  20. data/lib/funktor/cli/application.rb +23 -0
  21. data/lib/funktor/cli/bootstrap.rb +35 -0
  22. data/lib/funktor/cli/generate.rb +0 -0
  23. data/lib/funktor/cli/generate/base.rb +13 -0
  24. data/lib/funktor/cli/generate/work_queue.rb +25 -0
  25. data/lib/funktor/cli/init.rb +78 -0
  26. data/lib/funktor/cli/templates/Gemfile +9 -0
  27. data/lib/funktor/cli/templates/config/environment.yml +4 -0
  28. data/lib/funktor/cli/templates/config/funktor.yml +51 -0
  29. data/lib/funktor/cli/templates/config/package.yml +9 -0
  30. data/lib/funktor/cli/templates/config/ruby_layer.yml +11 -0
  31. data/lib/funktor/cli/templates/function_definitions/active_job_handler.yml +11 -0
  32. data/lib/funktor/cli/templates/function_definitions/incoming_job_handler.yml +11 -0
  33. data/lib/funktor/cli/templates/funktor.yml.tt +51 -0
  34. data/lib/funktor/cli/templates/gitignore +2 -0
  35. data/lib/funktor/cli/templates/handlers/active_job_handler.rb +17 -0
  36. data/lib/funktor/cli/templates/handlers/incoming_job_handler.rb +8 -0
  37. data/lib/funktor/cli/templates/iam_permissions/active_job_queue.yml +8 -0
  38. data/lib/funktor/cli/templates/iam_permissions/incoming_job_queue.yml +8 -0
  39. data/lib/funktor/cli/templates/iam_permissions/ssm.yml +5 -0
  40. data/lib/funktor/cli/templates/package.json +1 -0
  41. data/lib/funktor/cli/templates/resources/active_job_queue.yml +22 -0
  42. data/lib/funktor/cli/templates/resources/cloudwatch_dashboard.yml +518 -0
  43. data/lib/funktor/cli/templates/resources/incoming_job_queue.yml +22 -0
  44. data/lib/funktor/cli/templates/resources/incoming_job_queue_user.yml +26 -0
  45. data/lib/funktor/cli/templates/serverless.yml +54 -0
  46. data/lib/funktor/cli/templates/workers/hello_worker.rb +8 -0
  47. data/lib/funktor/deploy/cli.rb +42 -0
  48. data/lib/funktor/deploy/serverless.rb +60 -0
  49. data/lib/funktor/deploy/serverless_templates/serverless.yml +156 -0
  50. data/lib/funktor/fake_job_queue.rb +15 -0
  51. data/lib/funktor/incoming_job_handler.rb +39 -0
  52. data/lib/funktor/job.rb +76 -0
  53. data/lib/funktor/middleware/metrics.rb +51 -0
  54. data/lib/funktor/middleware_chain.rb +62 -0
  55. data/lib/funktor/testing.rb +69 -0
  56. data/lib/funktor/version.rb +3 -0
  57. data/lib/funktor/worker.rb +86 -0
  58. metadata +173 -0
@@ -0,0 +1,11 @@
1
+ handler: handlers/incoming_job_handler.call
2
+ timeout: ${self:custom.funktor.incomingJobHandler.timeout, 30}
3
+ reservedConcurrency: ${self:custom.funktor.incomingJobHandler.reservedConcurrency, null}
4
+ provisionedConcurrency: ${self:custom.funktor.incomingJobHandler.provisionedConcurrency, null}
5
+ memorySize: ${self:custom.funktor.incomingJobHandler.memorySize, 256}
6
+ events:
7
+ - sqs:
8
+ arn:
9
+ Fn::GetAtt:
10
+ - IncomingJobQueue
11
+ - Arn
@@ -0,0 +1,51 @@
1
+ # ℹ️ WARNING: This file doesn't control anything directly. It's used to allow you to set/maintain config options in a central place.
2
+ # When you make changes to this file you should run `funktor init` again to propagate the changes to the 'active' configuration files.
3
+ runtime: ruby2.7
4
+
5
+ # Incoming Job Handler
6
+ incoming_job_handler:
7
+ # Use memory_size to adjust the reousrces (both memory and CPU) available
8
+ # memory_size: 512
9
+ timeout_in_seconds: 20 # This handler might have to handle several incoming jobs at once
10
+ # WARNING : You probably don't want to limit concurrency on incoming jobs.
11
+ # concurrency: 100
12
+
13
+ # Delayed Job Activator
14
+ delayed_job_activator:
15
+ # Use memory_size to adjust the reousrces (both memory and CPU) available
16
+ # memory_size: 512
17
+ execution_schedule: rate(1 minute)
18
+ activation_window_in_seconds: 120 # Activate any jobs scheduled for the next two minutes
19
+ timeout_in_seconds: 300 # Allow an activation job to run for up to 5 minutes
20
+ concurrency: 1
21
+
22
+
23
+ queues:
24
+ default:
25
+ # Use memory_size to adjust the reousrces (both memory and CPU) available
26
+ # memory_size: 512
27
+ # You can set the batch size. Max of 10_000 for normal queues, 10 for FIFO.
28
+ # batch_size: 10
29
+ # How many seconds should AWS wait for a batch to fill up before executing lambda?
30
+ # For immediate execution set the batch size to 1.
31
+ # maximumBatchingWindow : 1
32
+ # A single handler can receive up to batch_size jobs at a time. Make sure timeout is long enough.
33
+ timeout_in_seconds: 300
34
+ # You might want to limit concurrency of executing jobs to stay within resource limits (like DB connections).
35
+ # concurrency: 10
36
+ # Visibility timeout should only come into play in the case of Funktor errors.
37
+ # Application level errors should be handled by Funktor retry mechanisms.
38
+ # The visibility timeout should be at least as long as the function timeout, and up to 6 times larger.
39
+ # visibility_timeout: 300
40
+ # TODO - Is it advisable to use FIFO queuues with Funktor?
41
+ # TODO - Maybe this isn't really even supported by CloudFormation?
42
+ # fifo: false
43
+
44
+ # TODO - Maybe this is handled in the Dockerfile?
45
+ package:
46
+ patterns:
47
+ - Gemfile
48
+ - Gemfile.lock
49
+ - ../app/**
50
+ - ../config/**
51
+ - ../lambda_handlers/**
@@ -0,0 +1,2 @@
1
+ .serverless
2
+ node_modules
@@ -0,0 +1,17 @@
1
+ require 'funktor'
2
+
3
+ # Bundler is hard to make work because AWS includes some gems in the basic ruby runtime.
4
+ # We're probably going to need to use containers...
5
+ #require "rubygems"
6
+ #require "bundler/setup"
7
+ #Bundler.require(:default)
8
+
9
+ # TODO : Ideally this wouldn't be needed
10
+ require_relative '../workers/hello_worker'
11
+
12
+ $handler = Funktor::ActiveJobHandler.new
13
+
14
+ def call(event:, context:)
15
+ $handler.call(event: event, context: context)
16
+ end
17
+
@@ -0,0 +1,8 @@
1
+ require 'funktor'
2
+
3
+ $handler = Funktor::IncomingJobHandler.new
4
+
5
+ def call(event:, context:)
6
+ $handler.call(event: event, context: context)
7
+ end
8
+
@@ -0,0 +1,8 @@
1
+ Effect: Allow
2
+ Action:
3
+ - sqs:ReceiveMessage
4
+ - sqs:DeleteMessage
5
+ - sqs:SendMessage
6
+ - sqs:GetQueueAttributes
7
+ Resource:
8
+ - "Fn::GetAtt": [ ActiveJobQueue, Arn ]
@@ -0,0 +1,8 @@
1
+ Effect: Allow
2
+ Action:
3
+ - sqs:ReceiveMessage
4
+ - sqs:DeleteMessage
5
+ - sqs:SendMessage
6
+ - sqs:GetQueueAttributes
7
+ Resource:
8
+ - "Fn::GetAtt": [ IncomingJobQueue, Arn ]
@@ -0,0 +1,5 @@
1
+ Effect: Allow
2
+ Action:
3
+ - ssm:Get*
4
+ Resource:
5
+ - '*' # TODO : This should probably be more selective...
@@ -0,0 +1 @@
1
+ {"name":"serverless-sub","description":"","version":"0.1.0","devDependencies":{"serverless-ruby-layer":"^1.4.0"}}
@@ -0,0 +1,22 @@
1
+ Resources:
2
+ ActiveJobQueue:
3
+ Type: AWS::SQS::Queue
4
+ Properties:
5
+ QueueName: ${self:custom.funktor.activeJobQueueName}
6
+ VisibilityTimeout: 300
7
+ RedrivePolicy:
8
+ deadLetterTargetArn:
9
+ "Fn::GetAtt": [ ActiveJobDeadLetterQueue, Arn ]
10
+ maxReceiveCount: 5
11
+ ActiveJobDeadLetterQueue:
12
+ Type: AWS::SQS::Queue
13
+ Properties:
14
+ QueueName: ${self:custom.funktor.deadJobQueueName}
15
+
16
+ Outputs:
17
+ ActiveJobQueueUrl:
18
+ Value:
19
+ Ref: ActiveJobQueue
20
+ ActiveJobDeadLetterQueueUrl:
21
+ Value:
22
+ Ref: ActiveJobDeadLetterQueue
@@ -0,0 +1,518 @@
1
+ Resources:
2
+ FunktorDashboard:
3
+ Type: AWS::CloudWatch::Dashboard
4
+ Properties:
5
+ DashboardName: ${self:custom.funktor.dashboardName}
6
+ DashboardBody: >
7
+ {
8
+ "widgets": [
9
+ {
10
+ "height": 6,
11
+ "width": 9,
12
+ "y": 3,
13
+ "x": 0,
14
+ "type": "metric",
15
+ "properties": {
16
+ "metrics": [
17
+ [ "AWS/SQS", "NumberOfMessagesReceived", "QueueName", "${self:custom.funktor.incomingJobQueueName}", { "label": "Received" } ],
18
+ [ ".", "NumberOfMessagesDeleted", ".", ".", { "label": "Handled" } ],
19
+ [ "AWS/Lambda", "Invocations", "FunctionName", "${self:service}-${self:provider.stage}-incoming_job_handler", "Resource", "${self:service}-${self:provider.stage}-incoming_job_handler", { "label": "Handler Invocations" } ],
20
+ [ "AWS/SQS", "ApproximateNumberOfMessagesVisible", "QueueName", "${self:custom.funktor.incomingJobQueueName}", { "label": "Pending?" } ],
21
+ [ ".", "ApproximateNumberOfMessagesNotVisible", ".", ".", { "label": "Backlog?" } ],
22
+ [ ".", "NumberOfMessagesSent", ".", ".", { "label": "Sent" } ],
23
+ [ ".", "ApproximateNumberOfMessagesDelayed", ".", ".", { "label": "Delayed" } ]
24
+ ],
25
+ "view": "timeSeries",
26
+ "stacked": false,
27
+ "region": "us-east-1",
28
+ "title": "Incoming Job Queue (Async & scheduled jobs land here first)",
29
+ "period": 60,
30
+ "stat": "Sum",
31
+ "setPeriodToTimeRange": true,
32
+ "liveData": true
33
+ }
34
+ },
35
+ {
36
+ "height": 6,
37
+ "width": 9,
38
+ "y": 12,
39
+ "x": 0,
40
+ "type": "metric",
41
+ "properties": {
42
+ "metrics": [
43
+ [ "AWS/SQS", "NumberOfMessagesReceived", "QueueName", "${self:custom.funktor.activeJobQueueName}", { "label": "Received" } ],
44
+ [ ".", "NumberOfMessagesDeleted", ".", ".", { "label": "Handled" } ],
45
+ [ "AWS/Lambda", "Invocations", "FunctionName", "${self:service}-${self:provider.stage}-activeJobHandler", "Resource", "${self:service}-${self:provider.stage}-activeJobHandler", { "label": "Handler Invocations" } ],
46
+ [ "AWS/SQS", "ApproximateNumberOfMessagesVisible", "QueueName", "${self:custom.funktor.activeJobQueueName}", { "label": "Pending?" } ],
47
+ [ ".", "ApproximateNumberOfMessagesNotVisible", ".", ".", { "label": "Backlog?" } ],
48
+ [ ".", "NumberOfMessagesSent", ".", ".", { "label": "Sent" } ],
49
+ [ ".", "ApproximateNumberOfMessagesDelayed", ".", ".", { "label": "Delayed" } ]
50
+ ],
51
+ "view": "timeSeries",
52
+ "stacked": false,
53
+ "region": "us-east-1",
54
+ "title": "Active Job Queue (Async jobs go here immediately, scheduled jobs land here in the minute before they're scheduled)",
55
+ "period": 60,
56
+ "stat": "Sum",
57
+ "liveData": true
58
+ }
59
+ },
60
+ {
61
+ "height": 3,
62
+ "width": 9,
63
+ "y": 30,
64
+ "x": 0,
65
+ "type": "metric",
66
+ "properties": {
67
+ "metrics": [
68
+ [ { "expression": "m2/PERIOD(m2)", "label": "Consumed Read Capacity Units", "id": "e1", "stat": "Sum", "region": "us-east-1" } ],
69
+ [ "AWS/DynamoDB", "ConsumedReadCapacityUnits", "TableName", "${self:service}-${self:custom.stage}-delayed-jobs", { "id": "m2", "visible": false } ],
70
+ [ ".", "ConsumedWriteCapacityUnits", ".", ".", { "yAxis": "left", "id": "m4", "visible": false } ],
71
+ [ ".", "WriteThrottleEvents", ".", ".", { "yAxis": "right", "id": "m5", "visible": false } ]
72
+ ],
73
+ "view": "timeSeries",
74
+ "stacked": false,
75
+ "region": "us-east-1",
76
+ "title": "Scheduled Job Table Read Capacity Units",
77
+ "period": 60,
78
+ "stat": "Sum",
79
+ "liveData": true
80
+ }
81
+ },
82
+ {
83
+ "height": 3,
84
+ "width": 18,
85
+ "y": 33,
86
+ "x": 0,
87
+ "type": "metric",
88
+ "properties": {
89
+ "metrics": [
90
+ [ "AWS/DynamoDB", "SuccessfulRequestLatency", "TableName", "${self:service}-${self:custom.stage}-delayed-jobs", "Operation", "PutItem", { "yAxis": "left" } ],
91
+ [ "...", "Query" ],
92
+ [ ".", "ThrottledRequests", ".", ".", ".", "PutItem", { "yAxis": "right", "visible": false } ],
93
+ [ ".", "SuccessfulRequestLatency", ".", ".", ".", "DeleteItem" ],
94
+ [ ".", "ThrottledRequests", ".", ".", ".", ".", { "yAxis": "right", "visible": false } ]
95
+ ],
96
+ "view": "timeSeries",
97
+ "stacked": false,
98
+ "region": "us-east-1",
99
+ "stat": "Average",
100
+ "period": 60,
101
+ "title": "Scheduled Job Table Latency",
102
+ "liveData": true
103
+ }
104
+ },
105
+ {
106
+ "height": 3,
107
+ "width": 6,
108
+ "y": 33,
109
+ "x": 18,
110
+ "type": "metric",
111
+ "properties": {
112
+ "metrics": [
113
+ [ "AWS/DynamoDB", "ThrottledRequests", "TableName", "${self:service}-${self:custom.stage}-delayed-jobs", "Operation", "DeleteItem" ],
114
+ [ "...", "PutItem" ]
115
+ ],
116
+ "view": "timeSeries",
117
+ "stacked": false,
118
+ "region": "us-east-1",
119
+ "stat": "Sum",
120
+ "period": 60,
121
+ "title": "Scheduled Job Table Throttled Operations",
122
+ "liveData": true
123
+ }
124
+ },
125
+ {
126
+ "height": 6,
127
+ "width": 9,
128
+ "y": 3,
129
+ "x": 9,
130
+ "type": "metric",
131
+ "properties": {
132
+ "period": 60,
133
+ "metrics": [
134
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:service}-${self:provider.stage}-incoming_job_handler", { "stat": "Minimum" } ],
135
+ [ "...", { "stat": "Average" } ],
136
+ [ "...", { "stat": "Maximum" } ]
137
+ ],
138
+ "region": "us-east-1",
139
+ "title": "Incoming Job Handler Duration in Milliseconds",
140
+ "view": "timeSeries",
141
+ "stacked": false,
142
+ "liveData": true
143
+ }
144
+ },
145
+ {
146
+ "height": 3,
147
+ "width": 6,
148
+ "y": 3,
149
+ "x": 18,
150
+ "type": "metric",
151
+ "properties": {
152
+ "period": 60,
153
+ "metrics": [
154
+ [ "AWS/Lambda", "Errors", "FunctionName", "${self:service}-${self:provider.stage}-incoming_job_handler", { "id": "errors", "stat": "Sum", "color": "#d13212" } ],
155
+ [ ".", "Invocations", ".", ".", { "id": "invocations", "stat": "Sum", "visible": false } ],
156
+ [ { "expression": "100 - 100 * errors / MAX([errors, invocations])", "label": "Success rate (%)", "id": "availability", "yAxis": "right", "region": "us-east-1" } ]
157
+ ],
158
+ "region": "us-east-1",
159
+ "title": "Incoming Job Handler Error count and success rate (%)",
160
+ "yAxis": {
161
+ "right": {
162
+ "max": 100
163
+ }
164
+ },
165
+ "view": "timeSeries",
166
+ "stacked": false,
167
+ "liveData": true
168
+ }
169
+ },
170
+ {
171
+ "height": 3,
172
+ "width": 6,
173
+ "y": 6,
174
+ "x": 18,
175
+ "type": "metric",
176
+ "properties": {
177
+ "period": 60,
178
+ "metrics": [
179
+ [ "AWS/Lambda", "ConcurrentExecutions", "FunctionName", "${self:service}-${self:provider.stage}-incoming_job_handler", { "stat": "Maximum" } ]
180
+ ],
181
+ "region": "us-east-1",
182
+ "title": "Incoming Job Handler Concurrent Executions",
183
+ "view": "timeSeries",
184
+ "stacked": false,
185
+ "liveData": true
186
+ }
187
+ },
188
+ {
189
+ "height": 6,
190
+ "width": 9,
191
+ "y": 12,
192
+ "x": 9,
193
+ "type": "metric",
194
+ "properties": {
195
+ "period": 60,
196
+ "metrics": [
197
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:service}-${self:provider.stage}-active_job_handler", { "stat": "Minimum" } ],
198
+ [ "...", { "stat": "Average" } ],
199
+ [ "...", { "stat": "Maximum" } ]
200
+ ],
201
+ "region": "us-east-1",
202
+ "title": "Active Job Handler Duration in Milliseconds",
203
+ "view": "timeSeries",
204
+ "stacked": false,
205
+ "liveData": true
206
+ }
207
+ },
208
+ {
209
+ "height": 3,
210
+ "width": 6,
211
+ "y": 12,
212
+ "x": 18,
213
+ "type": "metric",
214
+ "properties": {
215
+ "period": 60,
216
+ "metrics": [
217
+ [ "AWS/Lambda", "Errors", "FunctionName", "${self:service}-${self:provider.stage}-active_job_handler", { "id": "errors", "stat": "Sum", "color": "#d13212" } ],
218
+ [ ".", "Invocations", ".", ".", { "id": "invocations", "stat": "Sum", "visible": false } ],
219
+ [ { "expression": "100 - 100 * errors / MAX([errors, invocations])", "label": "Success rate (%)", "id": "availability", "yAxis": "right", "region": "us-east-1" } ]
220
+ ],
221
+ "region": "us-east-1",
222
+ "title": "Active Job HandlerError count and success rate (%)",
223
+ "yAxis": {
224
+ "right": {
225
+ "max": 100
226
+ }
227
+ },
228
+ "view": "timeSeries",
229
+ "stacked": false,
230
+ "liveData": true
231
+ }
232
+ },
233
+ {
234
+ "height": 3,
235
+ "width": 6,
236
+ "y": 15,
237
+ "x": 18,
238
+ "type": "metric",
239
+ "properties": {
240
+ "period": 60,
241
+ "metrics": [
242
+ [ "AWS/Lambda", "ConcurrentExecutions", "FunctionName", "${self:service}-${self:provider.stage}-active_job_handler", { "stat": "Maximum" } ]
243
+ ],
244
+ "region": "us-east-1",
245
+ "title": "Active Job Handler Concurrent executions",
246
+ "view": "timeSeries",
247
+ "stacked": false,
248
+ "liveData": true
249
+ }
250
+ },
251
+ {
252
+ "height": 3,
253
+ "width": 9,
254
+ "y": 27,
255
+ "x": 9,
256
+ "type": "metric",
257
+ "properties": {
258
+ "period": 60,
259
+ "metrics": [
260
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:service}-${self:provider.stage}-delayed_job_scheduler", { "stat": "Minimum" } ],
261
+ [ "...", { "stat": "Average" } ],
262
+ [ "...", { "stat": "Maximum" } ]
263
+ ],
264
+ "region": "us-east-1",
265
+ "title": "Delayed Job Scheduler Duration",
266
+ "view": "timeSeries",
267
+ "stacked": false,
268
+ "liveData": true
269
+ }
270
+ },
271
+ {
272
+ "height": 3,
273
+ "width": 6,
274
+ "y": 27,
275
+ "x": 18,
276
+ "type": "metric",
277
+ "properties": {
278
+ "period": 60,
279
+ "metrics": [
280
+ [ "AWS/Lambda", "Errors", "FunctionName", "${self:service}-${self:provider.stage}-delayed_job_scheduler", { "id": "errors", "stat": "Sum", "color": "#d13212" } ],
281
+ [ ".", "Invocations", ".", ".", { "id": "invocations", "stat": "Sum", "visible": false } ],
282
+ [ { "expression": "100 - 100 * errors / MAX([errors, invocations])", "label": "Success rate (%)", "id": "availability", "yAxis": "right", "region": "us-east-1" } ]
283
+ ],
284
+ "region": "us-east-1",
285
+ "title": "Delayed Job SchedulerError count and success rate (%)",
286
+ "yAxis": {
287
+ "right": {
288
+ "max": 100
289
+ }
290
+ },
291
+ "view": "timeSeries",
292
+ "stacked": false,
293
+ "liveData": true
294
+ }
295
+ },
296
+ {
297
+ "height": 3,
298
+ "width": 6,
299
+ "y": 30,
300
+ "x": 18,
301
+ "type": "metric",
302
+ "properties": {
303
+ "period": 60,
304
+ "metrics": [
305
+ [ "AWS/Lambda", "ConcurrentExecutions", "FunctionName", "${self:service}-${self:provider.stage}-delayed_job_scheduler", { "stat": "Maximum" } ]
306
+ ],
307
+ "region": "us-east-1",
308
+ "title": "Delayd Job Schedule Concurrent executions",
309
+ "view": "timeSeries",
310
+ "stacked": false,
311
+ "liveData": true
312
+ }
313
+ },
314
+ {
315
+ "height": 3,
316
+ "width": 9,
317
+ "y": 27,
318
+ "x": 0,
319
+ "type": "metric",
320
+ "properties": {
321
+ "metrics": [
322
+ [ "AWS/DynamoDB", "ReturnedItemCount", "TableName", "${self:service}-${self:custom.stage}-delayed-jobs", "Operation", "Query" ]
323
+ ],
324
+ "view": "timeSeries",
325
+ "stacked": false,
326
+ "region": "us-east-1",
327
+ "title": "Delayed Jobs To Be Executed In The Next 90 Seconds",
328
+ "period": 60,
329
+ "stat": "Average",
330
+ "liveData": true
331
+ }
332
+ },
333
+ {
334
+ "height": 3,
335
+ "width": 6,
336
+ "y": 0,
337
+ "x": 0,
338
+ "type": "text",
339
+ "properties": {
340
+ "markdown": "\n# Incoming Jobs\n"
341
+ }
342
+ },
343
+ {
344
+ "height": 3,
345
+ "width": 6,
346
+ "y": 9,
347
+ "x": 0,
348
+ "type": "text",
349
+ "properties": {
350
+ "markdown": "\n# Active Jobs\n"
351
+ }
352
+ },
353
+ {
354
+ "height": 3,
355
+ "width": 6,
356
+ "y": 24,
357
+ "x": 0,
358
+ "type": "text",
359
+ "properties": {
360
+ "markdown": "\n# Delayed Jobs\n"
361
+ }
362
+ },
363
+ {
364
+ "height": 3,
365
+ "width": 3,
366
+ "y": 0,
367
+ "x": 6,
368
+ "type": "metric",
369
+ "properties": {
370
+ "metrics": [
371
+ [ "AWS/SQS", "NumberOfMessagesReceived", "QueueName", "${self:custom.funktor.incomingJobQueueName}", { "label": "Messages Per Minute" } ]
372
+ ],
373
+ "view": "singleValue",
374
+ "region": "us-east-1",
375
+ "stat": "Sum",
376
+ "period": 60,
377
+ "title": "Messages Per Minute"
378
+ }
379
+ },
380
+ {
381
+ "height": 3,
382
+ "width": 3,
383
+ "y": 9,
384
+ "x": 6,
385
+ "type": "metric",
386
+ "properties": {
387
+ "metrics": [
388
+ [ "AWS/SQS", "NumberOfMessagesReceived", "QueueName", "${self:service}-${self:custom.stage}-active-jobs", { "label": "Messages Per Minute" } ]
389
+ ],
390
+ "view": "singleValue",
391
+ "region": "us-east-1",
392
+ "stat": "Sum",
393
+ "period": 60,
394
+ "title": "Messages Per Minute"
395
+ }
396
+ },
397
+ {
398
+ "height": 3,
399
+ "width": 15,
400
+ "y": 0,
401
+ "x": 9,
402
+ "type": "metric",
403
+ "properties": {
404
+ "metrics": [
405
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:service}-${self:provider.stage}-incoming_job_handler", "Resource", "${self:service}-${self:provider.stage}-incoming_job_handler", { "label": "p10" } ],
406
+ [ "...", { "label": "p50", "stat": "p50" } ],
407
+ [ "...", { "label": "p99", "stat": "p99" } ],
408
+ [ "...", { "label": "Average", "stat": "Average" } ]
409
+ ],
410
+ "view": "singleValue",
411
+ "region": "us-east-1",
412
+ "stat": "p10",
413
+ "period": 60,
414
+ "title": "Handler Duration"
415
+ }
416
+ },
417
+ {
418
+ "height": 3,
419
+ "width": 15,
420
+ "y": 9,
421
+ "x": 9,
422
+ "type": "metric",
423
+ "properties": {
424
+ "metrics": [
425
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:service}-${self:provider.stage}-active_job_handler", "Resource", "${self:service}-${self:provider.stage}-active_job_handler", { "label": "p10" } ],
426
+ [ "...", { "label": "p50", "stat": "p50" } ],
427
+ [ "...", { "label": "p99", "stat": "p99" } ],
428
+ [ "...", { "label": "Average", "stat": "Average" } ]
429
+ ],
430
+ "view": "singleValue",
431
+ "region": "us-east-1",
432
+ "stat": "p10",
433
+ "period": 60,
434
+ "title": "Handler Duration"
435
+ }
436
+ },
437
+ {
438
+ "height": 3,
439
+ "width": 3,
440
+ "y": 24,
441
+ "x": 6,
442
+ "type": "metric",
443
+ "properties": {
444
+ "metrics": [
445
+ [ "AWS/DynamoDB", "ReturnedItemCount", "TableName", "${self:service}-${self:custom.stage}-delayed-jobs", "Operation", "Query" ]
446
+ ],
447
+ "view": "singleValue",
448
+ "region": "us-east-1",
449
+ "stat": "Average",
450
+ "period": 60,
451
+ "title": "Messages To Be Scheduled"
452
+ }
453
+ },
454
+ {
455
+ "height": 3,
456
+ "width": 15,
457
+ "y": 24,
458
+ "x": 9,
459
+ "type": "metric",
460
+ "properties": {
461
+ "metrics": [
462
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:service}-${self:provider.stage}-delayed_job_scheduler", "Resource", "${self:service}-${self:provider.stage}-delayed_job_scheduler", { "label": "p10" } ],
463
+ [ "...", { "label": "p50", "stat": "p50" } ],
464
+ [ "...", { "label": "p99", "stat": "p99" } ],
465
+ [ "...", { "label": "Average", "stat": "Average" } ]
466
+ ],
467
+ "view": "singleValue",
468
+ "region": "us-east-1",
469
+ "stat": "p10",
470
+ "period": 60,
471
+ "title": "Handler Duration"
472
+ }
473
+ },
474
+ {
475
+ "height": 3,
476
+ "width": 9,
477
+ "y": 30,
478
+ "x": 9,
479
+ "type": "metric",
480
+ "properties": {
481
+ "metrics": [
482
+ [ { "expression": "m4/PERIOD(m4)", "label": "Consumed Read Capacity Units", "id": "e1", "stat": "Sum", "region": "us-east-1" } ],
483
+ [ "AWS/DynamoDB", "ConsumedReadCapacityUnits", "TableName", "${self:service}-${self:custom.stage}-delayed-jobs", { "id": "m2", "visible": false } ],
484
+ [ ".", "ConsumedWriteCapacityUnits", ".", ".", { "yAxis": "left", "id": "m4", "visible": false } ],
485
+ [ ".", "WriteThrottleEvents", ".", ".", { "yAxis": "right", "id": "m5", "visible": false } ]
486
+ ],
487
+ "view": "timeSeries",
488
+ "stacked": false,
489
+ "region": "us-east-1",
490
+ "title": "Scheduled Job Table Write Capacity Units",
491
+ "period": 60,
492
+ "stat": "Sum",
493
+ "liveData": true
494
+ }
495
+ },
496
+ {
497
+ "height": 6,
498
+ "width": 24,
499
+ "y": 18,
500
+ "x": 0,
501
+ "type": "metric",
502
+ "properties": {
503
+ "metrics": [
504
+ [ "rails-lambda-experiment", "Duration", "WorkerClassName", "HelloWorker" ],
505
+ [ "...", { "stat": "p99" } ],
506
+ [ "...", "HelloLaterWorker" ],
507
+ [ "...", { "stat": "p99" } ]
508
+ ],
509
+ "view": "timeSeries",
510
+ "stacked": false,
511
+ "region": "us-east-1",
512
+ "stat": "Average",
513
+ "period": 60,
514
+ "title": "Job Duration by Worker"
515
+ }
516
+ }
517
+ ]
518
+ }