funktor 0.4.7 → 0.6.2

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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.tool-versions +2 -0
  3. data/Gemfile.lock +31 -12
  4. data/funktor-testapp/.envrc +1 -0
  5. data/funktor-testapp/.gitignore +7 -0
  6. data/funktor-testapp/Gemfile +25 -0
  7. data/funktor-testapp/Gemfile.lock +51 -0
  8. data/funktor-testapp/app/services/job_flood.rb +38 -0
  9. data/funktor-testapp/app/workers/audit_worker.rb +49 -0
  10. data/funktor-testapp/app/workers/greetings_worker.rb +3 -0
  11. data/funktor-testapp/app/workers/hello_worker.rb +18 -0
  12. data/funktor-testapp/app/workers/single_thread_audit_worker.rb +3 -0
  13. data/funktor-testapp/deploy-dev.sh +5 -0
  14. data/funktor-testapp/funktor_config/boot.rb +17 -0
  15. data/funktor-testapp/funktor_config/environment.yml +15 -0
  16. data/funktor-testapp/funktor_config/function_definitions/default_queue_handler.yml +13 -0
  17. data/funktor-testapp/funktor_config/function_definitions/incoming_job_handler.yml +13 -0
  18. data/funktor-testapp/funktor_config/function_definitions/job_activator.yml +7 -0
  19. data/funktor-testapp/funktor_config/function_definitions/low_concurrency_queue_handler.yml +13 -0
  20. data/funktor-testapp/funktor_config/function_definitions/random_job_generator.yml +18 -0
  21. data/funktor-testapp/funktor_config/funktor.yml +114 -0
  22. data/funktor-testapp/funktor_config/iam_permissions/activity_table.yml +5 -0
  23. data/funktor-testapp/funktor_config/iam_permissions/default_queue.yml +8 -0
  24. data/funktor-testapp/funktor_config/iam_permissions/incoming_job_queue.yml +8 -0
  25. data/funktor-testapp/funktor_config/iam_permissions/jobs_table.yml +5 -0
  26. data/funktor-testapp/funktor_config/iam_permissions/jobs_table_secondary_index.yml +8 -0
  27. data/funktor-testapp/funktor_config/iam_permissions/low_concurrency_queue.yml +8 -0
  28. data/funktor-testapp/funktor_config/iam_permissions/ssm.yml +5 -0
  29. data/funktor-testapp/funktor_config/package.yml +11 -0
  30. data/funktor-testapp/funktor_config/resources/activity_table.yml +22 -0
  31. data/funktor-testapp/funktor_config/resources/cloudwatch_dashboard.yml +809 -0
  32. data/funktor-testapp/funktor_config/resources/default_queue.yml +22 -0
  33. data/funktor-testapp/funktor_config/resources/incoming_job_queue.yml +22 -0
  34. data/funktor-testapp/funktor_config/resources/incoming_job_queue_user.yml +26 -0
  35. data/funktor-testapp/funktor_config/resources/jobs_table.yml +56 -0
  36. data/funktor-testapp/funktor_config/resources/low_concurrency_queue.yml +22 -0
  37. data/funktor-testapp/funktor_config/ruby_layer.yml +11 -0
  38. data/funktor-testapp/funktor_init.yml +69 -0
  39. data/funktor-testapp/lambda_event_handlers/default_queue_handler.rb +8 -0
  40. data/funktor-testapp/lambda_event_handlers/incoming_job_handler.rb +8 -0
  41. data/funktor-testapp/lambda_event_handlers/job_activator.rb +8 -0
  42. data/funktor-testapp/lambda_event_handlers/low_concurrency_queue_handler.rb +8 -0
  43. data/funktor-testapp/lambda_event_handlers/random_job_generator.rb +35 -0
  44. data/funktor-testapp/package-lock.json +248 -0
  45. data/funktor-testapp/package.json +8 -0
  46. data/funktor-testapp/serverless.yml +66 -0
  47. data/funktor.gemspec +4 -1
  48. data/lib/active_job/queue_adapters/funktor_adapter.rb +3 -3
  49. data/lib/funktor/activity_tracker.rb +106 -0
  50. data/lib/funktor/cli/bootstrap.rb +0 -1
  51. data/lib/funktor/cli/init.rb +13 -0
  52. data/lib/funktor/cli/templates/app/workers/hello_worker.rb +1 -1
  53. data/lib/funktor/cli/templates/funktor_config/environment.yml +4 -0
  54. data/lib/funktor/cli/templates/funktor_config/function_definitions/incoming_job_handler.yml +3 -1
  55. data/lib/funktor/cli/templates/funktor_config/function_definitions/job_activator.yml +7 -0
  56. data/lib/funktor/cli/templates/funktor_config/function_definitions/work_queue_handler.yml +3 -1
  57. data/lib/funktor/cli/templates/funktor_config/funktor.yml +32 -6
  58. data/lib/funktor/cli/templates/funktor_config/iam_permissions/activity_table.yml +5 -0
  59. data/lib/funktor/cli/templates/funktor_config/iam_permissions/jobs_table.yml +5 -0
  60. data/lib/funktor/cli/templates/funktor_config/iam_permissions/jobs_table_secondary_index.yml +8 -0
  61. data/lib/funktor/cli/templates/funktor_config/resources/activity_table.yml +22 -0
  62. data/lib/funktor/cli/templates/funktor_config/resources/cloudwatch_dashboard.yml +13 -12
  63. data/lib/funktor/cli/templates/funktor_config/resources/incoming_job_queue.yml +2 -2
  64. data/lib/funktor/cli/templates/funktor_config/resources/jobs_table.yml +56 -0
  65. data/lib/funktor/cli/templates/funktor_config/resources/work_queue.yml +2 -2
  66. data/lib/funktor/cli/templates/funktor_init.yml.tt +16 -16
  67. data/lib/funktor/cli/templates/lambda_event_handlers/job_activator.rb +8 -0
  68. data/lib/funktor/cli/templates/lambda_event_handlers/work_queue_handler.rb +1 -1
  69. data/lib/funktor/cli/templates/serverless.yml +3 -2
  70. data/lib/funktor/counter.rb +4 -1
  71. data/lib/funktor/incoming_job_handler.rb +54 -18
  72. data/lib/funktor/job.rb +57 -7
  73. data/lib/funktor/job_activator.rb +124 -0
  74. data/lib/funktor/job_pusher.rb +0 -2
  75. data/lib/funktor/middleware/metrics.rb +8 -3
  76. data/lib/funktor/shard_utils.rb +6 -0
  77. data/lib/funktor/testing.rb +50 -47
  78. data/lib/funktor/version.rb +1 -1
  79. data/lib/funktor/web/application.rb +139 -0
  80. data/lib/funktor/web/views/index.erb +3 -0
  81. data/lib/funktor/web/views/layout.erb +58 -0
  82. data/lib/funktor/web/views/processing.erb +29 -0
  83. data/lib/funktor/web/views/queued.erb +29 -0
  84. data/lib/funktor/web/views/retries.erb +35 -0
  85. data/lib/funktor/web/views/scheduled.erb +26 -0
  86. data/lib/funktor/web/views/stats.erb +9 -0
  87. data/lib/funktor/web/views/table_stats_with_buttons.erb +11 -0
  88. data/lib/funktor/web.rb +1 -0
  89. data/lib/funktor/work_queue_handler.rb +101 -0
  90. data/lib/funktor/worker/funktor_options.rb +3 -1
  91. data/lib/funktor/worker.rb +8 -18
  92. data/lib/funktor.rb +52 -20
  93. metadata +109 -3
  94. data/lib/funktor/active_job_handler.rb +0 -58
@@ -0,0 +1,114 @@
1
+ IncomingJobHandler:
2
+ # timeout is how long the handler can possibly run. Up to 10 messages may be delivered
3
+ # to a handler at one time, so you'll want this to be at least 10x the maximum time you
4
+ # expect to spend for one message. The incoming job handler usually will be pretty fast,
5
+ # but we default to a high number here to allow for the times when things go weird.
6
+ functionTimeout: 300
7
+ # reservedConcurrency represents the maximum number of concurrent executions.
8
+ # For the incoming job handler you probably don't want to limit it because you
9
+ # want to get things onto work queues as quickly as possible.
10
+ reservedConcurrency: null
11
+ # provisionedConcurrency represents the number of lambda functions that will always
12
+ # be available. For the incoming jobs handler you probably don't need to set this
13
+ # unless your jobs are very bursty AND very time sensitive.
14
+ provisionedConcurrency: null
15
+ # Use memory_size to adjust the reousrces (both memory and CPU) available.
16
+ # For the incoming jobs handler you probably don't need this to be too large,
17
+ # but if you're seeing large delays at this stage it might help to bump it up.
18
+ memorySize: 256
19
+ batchSize: 1
20
+ maximumBatchingWindow: 0
21
+ visibilityTimeout: 1800
22
+ maxReceiveCount: 20
23
+
24
+ JobActivator:
25
+ # timeout is how long the handler can possibly run. Up to 10 messages may be delivered
26
+ # to a handler at one time, so you'll want this to be at least 10x the maximum time you
27
+ # expect to spend for one message. The job activator usually will be pretty fast,
28
+ # but we default to a high number here to allow for the times when things go weird.
29
+ functionTimeout: 300
30
+ # reservedConcurrency represents the maximum number of concurrent executions.
31
+ # For the job activator you probably don't want to limit it because you
32
+ # want to get things onto work queues as quickly as possible when they're ready.
33
+ reservedConcurrency: null
34
+ # provisionedConcurrency represents the number of lambda functions that will always
35
+ # be available. For the job activator you probably don't need to set this
36
+ # since it will be running on a schedule
37
+ provisionedConcurrency: null
38
+ # Use memory_size to adjust the reousrces (both memory and CPU) available.
39
+ # For the job activator you probably don't need this to be too large,
40
+ # but if you're seeing large delays at this stage it might help to bump it up.
41
+ memorySize: 256
42
+ batchSize: 1
43
+ maximumBatchingWindow: 0
44
+ visibilityTimeout: 1800
45
+ maxReceiveCount: 20
46
+
47
+
48
+
49
+ DefaultQueueHandler:
50
+ # timeout is how long the handler can possibly run. Up to 10 messages may be delivered
51
+ # to a handler at one time, so you'll want this to be at least 10x the maximum time you
52
+ # expect to spend for one message. The active job handler may be slow if your jobs are
53
+ # doing a lot of work, so we default to the maximum here.
54
+ functionTimeout: 300
55
+ # reservedConcurrency represents the maximum number of concurrent executions.
56
+ # For the active job handler you may want to limit it if you have resource limitations
57
+ # like database connections that you need to avoid exhausting.
58
+ reservedConcurrency: null
59
+ # provisionedConcurrency represents the number of lambda functions that will always
60
+ # be available. For the active job handler you probably don't need to set this
61
+ # unless your jobs are very bursty AND very time sensitive.
62
+ provisionedConcurrency: null
63
+ # Use memory_size to adjust the reousrces (both memory and CPU) available.
64
+ # For the active jobs handler you'll want this to be at least as large as the memory
65
+ # required to actually do your jobs. You can choose an even higher number to increase
66
+ # the available CPU to make the jobs run faster.
67
+ memorySize: 256
68
+ batchSize: 1
69
+ maximumBatchingWindow: 0
70
+ visibilityTimeout: 1800
71
+ maxReceiveCount: 20
72
+
73
+ LowConcurrencyQueueHandler:
74
+ # timeout is how long the handler can possibly run. Up to 10 messages may be delivered
75
+ # to a handler at one time, so you'll want this to be at least 10x the maximum time you
76
+ # expect to spend for one message. The active job handler may be slow if your jobs are
77
+ # doing a lot of work, so we default to the maximum here.
78
+ functionTimeout: 300
79
+ # reservedConcurrency represents the maximum number of concurrent executions.
80
+ # For the active job handler you may want to limit it if you have resource limitations
81
+ # like database connections that you need to avoid exhausting.
82
+ reservedConcurrency: 10
83
+ # provisionedConcurrency represents the number of lambda functions that will always
84
+ # be available. For the active job handler you probably don't need to set this
85
+ # unless your jobs are very bursty AND very time sensitive.
86
+ provisionedConcurrency: null
87
+ # Use memory_size to adjust the reousrces (both memory and CPU) available.
88
+ # For the active jobs handler you'll want this to be at least as large as the memory
89
+ # required to actually do your jobs. You can choose an even higher number to increase
90
+ # the available CPU to make the jobs run faster.
91
+ memorySize: 256
92
+ batchSize: 1
93
+ maximumBatchingWindow: 0
94
+ visibilityTimeout: 1800
95
+ maxReceiveCount: 20
96
+
97
+
98
+
99
+ # You shouldn't need to mess with these under most circumstances. But you could if you want to change
100
+ # the name of some of your resources in AWS.
101
+ IncomingJobQueueName: ${self:service}-${self:custom.stage}-incoming-jobs
102
+ IncomingDeadJobQueueName: ${self:service}-${self:custom.stage}-incoming-dead
103
+ IncomingJobHandlerName: ${self:service}-${self:custom.stage}-IncomingJobHandler
104
+ IncomingJobQueueAccessPolicyName: ${self:service}-${self:custom.stage}-incoming-job-queue-access
105
+ DashboardName: ${self:service}-${self:custom.stage}-dashboard
106
+ DefaultQueueName: ${self:service}-${self:custom.stage}-default
107
+ DefaultDeadJobQueueName: ${self:service}-${self:custom.stage}-default-dead
108
+ DefaultQueueHandlerName: ${self:service}-${self:custom.stage}-DefaultQueueHandler
109
+ LowConcurrencyQueueName: ${self:service}-${self:custom.stage}-low-concurrency
110
+ LowConcurrencyDeadJobQueueName: ${self:service}-${self:custom.stage}-low-concurrency-dead
111
+ LowConcurrencyQueueHandlerName: ${self:service}-${self:custom.stage}-LowConcurrencyQueueHandler
112
+ JobsTableName: ${self:service}-${self:custom.stage}-jobs
113
+ ActivityTableName: ${self:service}-${self:custom.stage}-activity
114
+ JobActivatorName: ${self:service}-${self:custom.stage}-JobActivator
@@ -0,0 +1,5 @@
1
+ Effect: Allow
2
+ Action:
3
+ - dynamodb:*
4
+ Resource:
5
+ - "Fn::GetAtt": [ ActivityTable, 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": [ DefaultQueue, 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
+ - dynamodb:*
4
+ Resource:
5
+ - "Fn::GetAtt": [ JobsTable, Arn ]
@@ -0,0 +1,8 @@
1
+ Effect: Allow
2
+ Action:
3
+ - dynamodb:Query
4
+ Resource:
5
+ Fn::Join:
6
+ - ""
7
+ - - "Fn::GetAtt": [ JobsTable, Arn ]
8
+ - "/index/performAtIndex"
@@ -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": [ LowConcurrencyQueue, 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,11 @@
1
+ # TODO - Figure out how to allow individual packaging to work out of the box.
2
+ individually: false
3
+ include:
4
+ - Gemfile
5
+ - Gemfile.lock
6
+ - funktor_config/boot.rb
7
+ - app/**
8
+ # Evertyting is excluded by default with serverless-ruby-layer, but you could use
9
+ # the lines below to exlude files that are inside an include path.
10
+ #exclude:
11
+ # - workers/excluded_worker.rb
@@ -0,0 +1,22 @@
1
+ Resources:
2
+ ActivityTable:
3
+ Type: AWS::DynamoDB::Table
4
+ Properties:
5
+ # Generate a name based on the stage
6
+ TableName: ${self:custom.funktor.ActivityTableName}
7
+ BillingMode: PAY_PER_REQUEST
8
+ AttributeDefinitions:
9
+ - AttributeName: category
10
+ AttributeType: S
11
+ - AttributeName: statName
12
+ AttributeType: S
13
+ KeySchema:
14
+ - AttributeName: category
15
+ KeyType: HASH
16
+ - AttributeName: statName
17
+ KeyType: RANGE
18
+
19
+ Outputs:
20
+ ActivityTable:
21
+ Value:
22
+ Ref: ActivityTable
@@ -0,0 +1,809 @@
1
+ Resources:
2
+ FunktorDashboard:
3
+ Type: AWS::CloudWatch::Dashboard
4
+ Properties:
5
+ DashboardName: ${self:custom.funktor.DashboardName}
6
+ DashboardBody: >
7
+ {
8
+ "widgets": [
9
+
10
+
11
+
12
+ {
13
+ "height": 3,
14
+ "width": 24,
15
+ "y": 0,
16
+ "x": 0,
17
+ "type": "text",
18
+ "properties": {
19
+ "markdown": "\n# Funktor Auto-generated Dashbaord\n\n This dashboard is auto-generated by Funktor and will be updated as Funktor progresses. If you want to customize this dashboard you should use 'Actions => Save dashbaord as' in the toolbar above to create a new dashboard of your own.\n\n The upper section shows you high level queue and worker stats, the lower sections show more details about all the AWS resources at play."
20
+ }
21
+ },
22
+
23
+
24
+ {
25
+ "height": 6,
26
+ "width": 12,
27
+ "y": 3,
28
+ "x": 12,
29
+ "type": "metric",
30
+ "properties": {
31
+ "metrics": [
32
+ [ "funktor-testapp", "Duration", "WorkerClassName", "AuditWorker" ],
33
+ [ "...", { "stat": "p99" } ],
34
+ [ "funktor-testapp", "Duration", "WorkerClassName", "GreetingsWorker" ],
35
+ [ "...", { "stat": "p99" } ],
36
+ [ "funktor-testapp", "Duration", "WorkerClassName", "HelloWorker" ],
37
+ [ "...", { "stat": "p99" } ],
38
+ [ "funktor-testapp", "Duration", "WorkerClassName", "SingleThreadAuditWorker" ],
39
+ [ "...", { "stat": "p99" } ]
40
+ ],
41
+ "view": "timeSeries",
42
+ "stacked": false,
43
+ "region": "us-east-1",
44
+ "stat": "Average",
45
+ "period": 60,
46
+ "title": "Job Duration by Worker"
47
+ }
48
+ },
49
+
50
+ {
51
+ "height": 6,
52
+ "width": 12,
53
+ "y": 3,
54
+ "x": 0,
55
+ "type": "metric",
56
+ "properties": {
57
+ "metrics": [
58
+ [ "funktor-testapp", "processed", "WorkerClassName", "AuditWorker" ],
59
+ [ ".", "failed", ".", "." ],
60
+ [ "funktor-testapp", "processed", "WorkerClassName", "GreetingsWorker" ],
61
+ [ ".", "failed", ".", "." ],
62
+ [ "funktor-testapp", "processed", "WorkerClassName", "HelloWorker" ],
63
+ [ ".", "failed", ".", "." ],
64
+ [ "funktor-testapp", "processed", "WorkerClassName", "SingleThreadAuditWorker" ],
65
+ [ ".", "failed", ".", "." ]
66
+ ],
67
+ "view": "timeSeries",
68
+ "stacked": false,
69
+ "region": "us-east-1",
70
+ "title": "Process/Failed Jobs By Worker",
71
+ "period": 60,
72
+ "stat": "Sum"
73
+ }
74
+ },
75
+
76
+ {
77
+ "height": 6,
78
+ "width": 12,
79
+ "y": 9,
80
+ "x": 12,
81
+ "type": "metric",
82
+ "properties": {
83
+ "metrics": [
84
+ [ "funktor-testapp", "Duration", "Queue", "default" ],
85
+ [ "...", { "stat": "p99" } ],
86
+ [ "funktor-testapp", "Duration", "Queue", "low_concurrency" ],
87
+ [ "...", { "stat": "p99" } ]
88
+ ],
89
+ "view": "timeSeries",
90
+ "stacked": false,
91
+ "region": "us-east-1",
92
+ "stat": "Average",
93
+ "period": 60,
94
+ "title": "Job Duration by Queue"
95
+ }
96
+ },
97
+ {
98
+ "height": 6,
99
+ "width": 12,
100
+ "y": 9,
101
+ "x": 0,
102
+ "type": "metric",
103
+ "properties": {
104
+ "metrics": [
105
+ [ "funktor-testapp", "processed", "Queue", "default" ],
106
+ [ ".", "failed", ".", "." ],
107
+ [ "funktor-testapp", "processed", "Queue", "low_concurrency" ],
108
+ [ ".", "failed", ".", "." ]
109
+ ],
110
+ "view": "timeSeries",
111
+ "stacked": false,
112
+ "region": "us-east-1",
113
+ "title": "Process/Failed Jobs By Queue",
114
+ "period": 60,
115
+ "stat": "Sum"
116
+ }
117
+ },
118
+
119
+
120
+ {
121
+ "height": 3,
122
+ "width": 24,
123
+ "y": 9,
124
+ "x": 0,
125
+ "type": "text",
126
+ "properties": {
127
+ "markdown": "\n# Behind the scenes\n\n The stats below give some insight into the inner workings of the Funktor apparatus."
128
+ }
129
+ },
130
+
131
+
132
+
133
+
134
+ {
135
+ "height": 3,
136
+ "width": 6,
137
+ "y": 18,
138
+ "x": 0,
139
+ "type": "text",
140
+ "properties": {
141
+ "markdown": "\n# Incoming Jobs\n"
142
+ }
143
+ },
144
+ {
145
+ "height": 3,
146
+ "width": 3,
147
+ "y": 18,
148
+ "x": 6,
149
+ "type": "metric",
150
+ "properties": {
151
+ "metrics": [
152
+ [ "AWS/SQS", "NumberOfMessagesReceived", "QueueName", "${self:custom.funktor.IncomingJobQueueName}", { "label": "Messages Per Minute" } ]
153
+ ],
154
+ "view": "singleValue",
155
+ "region": "us-east-1",
156
+ "stat": "Sum",
157
+ "period": 60,
158
+ "title": "Messages Per Minute"
159
+ }
160
+ },
161
+ {
162
+ "height": 3,
163
+ "width": 15,
164
+ "y": 18,
165
+ "x": 9,
166
+ "type": "metric",
167
+ "properties": {
168
+ "metrics": [
169
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:custom.funktor.IncomingJobHandlerName}", "Resource", "${self:custom.funktor.IncomingJobHandlerName}", { "label": "p10" } ],
170
+ [ "...", { "label": "p50", "stat": "p50" } ],
171
+ [ "...", { "label": "p99", "stat": "p99" } ],
172
+ [ "...", { "label": "Average", "stat": "Average" } ]
173
+ ],
174
+ "view": "singleValue",
175
+ "region": "us-east-1",
176
+ "stat": "p10",
177
+ "period": 60,
178
+ "title": "Handler Duration"
179
+ }
180
+ },
181
+
182
+
183
+
184
+ {
185
+ "height": 6,
186
+ "width": 9,
187
+ "y": 21,
188
+ "x": 0,
189
+ "type": "metric",
190
+ "properties": {
191
+ "metrics": [
192
+ [ "AWS/SQS", "NumberOfMessagesReceived", "QueueName", "${self:custom.funktor.IncomingJobQueueName}", { "label": "Received" } ],
193
+ [ ".", "NumberOfMessagesDeleted", ".", ".", { "label": "Handled" } ],
194
+ [ "AWS/Lambda", "Invocations", "FunctionName", "${self:custom.funktor.IncomingJobHandlerName}", "Resource", "${self:custom.funktor.IncomingJobHandlerName}", { "label": "Handler Invocations" } ],
195
+ [ "AWS/SQS", "ApproximateNumberOfMessagesVisible", "QueueName", "${self:custom.funktor.IncomingJobQueueName}", { "label": "Pending?" } ],
196
+ [ ".", "ApproximateNumberOfMessagesNotVisible", ".", ".", { "label": "Backlog?" } ],
197
+ [ ".", "NumberOfMessagesSent", ".", ".", { "label": "Sent" } ],
198
+ [ ".", "ApproximateNumberOfMessagesDelayed", ".", ".", { "label": "Delayed" } ]
199
+ ],
200
+ "view": "timeSeries",
201
+ "stacked": false,
202
+ "region": "us-east-1",
203
+ "title": "Incoming Job Queue (Async & scheduled jobs land here first)",
204
+ "period": 60,
205
+ "stat": "Sum",
206
+ "setPeriodToTimeRange": true,
207
+ "liveData": true
208
+ }
209
+ },
210
+ {
211
+ "height": 6,
212
+ "width": 9,
213
+ "y": 21,
214
+ "x": 9,
215
+ "type": "metric",
216
+ "properties": {
217
+ "period": 60,
218
+ "metrics": [
219
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:custom.funktor.IncomingJobHandlerName}", { "stat": "Minimum" } ],
220
+ [ "...", { "stat": "Average" } ],
221
+ [ "...", { "stat": "Maximum" } ]
222
+ ],
223
+ "region": "us-east-1",
224
+ "title": "Incoming Job Handler Duration in Milliseconds",
225
+ "view": "timeSeries",
226
+ "stacked": false,
227
+ "liveData": true
228
+ }
229
+ },
230
+ {
231
+ "height": 3,
232
+ "width": 6,
233
+ "y": 21,
234
+ "x": 18,
235
+ "type": "metric",
236
+ "properties": {
237
+ "period": 60,
238
+ "metrics": [
239
+ [ "AWS/Lambda", "Errors", "FunctionName", "${self:custom.funktor.IncomingJobHandlerName}", { "id": "errors", "stat": "Sum", "color": "#d13212" } ],
240
+ [ ".", "Invocations", ".", ".", { "id": "invocations", "stat": "Sum", "visible": false } ],
241
+ [ { "expression": "100 - 100 * errors / MAX([errors, invocations])", "label": "Success rate (%)", "id": "availability", "yAxis": "right", "region": "us-east-1" } ]
242
+ ],
243
+ "region": "us-east-1",
244
+ "title": "Incoming Job Handler Error count and success rate (%)",
245
+ "yAxis": {
246
+ "right": {
247
+ "max": 100
248
+ }
249
+ },
250
+ "view": "timeSeries",
251
+ "stacked": false,
252
+ "liveData": true
253
+ }
254
+ },
255
+
256
+
257
+ {
258
+ "height": 3,
259
+ "width": 6,
260
+ "y": 24,
261
+ "x": 18,
262
+ "type": "metric",
263
+ "properties": {
264
+ "period": 60,
265
+ "metrics": [
266
+ [ "AWS/Lambda", "ConcurrentExecutions", "FunctionName", "${self:custom.funktor.IncomingJobHandlerName}", { "stat": "Maximum" } ]
267
+ ],
268
+ "region": "us-east-1",
269
+ "title": "Incoming Job Handler Concurrent Executions",
270
+ "view": "timeSeries",
271
+ "stacked": false,
272
+ "liveData": true
273
+ }
274
+ },
275
+
276
+
277
+
278
+
279
+ {
280
+ "height": 3,
281
+ "width": 6,
282
+ "y": 27,
283
+ "x": 0,
284
+ "type": "text",
285
+ "properties": {
286
+ "markdown": "\n# Default Queue\n"
287
+ }
288
+ },
289
+ {
290
+ "height": 3,
291
+ "width": 3,
292
+ "y": 27,
293
+ "x": 6,
294
+ "type": "metric",
295
+ "properties": {
296
+ "metrics": [
297
+ [ "AWS/SQS", "NumberOfMessagesReceived", "QueueName",
298
+ "${self:custom.funktor.DefaultQueueName}", { "label": "Messages Per Minute" } ]
299
+ ],
300
+ "view": "singleValue",
301
+ "region": "us-east-1",
302
+ "stat": "Sum",
303
+ "period": 60,
304
+ "title": "Messages Per Minute"
305
+ }
306
+ },
307
+ {
308
+ "height": 3,
309
+ "width": 15,
310
+ "y": 27,
311
+ "x": 9,
312
+ "type": "metric",
313
+ "properties": {
314
+ "metrics": [
315
+ [ "AWS/Lambda", "Duration", "FunctionName",
316
+ "${self:custom.funktor.DefaultQueueHandlerName}", "Resource",
317
+ "${self:custom.funktor.DefaultQueueHandlerName}", { "label": "p10" } ],
318
+ [ "...", { "label": "p50", "stat": "p50" } ],
319
+ [ "...", { "label": "p99", "stat": "p99" } ],
320
+ [ "...", { "label": "Average", "stat": "Average" } ]
321
+ ],
322
+ "view": "singleValue",
323
+ "region": "us-east-1",
324
+ "stat": "p10",
325
+ "period": 60,
326
+ "title": "Handler Duration"
327
+ }
328
+ },
329
+ {
330
+ "height": 6,
331
+ "width": 9,
332
+ "y": 30,
333
+ "x": 0,
334
+ "type": "metric",
335
+ "properties": {
336
+ "metrics": [
337
+ [ "AWS/SQS", "NumberOfMessagesReceived", "QueueName",
338
+ "${self:custom.funktor.DefaultQueueName}",
339
+ { "label": "Received" } ],
340
+ [ ".", "NumberOfMessagesDeleted", ".", ".", { "label": "Handled" } ],
341
+ [ "AWS/Lambda", "Invocations", "FunctionName",
342
+ "${self:custom.funktor.DefaultQueueHandlerName}", "Resource",
343
+ "${self:custom.funktor.DefaultQueueHandlerName}", { "label": "Handler Invocations" } ],
344
+ [ "AWS/SQS", "ApproximateNumberOfMessagesVisible", "QueueName",
345
+ "${self:custom.funktor.DefaultQueueName}", { "label": "Pending?" } ],
346
+ [ ".", "ApproximateNumberOfMessagesNotVisible", ".", ".", { "label": "Backlog?" } ],
347
+ [ ".", "NumberOfMessagesSent", ".", ".", { "label": "Sent" } ],
348
+ [ ".", "ApproximateNumberOfMessagesDelayed", ".", ".", { "label": "Delayed" } ]
349
+ ],
350
+ "view": "timeSeries",
351
+ "stacked": false,
352
+ "region": "us-east-1",
353
+ "title": "Default Queue (Async jobs go here immediately, scheduled jobs land here in the minute before they're scheduled)",
354
+ "period": 60,
355
+ "stat": "Sum",
356
+ "liveData": true
357
+ }
358
+ },
359
+ {
360
+ "height": 6,
361
+ "width": 9,
362
+ "y": 30,
363
+ "x": 9,
364
+ "type": "metric",
365
+ "properties": {
366
+ "period": 60,
367
+ "metrics": [
368
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:custom.funktor.DefaultQueueHandlerName}", { "stat": "Minimum" } ],
369
+ [ "...", { "stat": "Average" } ],
370
+ [ "...", { "stat": "Maximum" } ]
371
+ ],
372
+ "region": "us-east-1",
373
+ "title": "Default Queue Handler Duration in Milliseconds",
374
+ "view": "timeSeries",
375
+ "stacked": false,
376
+ "liveData": true
377
+ }
378
+ },
379
+ {
380
+ "height": 3,
381
+ "width": 6,
382
+ "y": 30,
383
+ "x": 18,
384
+ "type": "metric",
385
+ "properties": {
386
+ "period": 60,
387
+ "metrics": [
388
+ [ "AWS/Lambda", "Errors", "FunctionName",
389
+ "${self:custom.funktor.DefaultQueueHandlerName}", { "id": "errors", "stat": "Sum", "color": "#d13212" } ],
390
+ [ ".", "Invocations", ".", ".", { "id": "invocations", "stat": "Sum", "visible": false } ],
391
+ [ { "expression": "100 - 100 * errors / MAX([errors, invocations])", "label": "Success rate (%)", "id": "availability", "yAxis": "right", "region": "us-east-1" } ]
392
+ ],
393
+ "region": "us-east-1",
394
+ "title": "Default Queue Handler Error count and success rate (%)",
395
+ "yAxis": {
396
+ "right": {
397
+ "max": 100
398
+ }
399
+ },
400
+ "view": "timeSeries",
401
+ "stacked": false,
402
+ "liveData": true
403
+ }
404
+ },
405
+ {
406
+ "height": 3,
407
+ "width": 6,
408
+ "y": 33,
409
+ "x": 18,
410
+ "type": "metric",
411
+ "properties": {
412
+ "period": 60,
413
+ "metrics": [
414
+ [ "AWS/Lambda", "ConcurrentExecutions", "FunctionName",
415
+ "${self:custom.funktor.DefaultQueueHandlerName}", { "stat": "Maximum" } ]
416
+ ],
417
+ "region": "us-east-1",
418
+ "title": "Default Queue Handler Concurrent executions",
419
+ "view": "timeSeries",
420
+ "stacked": false,
421
+ "liveData": true
422
+ }
423
+ },
424
+
425
+
426
+ {
427
+ "height": 3,
428
+ "width": 6,
429
+ "y": 36,
430
+ "x": 0,
431
+ "type": "text",
432
+ "properties": {
433
+ "markdown": "\n# LowConcurrency Queue\n"
434
+ }
435
+ },
436
+ {
437
+ "height": 3,
438
+ "width": 3,
439
+ "y": 36,
440
+ "x": 6,
441
+ "type": "metric",
442
+ "properties": {
443
+ "metrics": [
444
+ [ "AWS/SQS", "NumberOfMessagesReceived", "QueueName",
445
+ "${self:custom.funktor.LowConcurrencyQueueName}", { "label": "Messages Per Minute" } ]
446
+ ],
447
+ "view": "singleValue",
448
+ "region": "us-east-1",
449
+ "stat": "Sum",
450
+ "period": 60,
451
+ "title": "Messages Per Minute"
452
+ }
453
+ },
454
+ {
455
+ "height": 3,
456
+ "width": 15,
457
+ "y": 36,
458
+ "x": 9,
459
+ "type": "metric",
460
+ "properties": {
461
+ "metrics": [
462
+ [ "AWS/Lambda", "Duration", "FunctionName",
463
+ "${self:custom.funktor.LowConcurrencyQueueHandlerName}", "Resource",
464
+ "${self:custom.funktor.LowConcurrencyQueueHandlerName}", { "label": "p10" } ],
465
+ [ "...", { "label": "p50", "stat": "p50" } ],
466
+ [ "...", { "label": "p99", "stat": "p99" } ],
467
+ [ "...", { "label": "Average", "stat": "Average" } ]
468
+ ],
469
+ "view": "singleValue",
470
+ "region": "us-east-1",
471
+ "stat": "p10",
472
+ "period": 60,
473
+ "title": "Handler Duration"
474
+ }
475
+ },
476
+ {
477
+ "height": 6,
478
+ "width": 9,
479
+ "y": 39,
480
+ "x": 0,
481
+ "type": "metric",
482
+ "properties": {
483
+ "metrics": [
484
+ [ "AWS/SQS", "NumberOfMessagesReceived", "QueueName",
485
+ "${self:custom.funktor.LowConcurrencyQueueName}",
486
+ { "label": "Received" } ],
487
+ [ ".", "NumberOfMessagesDeleted", ".", ".", { "label": "Handled" } ],
488
+ [ "AWS/Lambda", "Invocations", "FunctionName",
489
+ "${self:custom.funktor.LowConcurrencyQueueHandlerName}", "Resource",
490
+ "${self:custom.funktor.LowConcurrencyQueueHandlerName}", { "label": "Handler Invocations" } ],
491
+ [ "AWS/SQS", "ApproximateNumberOfMessagesVisible", "QueueName",
492
+ "${self:custom.funktor.LowConcurrencyQueueName}", { "label": "Pending?" } ],
493
+ [ ".", "ApproximateNumberOfMessagesNotVisible", ".", ".", { "label": "Backlog?" } ],
494
+ [ ".", "NumberOfMessagesSent", ".", ".", { "label": "Sent" } ],
495
+ [ ".", "ApproximateNumberOfMessagesDelayed", ".", ".", { "label": "Delayed" } ]
496
+ ],
497
+ "view": "timeSeries",
498
+ "stacked": false,
499
+ "region": "us-east-1",
500
+ "title": "LowConcurrency Queue (Async jobs go here immediately, scheduled jobs land here in the minute before they're scheduled)",
501
+ "period": 60,
502
+ "stat": "Sum",
503
+ "liveData": true
504
+ }
505
+ },
506
+ {
507
+ "height": 6,
508
+ "width": 9,
509
+ "y": 39,
510
+ "x": 9,
511
+ "type": "metric",
512
+ "properties": {
513
+ "period": 60,
514
+ "metrics": [
515
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:custom.funktor.LowConcurrencyQueueHandlerName}", { "stat": "Minimum" } ],
516
+ [ "...", { "stat": "Average" } ],
517
+ [ "...", { "stat": "Maximum" } ]
518
+ ],
519
+ "region": "us-east-1",
520
+ "title": "LowConcurrency Queue Handler Duration in Milliseconds",
521
+ "view": "timeSeries",
522
+ "stacked": false,
523
+ "liveData": true
524
+ }
525
+ },
526
+ {
527
+ "height": 3,
528
+ "width": 6,
529
+ "y": 39,
530
+ "x": 18,
531
+ "type": "metric",
532
+ "properties": {
533
+ "period": 60,
534
+ "metrics": [
535
+ [ "AWS/Lambda", "Errors", "FunctionName",
536
+ "${self:custom.funktor.LowConcurrencyQueueHandlerName}", { "id": "errors", "stat": "Sum", "color": "#d13212" } ],
537
+ [ ".", "Invocations", ".", ".", { "id": "invocations", "stat": "Sum", "visible": false } ],
538
+ [ { "expression": "100 - 100 * errors / MAX([errors, invocations])", "label": "Success rate (%)", "id": "availability", "yAxis": "right", "region": "us-east-1" } ]
539
+ ],
540
+ "region": "us-east-1",
541
+ "title": "LowConcurrency Queue Handler Error count and success rate (%)",
542
+ "yAxis": {
543
+ "right": {
544
+ "max": 100
545
+ }
546
+ },
547
+ "view": "timeSeries",
548
+ "stacked": false,
549
+ "liveData": true
550
+ }
551
+ },
552
+ {
553
+ "height": 3,
554
+ "width": 6,
555
+ "y": 42,
556
+ "x": 18,
557
+ "type": "metric",
558
+ "properties": {
559
+ "period": 60,
560
+ "metrics": [
561
+ [ "AWS/Lambda", "ConcurrentExecutions", "FunctionName",
562
+ "${self:custom.funktor.LowConcurrencyQueueHandlerName}", { "stat": "Maximum" } ]
563
+ ],
564
+ "region": "us-east-1",
565
+ "title": "LowConcurrency Queue Handler Concurrent executions",
566
+ "view": "timeSeries",
567
+ "stacked": false,
568
+ "liveData": true
569
+ }
570
+ },
571
+
572
+
573
+
574
+
575
+
576
+ {
577
+ "height": 3,
578
+ "width": 6,
579
+ "y": 45,
580
+ "x": 0,
581
+ "type": "text",
582
+ "properties": {
583
+ "markdown": "\n# Delayed Jobs\n"
584
+ }
585
+ },
586
+ {
587
+ "height": 3,
588
+ "width": 3,
589
+ "y": 45,
590
+ "x": 6,
591
+ "type": "metric",
592
+ "properties": {
593
+ "metrics": [
594
+ [ "AWS/DynamoDB", "ReturnedItemCount", "TableName", "${self:custom.funktor.JobsTableName}", "Operation", "Query" ]
595
+ ],
596
+ "view": "singleValue",
597
+ "region": "us-east-1",
598
+ "stat": "Average",
599
+ "period": 60,
600
+ "title": "Messages To Be Scheduled"
601
+ }
602
+ },
603
+ {
604
+ "height": 3,
605
+ "width": 15,
606
+ "y": 45,
607
+ "x": 9,
608
+ "type": "metric",
609
+ "properties": {
610
+ "metrics": [
611
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:custom.funktor.JobActivatorName}", "Resource", "${self:custom.funktor.JobActivatorName}", { "label": "p10" } ],
612
+ [ "...", { "label": "p50", "stat": "p50" } ],
613
+ [ "...", { "label": "p99", "stat": "p99" } ],
614
+ [ "...", { "label": "Average", "stat": "Average" } ]
615
+ ],
616
+ "view": "singleValue",
617
+ "region": "us-east-1",
618
+ "stat": "p10",
619
+ "period": 60,
620
+ "title": "Handler Duration"
621
+ }
622
+ },
623
+
624
+
625
+
626
+
627
+ {
628
+ "height": 3,
629
+ "width": 6,
630
+ "y": 48,
631
+ "x": 18,
632
+ "type": "metric",
633
+ "properties": {
634
+ "period": 60,
635
+ "metrics": [
636
+ [ "AWS/Lambda", "Errors", "FunctionName", "${self:custom.funktor.JobActivatorName}", { "id": "errors", "stat": "Sum", "color": "#d13212" } ],
637
+ [ ".", "Invocations", ".", ".", { "id": "invocations", "stat": "Sum", "visible": false } ],
638
+ [ { "expression": "100 - 100 * errors / MAX([errors, invocations])", "label": "Success rate (%)", "id": "availability", "yAxis": "right", "region": "us-east-1" } ]
639
+ ],
640
+ "region": "us-east-1",
641
+ "title": "Delayed Job SchedulerError count and success rate (%)",
642
+ "yAxis": {
643
+ "right": {
644
+ "max": 100
645
+ }
646
+ },
647
+ "view": "timeSeries",
648
+ "stacked": false,
649
+ "liveData": true
650
+ }
651
+ },
652
+ {
653
+ "height": 3,
654
+ "width": 9,
655
+ "y": 48,
656
+ "x": 9,
657
+ "type": "metric",
658
+ "properties": {
659
+ "period": 60,
660
+ "metrics": [
661
+ [ "AWS/Lambda", "Duration", "FunctionName", "${self:custom.funktor.JobActivatorName}", { "stat": "Minimum" } ],
662
+ [ "...", { "stat": "Average" } ],
663
+ [ "...", { "stat": "Maximum" } ]
664
+ ],
665
+ "region": "us-east-1",
666
+ "title": "Delayed Job Scheduler Duration",
667
+ "view": "timeSeries",
668
+ "stacked": false,
669
+ "liveData": true
670
+ }
671
+ },
672
+ {
673
+ "height": 3,
674
+ "width": 9,
675
+ "y": 48,
676
+ "x": 0,
677
+ "type": "metric",
678
+ "properties": {
679
+ "metrics": [
680
+ [ "AWS/DynamoDB", "ReturnedItemCount", "TableName", "${self:custom.funktor.JobsTableName}", "Operation", "Query" ]
681
+ ],
682
+ "view": "timeSeries",
683
+ "stacked": false,
684
+ "region": "us-east-1",
685
+ "title": "Delayed Jobs To Be Executed In The Next 90 Seconds",
686
+ "period": 60,
687
+ "stat": "Average",
688
+ "liveData": true
689
+ }
690
+ },
691
+
692
+
693
+
694
+ {
695
+ "height": 3,
696
+ "width": 9,
697
+ "y": 51,
698
+ "x": 0,
699
+ "type": "metric",
700
+ "properties": {
701
+ "metrics": [
702
+ [ { "expression": "m2/PERIOD(m2)", "label": "Consumed Read Capacity Units", "id": "e1", "stat": "Sum", "region": "us-east-1" } ],
703
+ [ "AWS/DynamoDB", "ConsumedReadCapacityUnits", "TableName", "${self:custom.funktor.JobsTableName}", { "id": "m2", "visible": false } ],
704
+ [ ".", "ConsumedWriteCapacityUnits", ".", ".", { "yAxis": "left", "id": "m4", "visible": false } ],
705
+ [ ".", "WriteThrottleEvents", ".", ".", { "yAxis": "right", "id": "m5", "visible": false } ]
706
+ ],
707
+ "view": "timeSeries",
708
+ "stacked": false,
709
+ "region": "us-east-1",
710
+ "title": "Scheduled Job Table Read Capacity Units",
711
+ "period": 60,
712
+ "stat": "Sum",
713
+ "liveData": true
714
+ }
715
+ },
716
+ {
717
+ "height": 3,
718
+ "width": 6,
719
+ "y": 51,
720
+ "x": 18,
721
+ "type": "metric",
722
+ "properties": {
723
+ "period": 60,
724
+ "metrics": [
725
+ [ "AWS/Lambda", "ConcurrentExecutions", "FunctionName", "${self:custom.funktor.JobActivatorName}", { "stat": "Maximum" } ]
726
+ ],
727
+ "region": "us-east-1",
728
+ "title": "Delayd Job Schedule Concurrent executions",
729
+ "view": "timeSeries",
730
+ "stacked": false,
731
+ "liveData": true
732
+ }
733
+ },
734
+ {
735
+ "height": 3,
736
+ "width": 9,
737
+ "y": 51,
738
+ "x": 9,
739
+ "type": "metric",
740
+ "properties": {
741
+ "metrics": [
742
+ [ { "expression": "m4/PERIOD(m4)", "label": "Consumed Read Capacity Units", "id": "e1", "stat": "Sum", "region": "us-east-1" } ],
743
+ [ "AWS/DynamoDB", "ConsumedReadCapacityUnits", "TableName", "${self:custom.funktor.JobsTableName}", { "id": "m2", "visible": false } ],
744
+ [ ".", "ConsumedWriteCapacityUnits", ".", ".", { "yAxis": "left", "id": "m4", "visible": false } ],
745
+ [ ".", "WriteThrottleEvents", ".", ".", { "yAxis": "right", "id": "m5", "visible": false } ]
746
+ ],
747
+ "view": "timeSeries",
748
+ "stacked": false,
749
+ "region": "us-east-1",
750
+ "title": "Scheduled Job Table Write Capacity Units",
751
+ "period": 60,
752
+ "stat": "Sum",
753
+ "liveData": true
754
+ }
755
+ },
756
+
757
+
758
+
759
+
760
+ {
761
+ "height": 3,
762
+ "width": 18,
763
+ "y": 54,
764
+ "x": 0,
765
+ "type": "metric",
766
+ "properties": {
767
+ "metrics": [
768
+ [ "AWS/DynamoDB", "SuccessfulRequestLatency", "TableName", "${self:custom.funktor.JobsTableName}", "Operation", "PutItem", { "yAxis": "left" } ],
769
+ [ "...", "Query" ],
770
+ [ ".", "ThrottledRequests", ".", ".", ".", "PutItem", { "yAxis": "right", "visible": false } ],
771
+ [ ".", "SuccessfulRequestLatency", ".", ".", ".", "DeleteItem" ],
772
+ [ ".", "SuccessfulRequestLatency", ".", ".", ".", "UpdateItem" ],
773
+ [ ".", "ThrottledRequests", ".", ".", ".", ".", { "yAxis": "right", "visible": false } ]
774
+ ],
775
+ "view": "timeSeries",
776
+ "stacked": false,
777
+ "region": "us-east-1",
778
+ "stat": "Average",
779
+ "period": 60,
780
+ "title": "Scheduled Job Table Latency",
781
+ "liveData": true
782
+ }
783
+ },
784
+ {
785
+ "height": 3,
786
+ "width": 6,
787
+ "y": 54,
788
+ "x": 18,
789
+ "type": "metric",
790
+ "properties": {
791
+ "metrics": [
792
+ [ "AWS/DynamoDB", "ThrottledRequests", "TableName", "${self:custom.funktor.JobsTableName}", "Operation", "DeleteItem" ],
793
+ [ "...", "PutItem" ]
794
+ ],
795
+ "view": "timeSeries",
796
+ "stacked": false,
797
+ "region": "us-east-1",
798
+ "stat": "Sum",
799
+ "period": 60,
800
+ "title": "Scheduled Job Table Throttled Operations",
801
+ "liveData": true
802
+ }
803
+ }
804
+
805
+
806
+
807
+
808
+ ]
809
+ }