idea-aws 3.14.1 → 3.15.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.
@@ -0,0 +1,31 @@
1
+ import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics';
2
+ /**
3
+ * A wrapper for simple uses of CloudWatch Metrics.
4
+ */
5
+ export declare class CloudWatchMetrics {
6
+ private metrics;
7
+ constructor(options?: {
8
+ project?: string;
9
+ });
10
+ /**
11
+ * Get the raw Metrics object. To use for custom purposes.
12
+ */
13
+ __raw(): Metrics;
14
+ /**
15
+ * Add an entry for the metrics.
16
+ */
17
+ addMetric(metricName: string, value?: number, unit?: MetricUnits): void;
18
+ /**
19
+ * Add a metadata useful when you want to search highly contextual information along with your metrics in your logs.
20
+ */
21
+ addMetadata(key: string, value: string): void;
22
+ /**
23
+ * Add an additional metrics dimension.
24
+ */
25
+ addDimension(name: string, value: string, defaultValue?: string): void;
26
+ /**
27
+ * Synchronous function to actually publish your metrics.
28
+ * It will create a new EMF blob and log it to be then ingested by Cloudwatch logs and processed for metrics creation.
29
+ */
30
+ publishStoredMetrics(): void;
31
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CloudWatchMetrics = void 0;
4
+ const metrics_1 = require("@aws-lambda-powertools/metrics");
5
+ /**
6
+ * A wrapper for simple uses of CloudWatch Metrics.
7
+ */
8
+ class CloudWatchMetrics {
9
+ constructor(options) {
10
+ const project = options?.project ?? process.env.PROJECT ?? 'unknownProject';
11
+ this.metrics = new metrics_1.Metrics({ namespace: project });
12
+ }
13
+ /**
14
+ * Get the raw Metrics object. To use for custom purposes.
15
+ */
16
+ __raw() {
17
+ return this.metrics;
18
+ }
19
+ /**
20
+ * Add an entry for the metrics.
21
+ */
22
+ addMetric(metricName, value = 1, unit = metrics_1.MetricUnits.Count) {
23
+ this.metrics.addMetric(metricName, unit, value);
24
+ }
25
+ /**
26
+ * Add a metadata useful when you want to search highly contextual information along with your metrics in your logs.
27
+ */
28
+ addMetadata(key, value) {
29
+ this.metrics.addMetadata(key, value);
30
+ }
31
+ /**
32
+ * Add an additional metrics dimension.
33
+ */
34
+ addDimension(name, value, defaultValue = '-') {
35
+ this.metrics.addDimension(name, value ?? defaultValue);
36
+ }
37
+ /**
38
+ * Synchronous function to actually publish your metrics.
39
+ * It will create a new EMF blob and log it to be then ingested by Cloudwatch logs and processed for metrics creation.
40
+ */
41
+ publishStoredMetrics() {
42
+ this.metrics.publishStoredMetrics();
43
+ }
44
+ }
45
+ exports.CloudWatchMetrics = CloudWatchMetrics;
@@ -2,6 +2,7 @@ import 'source-map-support/register';
2
2
  import { APIGatewayProxyEventV2, APIGatewayProxyEvent, Callback } from 'aws-lambda';
3
3
  import { CognitoUser, Auth0User } from 'idea-toolbox';
4
4
  import { Logger } from './logger';
5
+ import { CloudWatchMetrics } from './metrics';
5
6
  import { GenericController, GenericControllerOptions } from './genericController';
6
7
  /**
7
8
  * An abstract class to inherit to manage API requests (AWS API Gateway) in an AWS Lambda function.
@@ -26,6 +27,7 @@ export declare abstract class ResourceController extends GenericController {
26
27
  protected returnStatusCode?: number;
27
28
  protected logger: Logger;
28
29
  protected logRequestsWithKey: string;
30
+ protected metrics: CloudWatchMetrics;
29
31
  protected currentLang: string;
30
32
  protected defaultLang: string;
31
33
  protected translations: any;
@@ -100,12 +102,20 @@ export declare abstract class ResourceController extends GenericController {
100
102
  * Check whether shared resource exists in the back-end (translation, template, etc.).
101
103
  * Search for the specified file path in both the Lambda function's main folder and the layers folder.
102
104
  */
103
- sharedResourceExists(filePath: string): boolean;
105
+ protected sharedResourceExists(filePath: string): boolean;
104
106
  /**
105
107
  * Load a shared resource in the back-end (translation, template, etc.).
106
108
  * Search for the specified file path in both the Lambda function's main folder and the layers folder.
107
109
  */
108
- loadSharedResource(filePath: string): string;
110
+ protected loadSharedResource(filePath: string): string;
111
+ /**
112
+ * Prepare the CloudWatch metrics at the beginning of a request.
113
+ */
114
+ protected prepareMetrics(): void;
115
+ /**
116
+ * Publish the CloudWatch metrics (default and custom-defined) at the end of a reqeust.
117
+ */
118
+ protected publishMetrics(statusCode: number, error?: any): void;
109
119
  /**
110
120
  * Simulate an internal API request, invoking directly the lambda and therefore saving resources.
111
121
  * @return the body of the response
@@ -6,6 +6,7 @@ const fs_1 = require("fs");
6
6
  const aws_sdk_1 = require("aws-sdk");
7
7
  const idea_toolbox_1 = require("idea-toolbox");
8
8
  const logger_1 = require("./logger");
9
+ const metrics_1 = require("./metrics");
9
10
  const genericController_1 = require("./genericController");
10
11
  /**
11
12
  * An abstract class to inherit to manage API requests (AWS API Gateway) in an AWS Lambda function.
@@ -15,6 +16,7 @@ class ResourceController extends genericController_1.GenericController {
15
16
  super(event, callback, options);
16
17
  this.initError = false;
17
18
  this.logger = new logger_1.Logger();
19
+ this.metrics = new metrics_1.CloudWatchMetrics();
18
20
  this.templateMatcher = /{{\s?([^{}\s]*)\s?}}/g;
19
21
  ///
20
22
  /// REQUEST HANDLERS
@@ -104,6 +106,7 @@ class ResourceController extends genericController_1.GenericController {
104
106
  platform = this.queryParams['_p'];
105
107
  delete this.queryParams['_p'];
106
108
  }
109
+ this.prepareMetrics();
107
110
  // print the initial log
108
111
  const info = { principalId: this.principalId, queryParams: this.queryParams, body: this.body, version, platform };
109
112
  this.logger.info(`START: ${this.httpMethod} ${this.path}`, info);
@@ -180,9 +183,9 @@ class ResourceController extends genericController_1.GenericController {
180
183
  this.logger.info('END-FAILED', { statusCode, error: err.message || err.errorMessage });
181
184
  else
182
185
  this.logger.info('END-SUCCESS', { statusCode });
183
- // if configured, store the log of the request
184
186
  if (this.logRequestsWithKey)
185
187
  this.storeLog(!err);
188
+ this.publishMetrics(statusCode, err);
186
189
  this.callback(null, {
187
190
  statusCode: String(statusCode),
188
191
  body: err ? JSON.stringify({ message: err.message }) : JSON.stringify(res || {}),
@@ -309,6 +312,32 @@ class ResourceController extends genericController_1.GenericController {
309
312
  path = `/opt/nodejs/assets/${filePath}`;
310
313
  return path ? (0, fs_1.readFileSync)(path, { encoding: 'utf-8' }) : null;
311
314
  }
315
+ /**
316
+ * Prepare the CloudWatch metrics at the beginning of a request.
317
+ */
318
+ prepareMetrics() {
319
+ this.metrics.addDimension('stage', process.env.STAGE);
320
+ this.metrics.addDimension('resource', process.env.RESOURCE);
321
+ this.metrics.addDimension('method', this.httpMethod);
322
+ this.metrics.addDimension('target', this.resourceId ? 'id' : 'list');
323
+ this.metrics.addDimension('action', this.body?.action);
324
+ this.metrics.addDimension('userId', this.principalId);
325
+ this.metrics.addMetadata('resourceId', this.resourceId);
326
+ }
327
+ /**
328
+ * Publish the CloudWatch metrics (default and custom-defined) at the end of a reqeust.
329
+ */
330
+ publishMetrics(statusCode, error) {
331
+ this.metrics.addMetric('request');
332
+ this.metrics.addMetric('statusCode', statusCode);
333
+ if (error) {
334
+ this.metrics.addMetric('failed');
335
+ this.metrics.addMetadata('errorMessage', error.name);
336
+ }
337
+ else
338
+ this.metrics.addMetric('success');
339
+ this.metrics.publishStoredMetrics();
340
+ }
312
341
  ///
313
342
  /// MANAGE INTERNAL API REQUESTS (lambda invokes masked as API requests)
314
343
  ///
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "idea-aws",
3
- "version": "3.14.1",
3
+ "version": "3.15.0",
4
4
  "description": "AWS wrappers to use in IDEA's back-ends",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -26,7 +26,8 @@
26
26
  "translate",
27
27
  "cognito",
28
28
  "comprehend",
29
- "secretsManager"
29
+ "secretsManager",
30
+ "cloudWatch"
30
31
  ],
31
32
  "author": "ITER IDEA <info@iter-idea.com> (https://iter-idea.com)",
32
33
  "license": "ISC",
@@ -35,7 +36,8 @@
35
36
  },
36
37
  "homepage": "https://iter-idea.github.io/IDEA-AWS",
37
38
  "dependencies": {
38
- "idea-toolbox": "^6.6.2",
39
+ "@aws-lambda-powertools/metrics": "^1.4.1",
40
+ "idea-toolbox": "^6.6.3",
39
41
  "nanoid": "^3.3.4",
40
42
  "nodemailer": "^6.7.7",
41
43
  "shortid": "^2.2.16",