quidproquo-actionprocessor-awslambda 0.0.241 → 0.0.243

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 (29) hide show
  1. package/lib/commonjs/getActionProcessor/core/event/apiGatwayEvent/api/getEventGetRecordsActionProcessor.js +0 -1
  2. package/lib/commonjs/getActionProcessor/core/event/sqs/queue/getEventGetRecordsActionProcessor.js +48 -2
  3. package/lib/commonjs/getActionProcessor/core/event/sqs/queue/types.d.ts +30 -3
  4. package/lib/commonjs/getActionProcessor/core/file/getFileReadObjectJsonActionProcessor.d.ts +2 -0
  5. package/lib/commonjs/getActionProcessor/core/file/getFileReadObjectJsonActionProcessor.js +37 -0
  6. package/lib/commonjs/getActionProcessor/core/file/getFileWriteObjectJsonActionProcessor.d.ts +2 -0
  7. package/lib/commonjs/getActionProcessor/core/file/getFileWriteObjectJsonActionProcessor.js +31 -0
  8. package/lib/commonjs/getActionProcessor/core/file/index.js +3 -1
  9. package/lib/commonjs/getActionProcessor/core/system/getSystemExecuteStoryActionProcessor.js +0 -3
  10. package/lib/commonjs/lambdaHandlers/helpers/logger.js +22 -12
  11. package/lib/commonjs/lambdas/lambda-utils/index.d.ts +0 -1
  12. package/lib/commonjs/lambdas/lambda-utils/index.js +0 -1
  13. package/lib/esm/getActionProcessor/core/event/apiGatwayEvent/api/getEventGetRecordsActionProcessor.js +0 -1
  14. package/lib/esm/getActionProcessor/core/event/sqs/queue/getEventGetRecordsActionProcessor.js +49 -3
  15. package/lib/esm/getActionProcessor/core/event/sqs/queue/types.d.ts +30 -3
  16. package/lib/esm/getActionProcessor/core/file/getFileReadObjectJsonActionProcessor.d.ts +2 -0
  17. package/lib/esm/getActionProcessor/core/file/getFileReadObjectJsonActionProcessor.js +22 -0
  18. package/lib/esm/getActionProcessor/core/file/getFileWriteObjectJsonActionProcessor.d.ts +2 -0
  19. package/lib/esm/getActionProcessor/core/file/getFileWriteObjectJsonActionProcessor.js +16 -0
  20. package/lib/esm/getActionProcessor/core/file/index.js +4 -0
  21. package/lib/esm/getActionProcessor/core/system/getSystemExecuteStoryActionProcessor.js +0 -3
  22. package/lib/esm/lambdaHandlers/helpers/logger.js +26 -13
  23. package/lib/esm/lambdas/lambda-utils/index.d.ts +0 -1
  24. package/lib/esm/lambdas/lambda-utils/index.js +0 -1
  25. package/package.json +5 -5
  26. package/lib/commonjs/lambdas/lambda-utils/logger.d.ts +0 -5
  27. package/lib/commonjs/lambdas/lambda-utils/logger.js +0 -111
  28. package/lib/esm/lambdas/lambda-utils/logger.d.ts +0 -5
  29. package/lib/esm/lambdas/lambda-utils/logger.js +0 -92
@@ -37,7 +37,6 @@ const getProcessGetRecords = (qpqConfig) => {
37
37
  if ((quidproquo_webserver_1.qpqWebServerUtils.getHeaderValue('Content-Type', apiGatewayEvent.headers) || '').startsWith('multipart/form-data') && apiGatewayEvent.body) {
38
38
  internalEventRecord.files = yield (0, parseMultipartFormData_1.parseMultipartFormData)(apiGatewayEvent);
39
39
  }
40
- console.log(JSON.stringify(internalEventRecord, null, 2));
41
40
  return (0, quidproquo_core_1.actionResult)([internalEventRecord]);
42
41
  });
43
42
  };
@@ -11,16 +11,62 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.getEventGetRecordsActionProcessor = void 0;
13
13
  const quidproquo_core_1 = require("quidproquo-core");
14
+ function isCloudWatchAlarmNotification(obj) {
15
+ return typeof obj === 'object' && !!obj.AlarmName && !!obj.Trigger;
16
+ }
17
+ function isErrorsCloudWatchAlarmNotification(cwn) {
18
+ return cwn.Trigger.MetricName === 'Errors' && cwn.Trigger.Namespace === 'AWS/Lambda';
19
+ }
20
+ function isTimeoutCloudWatchAlarmNotification(cwn) {
21
+ return cwn.Trigger.MetricName === 'Timeout' && cwn.Trigger.Namespace === 'AWS/Lambda';
22
+ }
23
+ function isThrottlesCloudWatchAlarmNotification(cwn) {
24
+ return cwn.Trigger.MetricName === 'Throttles' && cwn.Trigger.Namespace === 'AWS/Lambda';
25
+ }
26
+ function buildQueueBaseEvent(messageId, notifyErrorQueueEvents, cloudWatchAlarmNotification) {
27
+ const payload = {
28
+ newStateReason: cloudWatchAlarmNotification.NewStateReason,
29
+ newStateInAlarm: cloudWatchAlarmNotification.NewStateValue === 'ALARM',
30
+ oldStateInAlarm: cloudWatchAlarmNotification.OldStateValue === 'ALARM',
31
+ };
32
+ const queueEvent = {
33
+ id: messageId,
34
+ message: {
35
+ type: notifyErrorQueueEvents,
36
+ payload,
37
+ },
38
+ };
39
+ return queueEvent;
40
+ }
14
41
  const getProcessGetRecords = (qpqConfig) => {
15
42
  return ({ eventParams: [sqsEvent, context] }) => __awaiter(void 0, void 0, void 0, function* () {
16
43
  const records = sqsEvent.Records.map((record) => {
17
44
  const parsedInternalEventRecord = JSON.parse(record.body);
45
+ if (isCloudWatchAlarmNotification(parsedInternalEventRecord)) {
46
+ // Error
47
+ if (isErrorsCloudWatchAlarmNotification(parsedInternalEventRecord)) {
48
+ const queueEvent = buildQueueBaseEvent(record.messageId, quidproquo_core_1.NotifyErrorQueueEvents.Error, parsedInternalEventRecord);
49
+ return queueEvent;
50
+ }
51
+ // Timeout
52
+ else if (isTimeoutCloudWatchAlarmNotification(parsedInternalEventRecord)) {
53
+ const queueEvent = buildQueueBaseEvent(record.messageId, quidproquo_core_1.NotifyErrorQueueEvents.Timeout, parsedInternalEventRecord);
54
+ return queueEvent;
55
+ }
56
+ // Throttle
57
+ else if (isThrottlesCloudWatchAlarmNotification(parsedInternalEventRecord)) {
58
+ const queueEvent = buildQueueBaseEvent(record.messageId, quidproquo_core_1.NotifyErrorQueueEvents.Throttle, parsedInternalEventRecord);
59
+ return queueEvent;
60
+ }
61
+ const queueEvent = buildQueueBaseEvent(record.messageId, quidproquo_core_1.NotifyErrorQueueEvents.Unknown, parsedInternalEventRecord);
62
+ return queueEvent;
63
+ }
18
64
  // TODO: Remove the session from this object
19
65
  // note: we still need to access the session in the story execution for depth and auth etc.
20
66
  const internalEventRecord = {
21
67
  message: {
22
- type: parsedInternalEventRecord.type || 'AWS_ALARM',
23
- payload: parsedInternalEventRecord.payload || {},
68
+ type: parsedInternalEventRecord.type,
69
+ payload: parsedInternalEventRecord.payload,
24
70
  },
25
71
  id: record.messageId,
26
72
  };
@@ -1,6 +1,4 @@
1
- import { MatchStoryResult, QueueMessage, StorySession } from 'quidproquo-core';
2
- import { QueueEventResponse } from 'quidproquo-webserver';
3
- import { QueueEvent } from 'quidproquo-webserver';
1
+ import { MatchStoryResult, QueueEvent, QueueEventResponse, QueueMessage, StorySession } from 'quidproquo-core';
4
2
  import { Context, SQSBatchResponse, SQSEvent } from 'aws-lambda';
5
3
  export type AnyQueueMessageWithSession = QueueMessage<any> & {
6
4
  storySession: StorySession;
@@ -10,3 +8,32 @@ export type EventOutput = SQSBatchResponse;
10
8
  export type InternalEventRecord = QueueEvent<QueueMessage<any>>;
11
9
  export type InternalEventOutput = QueueEventResponse;
12
10
  export type MatchResult = MatchStoryResult<any, any>;
11
+ export interface CloudWatchAlarmNotification {
12
+ AlarmName: string;
13
+ AlarmDescription: string | null;
14
+ AWSAccountId: string;
15
+ AlarmConfigurationUpdatedTimestamp: string;
16
+ NewStateValue: 'OK' | 'ALARM' | 'INSUFFICIENT_DATA';
17
+ NewStateReason: string;
18
+ StateChangeTime: string;
19
+ Region: string;
20
+ AlarmArn: string;
21
+ OldStateValue: string;
22
+ OKActions: string[];
23
+ AlarmActions: string[];
24
+ InsufficientDataActions: string[];
25
+ Trigger: {
26
+ MetricName: string;
27
+ Namespace: string;
28
+ StatisticType: string;
29
+ Statistic: string;
30
+ Unit: string | null;
31
+ Dimensions: any[];
32
+ Period: number;
33
+ EvaluationPeriods: number;
34
+ ComparisonOperator: string;
35
+ Threshold: number;
36
+ TreatMissingData: string;
37
+ EvaluateLowSampleCountPercentile: string;
38
+ };
39
+ }
@@ -0,0 +1,2 @@
1
+ import { ActionProcessorListResolver } from 'quidproquo-core';
2
+ export declare const getFileReadObjectJsonActionProcessor: ActionProcessorListResolver;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getFileReadObjectJsonActionProcessor = void 0;
13
+ const quidproquo_config_aws_1 = require("quidproquo-config-aws");
14
+ const quidproquo_core_1 = require("quidproquo-core");
15
+ const s3Utils_1 = require("../../../logic/s3/s3Utils");
16
+ const utils_1 = require("./utils");
17
+ const getProcessFileReadObjectJson = (qpqConfig) => {
18
+ return ({ drive, filepath }) => __awaiter(void 0, void 0, void 0, function* () {
19
+ try {
20
+ const s3BucketName = (0, utils_1.resolveStorageDriveBucketName)(drive, qpqConfig);
21
+ const json = yield (0, s3Utils_1.readTextFile)(s3BucketName, filepath, quidproquo_config_aws_1.qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig));
22
+ const obj = JSON.parse(json);
23
+ return (0, quidproquo_core_1.actionResult)(obj);
24
+ }
25
+ catch (error) {
26
+ return (0, quidproquo_core_1.actionResultErrorFromCaughtError)(error, {
27
+ InvalidObjectState: () => (0, quidproquo_core_1.actionResultError)(quidproquo_core_1.FileReadObjectJsonErrorTypeEnum.InvalidStorageClass, 'File is in the wrong storage class'),
28
+ });
29
+ }
30
+ });
31
+ };
32
+ const getFileReadObjectJsonActionProcessor = (qpqConfig) => __awaiter(void 0, void 0, void 0, function* () {
33
+ return ({
34
+ [quidproquo_core_1.FileActionType.ReadObjectJson]: getProcessFileReadObjectJson(qpqConfig),
35
+ });
36
+ });
37
+ exports.getFileReadObjectJsonActionProcessor = getFileReadObjectJsonActionProcessor;
@@ -0,0 +1,2 @@
1
+ import { ActionProcessorListResolver } from 'quidproquo-core';
2
+ export declare const getFileWriteObjectJsonActionProcessor: ActionProcessorListResolver;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getFileWriteObjectJsonActionProcessor = void 0;
13
+ const quidproquo_config_aws_1 = require("quidproquo-config-aws");
14
+ const quidproquo_core_1 = require("quidproquo-core");
15
+ const awsLambdaUtils_1 = require("../../../awsLambdaUtils");
16
+ const s3Utils_1 = require("../../../logic/s3/s3Utils");
17
+ const utils_1 = require("./utils");
18
+ const getProcessFileWriteObjectJson = (qpqConfig) => {
19
+ return ({ drive, filepath, data, storageDriveAdvancedWriteOptions }) => __awaiter(void 0, void 0, void 0, function* () {
20
+ const s3BucketName = (0, utils_1.resolveStorageDriveBucketName)(drive, qpqConfig);
21
+ const dataJson = JSON.stringify(data);
22
+ yield (0, s3Utils_1.writeTextFile)(s3BucketName, filepath, dataJson, quidproquo_config_aws_1.qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig), (0, awsLambdaUtils_1.getS3BucketStorageClassFromStorageDriveTier)(storageDriveAdvancedWriteOptions === null || storageDriveAdvancedWriteOptions === void 0 ? void 0 : storageDriveAdvancedWriteOptions.storageDriveTier));
23
+ return (0, quidproquo_core_1.actionResult)(void 0);
24
+ });
25
+ };
26
+ const getFileWriteObjectJsonActionProcessor = (qpqConfig) => __awaiter(void 0, void 0, void 0, function* () {
27
+ return ({
28
+ [quidproquo_core_1.FileActionType.WriteObjectJson]: getProcessFileWriteObjectJson(qpqConfig),
29
+ });
30
+ });
31
+ exports.getFileWriteObjectJsonActionProcessor = getFileWriteObjectJsonActionProcessor;
@@ -16,10 +16,12 @@ const getFileGenerateTemporarySecureUrlActionProcessor_1 = require("./getFileGen
16
16
  const getFileIsColdStorageActionProcessor_1 = require("./getFileIsColdStorageActionProcessor");
17
17
  const getFileListDirectoryActionProcessor_1 = require("./getFileListDirectoryActionProcessor");
18
18
  const getFileReadBinaryContentsActionProcessor_1 = require("./getFileReadBinaryContentsActionProcessor");
19
+ const getFileReadObjectJsonActionProcessor_1 = require("./getFileReadObjectJsonActionProcessor");
19
20
  const getFileReadTextContentsActionProcessor_1 = require("./getFileReadTextContentsActionProcessor");
20
21
  const getFileWriteBinaryContentsActionProcessor_1 = require("./getFileWriteBinaryContentsActionProcessor");
22
+ const getFileWriteObjectJsonActionProcessor_1 = require("./getFileWriteObjectJsonActionProcessor");
21
23
  const getFileWriteTextContentsActionProcessor_1 = require("./getFileWriteTextContentsActionProcessor");
22
24
  const getFileActionProcessor = (qpqConfig, dynamicModuleLoader) => __awaiter(void 0, void 0, void 0, function* () {
23
- return (Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (yield (0, getFileDeleteActionProcessor_1.getFileDeleteActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileExistsActionProcessor_1.getFileExistsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileGenerateTemporarySecureUrlActionProcessor_1.getFileGenerateTemporarySecureUrlActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileIsColdStorageActionProcessor_1.getFileIsColdStorageActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileListDirectoryActionProcessor_1.getFileListDirectoryActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileReadTextContentsActionProcessor_1.getFileReadTextContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileWriteTextContentsActionProcessor_1.getFileWriteTextContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileReadBinaryContentsActionProcessor_1.getFileReadBinaryContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileWriteBinaryContentsActionProcessor_1.getFileWriteBinaryContentsActionProcessor)(qpqConfig, dynamicModuleLoader))));
25
+ return (Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (yield (0, getFileDeleteActionProcessor_1.getFileDeleteActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileExistsActionProcessor_1.getFileExistsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileGenerateTemporarySecureUrlActionProcessor_1.getFileGenerateTemporarySecureUrlActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileIsColdStorageActionProcessor_1.getFileIsColdStorageActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileListDirectoryActionProcessor_1.getFileListDirectoryActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileReadTextContentsActionProcessor_1.getFileReadTextContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileReadObjectJsonActionProcessor_1.getFileReadObjectJsonActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileWriteTextContentsActionProcessor_1.getFileWriteTextContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileReadBinaryContentsActionProcessor_1.getFileReadBinaryContentsActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileWriteObjectJsonActionProcessor_1.getFileWriteObjectJsonActionProcessor)(qpqConfig, dynamicModuleLoader))), (yield (0, getFileWriteBinaryContentsActionProcessor_1.getFileWriteBinaryContentsActionProcessor)(qpqConfig, dynamicModuleLoader))));
24
26
  });
25
27
  exports.getFileActionProcessor = getFileActionProcessor;
@@ -18,11 +18,8 @@ const getProcessExecuteStory = (qpqConfig) => {
18
18
  const moduleName = quidproquo_core_1.qpqCoreUtils.getApplicationModuleName(qpqConfig);
19
19
  return (payload, session, actionProcessors, logger, updateSession, dynamicModuleLoader) => __awaiter(void 0, void 0, void 0, function* () {
20
20
  var _a, _b, _c, _d;
21
- console.log('Trying to load module');
22
21
  let story = yield dynamicModuleLoader(payload.runtime);
23
- console.log('After - Trying to load module');
24
22
  if (!story) {
25
- console.log('No story');
26
23
  return (0, quidproquo_core_1.actionResultError)(quidproquo_core_1.ErrorTypeEnum.NotFound, `Unable to dynamically load: [${payload.runtime}]`);
27
24
  }
28
25
  const resolveStory = (0, quidproquo_core_1.createRuntime)(qpqConfig, {
@@ -20,7 +20,7 @@ const client_s3_1 = require("@aws-sdk/client-s3");
20
20
  const awsNamingUtils_1 = require("../../awsNamingUtils");
21
21
  const tempDirectory = '/tmp/qpqlogs';
22
22
  const quidproquo_config_aws_1 = require("quidproquo-config-aws");
23
- const crypto_1 = require("crypto");
23
+ const quidproquo_core_2 = require("quidproquo-core");
24
24
  const storyLogger = (result, bucketName, region) => __awaiter(void 0, void 0, void 0, function* () {
25
25
  try {
26
26
  const s3Client = new client_s3_1.S3Client({ region });
@@ -32,8 +32,8 @@ const storyLogger = (result, bucketName, region) => __awaiter(void 0, void 0, vo
32
32
  };
33
33
  yield s3Client.send(new client_s3_1.PutObjectCommand(commandParams));
34
34
  }
35
- catch (_a) {
36
- console.log(`Failed to log story result to S3 [${result.correlation}]`);
35
+ catch (error) {
36
+ console.log(`Failed to log story result to S3 [${result.correlation}]:`, error);
37
37
  }
38
38
  });
39
39
  exports.storyLogger = storyLogger;
@@ -74,6 +74,7 @@ const getLogger = (qpqConfig) => {
74
74
  // If we have no log service, just return nothing.
75
75
  if (!awsSettings.logServiceName || awsSettings.disableLogs || process.env.storageDriveName === 'qpq-logs') {
76
76
  return {
77
+ enableLogs: () => __awaiter(void 0, void 0, void 0, function* () { }),
77
78
  log: () => __awaiter(void 0, void 0, void 0, function* () { }),
78
79
  waitToFinishWriting: () => __awaiter(void 0, void 0, void 0, function* () { }),
79
80
  moveToPermanentStorage: () => __awaiter(void 0, void 0, void 0, function* () { }),
@@ -83,28 +84,37 @@ const getLogger = (qpqConfig) => {
83
84
  const application = quidproquo_core_1.qpqCoreUtils.getApplicationName(qpqConfig);
84
85
  const environment = quidproquo_core_1.qpqCoreUtils.getApplicationModuleEnvironment(qpqConfig);
85
86
  const feature = quidproquo_core_1.qpqCoreUtils.getApplicationModuleFeature(qpqConfig);
86
- console.log('Env for bucket: ', environment);
87
87
  // Workout the bucket name.
88
88
  const bucketName = (0, awsNamingUtils_1.getConfigRuntimeResourceName)('qpq-logs', application, service, environment, feature);
89
89
  // Where is this bucket?
90
90
  const regionForBucket = (0, quidproquo_config_aws_1.getAwsServiceAccountInfoByDeploymentInfo)(qpqConfig, service, environment, feature, application).awsRegion;
91
- console.log('Bucket for logs: ', bucketName, regionForBucket);
92
91
  const logs = [];
92
+ let disabledLogCorrelations = [];
93
93
  return {
94
+ enableLogs: (enable, reason, correlation) => __awaiter(void 0, void 0, void 0, function* () {
95
+ if (!enable) {
96
+ disabledLogCorrelations = [...disabledLogCorrelations, correlation];
97
+ }
98
+ else {
99
+ disabledLogCorrelations = disabledLogCorrelations.filter((dlc) => dlc !== correlation);
100
+ }
101
+ }),
94
102
  log: (result) => __awaiter(void 0, void 0, void 0, function* () {
95
- const promise = (0, exports.storyLogger)(result, bucketName, regionForBucket).catch((e) => {
103
+ let modifyableResult = !disabledLogCorrelations.includes(result.correlation)
104
+ ? result
105
+ : Object.assign(Object.assign({}, result), { history: (0, quidproquo_core_2.filterLogHistoryByActionTypes)(result.history, [
106
+ quidproquo_core_1.LogActionType.Create,
107
+ quidproquo_core_1.LogActionType.TemplateLiteral,
108
+ quidproquo_core_1.LogActionType.DisableEventHistory,
109
+ ]) });
110
+ // TODO: Filter and flatten histories log histories
111
+ const promise = (0, exports.storyLogger)(modifyableResult, bucketName, regionForBucket).catch((e) => {
96
112
  console.log('Failed to log story result to S3', JSON.stringify(e, null, 2));
97
113
  });
98
114
  logs.push(promise);
99
- console.log('Added to logs', logs.length);
100
115
  }),
101
116
  waitToFinishWriting: () => __awaiter(void 0, void 0, void 0, function* () {
102
- console.log('logs.length', logs.length);
103
- const id = (0, crypto_1.randomUUID)();
104
- console.time(`Writing Logs ${id}`);
105
117
  yield Promise.all(logs);
106
- console.timeEnd(`Writing Logs ${id}`);
107
- console.log('done writing logs');
108
118
  }),
109
119
  moveToPermanentStorage: () => __awaiter(void 0, void 0, void 0, function* () {
110
120
  yield (0, exports.moveLogsToPerminateStorage)(bucketName, regionForBucket);
@@ -1,2 +1 @@
1
1
  export * from './getQpqConfig';
2
- export * from './logger';
@@ -15,4 +15,3 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./getQpqConfig"), exports);
18
- __exportStar(require("./logger"), exports);
@@ -28,7 +28,6 @@ const getProcessGetRecords = (qpqConfig) => {
28
28
  if ((qpqWebServerUtils.getHeaderValue('Content-Type', apiGatewayEvent.headers) || '').startsWith('multipart/form-data') && apiGatewayEvent.body) {
29
29
  internalEventRecord.files = await parseMultipartFormData(apiGatewayEvent);
30
30
  }
31
- console.log(JSON.stringify(internalEventRecord, null, 2));
32
31
  return actionResult([internalEventRecord]);
33
32
  };
34
33
  };
@@ -1,14 +1,60 @@
1
- import { actionResult, EventActionType, } from 'quidproquo-core';
1
+ import { actionResult, EventActionType, NotifyErrorQueueEvents, } from 'quidproquo-core';
2
+ function isCloudWatchAlarmNotification(obj) {
3
+ return typeof obj === 'object' && !!obj.AlarmName && !!obj.Trigger;
4
+ }
5
+ function isErrorsCloudWatchAlarmNotification(cwn) {
6
+ return cwn.Trigger.MetricName === 'Errors' && cwn.Trigger.Namespace === 'AWS/Lambda';
7
+ }
8
+ function isTimeoutCloudWatchAlarmNotification(cwn) {
9
+ return cwn.Trigger.MetricName === 'Timeout' && cwn.Trigger.Namespace === 'AWS/Lambda';
10
+ }
11
+ function isThrottlesCloudWatchAlarmNotification(cwn) {
12
+ return cwn.Trigger.MetricName === 'Throttles' && cwn.Trigger.Namespace === 'AWS/Lambda';
13
+ }
14
+ function buildQueueBaseEvent(messageId, notifyErrorQueueEvents, cloudWatchAlarmNotification) {
15
+ const payload = {
16
+ newStateReason: cloudWatchAlarmNotification.NewStateReason,
17
+ newStateInAlarm: cloudWatchAlarmNotification.NewStateValue === 'ALARM',
18
+ oldStateInAlarm: cloudWatchAlarmNotification.OldStateValue === 'ALARM',
19
+ };
20
+ const queueEvent = {
21
+ id: messageId,
22
+ message: {
23
+ type: notifyErrorQueueEvents,
24
+ payload,
25
+ },
26
+ };
27
+ return queueEvent;
28
+ }
2
29
  const getProcessGetRecords = (qpqConfig) => {
3
30
  return async ({ eventParams: [sqsEvent, context] }) => {
4
31
  const records = sqsEvent.Records.map((record) => {
5
32
  const parsedInternalEventRecord = JSON.parse(record.body);
33
+ if (isCloudWatchAlarmNotification(parsedInternalEventRecord)) {
34
+ // Error
35
+ if (isErrorsCloudWatchAlarmNotification(parsedInternalEventRecord)) {
36
+ const queueEvent = buildQueueBaseEvent(record.messageId, NotifyErrorQueueEvents.Error, parsedInternalEventRecord);
37
+ return queueEvent;
38
+ }
39
+ // Timeout
40
+ else if (isTimeoutCloudWatchAlarmNotification(parsedInternalEventRecord)) {
41
+ const queueEvent = buildQueueBaseEvent(record.messageId, NotifyErrorQueueEvents.Timeout, parsedInternalEventRecord);
42
+ return queueEvent;
43
+ }
44
+ // Throttle
45
+ else if (isThrottlesCloudWatchAlarmNotification(parsedInternalEventRecord)) {
46
+ const queueEvent = buildQueueBaseEvent(record.messageId, NotifyErrorQueueEvents.Throttle, parsedInternalEventRecord);
47
+ return queueEvent;
48
+ }
49
+ const queueEvent = buildQueueBaseEvent(record.messageId, NotifyErrorQueueEvents.Unknown, parsedInternalEventRecord);
50
+ return queueEvent;
51
+ }
6
52
  // TODO: Remove the session from this object
7
53
  // note: we still need to access the session in the story execution for depth and auth etc.
8
54
  const internalEventRecord = {
9
55
  message: {
10
- type: parsedInternalEventRecord.type || 'AWS_ALARM',
11
- payload: parsedInternalEventRecord.payload || {},
56
+ type: parsedInternalEventRecord.type,
57
+ payload: parsedInternalEventRecord.payload,
12
58
  },
13
59
  id: record.messageId,
14
60
  };
@@ -1,6 +1,4 @@
1
- import { MatchStoryResult, QueueMessage, StorySession } from 'quidproquo-core';
2
- import { QueueEventResponse } from 'quidproquo-webserver';
3
- import { QueueEvent } from 'quidproquo-webserver';
1
+ import { MatchStoryResult, QueueEvent, QueueEventResponse, QueueMessage, StorySession } from 'quidproquo-core';
4
2
  import { Context, SQSBatchResponse, SQSEvent } from 'aws-lambda';
5
3
  export type AnyQueueMessageWithSession = QueueMessage<any> & {
6
4
  storySession: StorySession;
@@ -10,3 +8,32 @@ export type EventOutput = SQSBatchResponse;
10
8
  export type InternalEventRecord = QueueEvent<QueueMessage<any>>;
11
9
  export type InternalEventOutput = QueueEventResponse;
12
10
  export type MatchResult = MatchStoryResult<any, any>;
11
+ export interface CloudWatchAlarmNotification {
12
+ AlarmName: string;
13
+ AlarmDescription: string | null;
14
+ AWSAccountId: string;
15
+ AlarmConfigurationUpdatedTimestamp: string;
16
+ NewStateValue: 'OK' | 'ALARM' | 'INSUFFICIENT_DATA';
17
+ NewStateReason: string;
18
+ StateChangeTime: string;
19
+ Region: string;
20
+ AlarmArn: string;
21
+ OldStateValue: string;
22
+ OKActions: string[];
23
+ AlarmActions: string[];
24
+ InsufficientDataActions: string[];
25
+ Trigger: {
26
+ MetricName: string;
27
+ Namespace: string;
28
+ StatisticType: string;
29
+ Statistic: string;
30
+ Unit: string | null;
31
+ Dimensions: any[];
32
+ Period: number;
33
+ EvaluationPeriods: number;
34
+ ComparisonOperator: string;
35
+ Threshold: number;
36
+ TreatMissingData: string;
37
+ EvaluateLowSampleCountPercentile: string;
38
+ };
39
+ }
@@ -0,0 +1,2 @@
1
+ import { ActionProcessorListResolver } from 'quidproquo-core';
2
+ export declare const getFileReadObjectJsonActionProcessor: ActionProcessorListResolver;
@@ -0,0 +1,22 @@
1
+ import { qpqConfigAwsUtils } from 'quidproquo-config-aws';
2
+ import { actionResult, actionResultError, actionResultErrorFromCaughtError, FileActionType, FileReadObjectJsonErrorTypeEnum, } from 'quidproquo-core';
3
+ import { readTextFile } from '../../../logic/s3/s3Utils';
4
+ import { resolveStorageDriveBucketName } from './utils';
5
+ const getProcessFileReadObjectJson = (qpqConfig) => {
6
+ return async ({ drive, filepath }) => {
7
+ try {
8
+ const s3BucketName = resolveStorageDriveBucketName(drive, qpqConfig);
9
+ const json = await readTextFile(s3BucketName, filepath, qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig));
10
+ const obj = JSON.parse(json);
11
+ return actionResult(obj);
12
+ }
13
+ catch (error) {
14
+ return actionResultErrorFromCaughtError(error, {
15
+ InvalidObjectState: () => actionResultError(FileReadObjectJsonErrorTypeEnum.InvalidStorageClass, 'File is in the wrong storage class'),
16
+ });
17
+ }
18
+ };
19
+ };
20
+ export const getFileReadObjectJsonActionProcessor = async (qpqConfig) => ({
21
+ [FileActionType.ReadObjectJson]: getProcessFileReadObjectJson(qpqConfig),
22
+ });
@@ -0,0 +1,2 @@
1
+ import { ActionProcessorListResolver } from 'quidproquo-core';
2
+ export declare const getFileWriteObjectJsonActionProcessor: ActionProcessorListResolver;
@@ -0,0 +1,16 @@
1
+ import { qpqConfigAwsUtils } from 'quidproquo-config-aws';
2
+ import { actionResult, FileActionType, } from 'quidproquo-core';
3
+ import { getS3BucketStorageClassFromStorageDriveTier } from '../../../awsLambdaUtils';
4
+ import { writeTextFile } from '../../../logic/s3/s3Utils';
5
+ import { resolveStorageDriveBucketName } from './utils';
6
+ const getProcessFileWriteObjectJson = (qpqConfig) => {
7
+ return async ({ drive, filepath, data, storageDriveAdvancedWriteOptions }) => {
8
+ const s3BucketName = resolveStorageDriveBucketName(drive, qpqConfig);
9
+ const dataJson = JSON.stringify(data);
10
+ await writeTextFile(s3BucketName, filepath, dataJson, qpqConfigAwsUtils.getApplicationModuleDeployRegion(qpqConfig), getS3BucketStorageClassFromStorageDriveTier(storageDriveAdvancedWriteOptions?.storageDriveTier));
11
+ return actionResult(void 0);
12
+ };
13
+ };
14
+ export const getFileWriteObjectJsonActionProcessor = async (qpqConfig) => ({
15
+ [FileActionType.WriteObjectJson]: getProcessFileWriteObjectJson(qpqConfig),
16
+ });
@@ -4,8 +4,10 @@ import { getFileGenerateTemporarySecureUrlActionProcessor } from './getFileGener
4
4
  import { getFileIsColdStorageActionProcessor } from './getFileIsColdStorageActionProcessor';
5
5
  import { getFileListDirectoryActionProcessor } from './getFileListDirectoryActionProcessor';
6
6
  import { getFileReadBinaryContentsActionProcessor } from './getFileReadBinaryContentsActionProcessor';
7
+ import { getFileReadObjectJsonActionProcessor } from './getFileReadObjectJsonActionProcessor';
7
8
  import { getFileReadTextContentsActionProcessor } from './getFileReadTextContentsActionProcessor';
8
9
  import { getFileWriteBinaryContentsActionProcessor } from './getFileWriteBinaryContentsActionProcessor';
10
+ import { getFileWriteObjectJsonActionProcessor } from './getFileWriteObjectJsonActionProcessor';
9
11
  import { getFileWriteTextContentsActionProcessor } from './getFileWriteTextContentsActionProcessor';
10
12
  export const getFileActionProcessor = async (qpqConfig, dynamicModuleLoader) => ({
11
13
  ...(await getFileDeleteActionProcessor(qpqConfig, dynamicModuleLoader)),
@@ -14,7 +16,9 @@ export const getFileActionProcessor = async (qpqConfig, dynamicModuleLoader) =>
14
16
  ...(await getFileIsColdStorageActionProcessor(qpqConfig, dynamicModuleLoader)),
15
17
  ...(await getFileListDirectoryActionProcessor(qpqConfig, dynamicModuleLoader)),
16
18
  ...(await getFileReadTextContentsActionProcessor(qpqConfig, dynamicModuleLoader)),
19
+ ...(await getFileReadObjectJsonActionProcessor(qpqConfig, dynamicModuleLoader)),
17
20
  ...(await getFileWriteTextContentsActionProcessor(qpqConfig, dynamicModuleLoader)),
18
21
  ...(await getFileReadBinaryContentsActionProcessor(qpqConfig, dynamicModuleLoader)),
22
+ ...(await getFileWriteObjectJsonActionProcessor(qpqConfig, dynamicModuleLoader)),
19
23
  ...(await getFileWriteBinaryContentsActionProcessor(qpqConfig, dynamicModuleLoader)),
20
24
  });
@@ -4,11 +4,8 @@ export const getDateNow = () => new Date().toISOString();
4
4
  const getProcessExecuteStory = (qpqConfig) => {
5
5
  const moduleName = qpqCoreUtils.getApplicationModuleName(qpqConfig);
6
6
  return async (payload, session, actionProcessors, logger, updateSession, dynamicModuleLoader) => {
7
- console.log('Trying to load module');
8
7
  let story = await dynamicModuleLoader(payload.runtime);
9
- console.log('After - Trying to load module');
10
8
  if (!story) {
11
- console.log('No story');
12
9
  return actionResultError(ErrorTypeEnum.NotFound, `Unable to dynamically load: [${payload.runtime}]`);
13
10
  }
14
11
  const resolveStory = createRuntime(qpqConfig, {
@@ -1,11 +1,11 @@
1
- import { qpqCoreUtils } from 'quidproquo-core';
1
+ import { LogActionType, qpqCoreUtils } from 'quidproquo-core';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
4
  import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
5
5
  import { getConfigRuntimeResourceName } from '../../awsNamingUtils';
6
6
  const tempDirectory = '/tmp/qpqlogs';
7
7
  import { getAwsServiceAccountInfoByDeploymentInfo, getAwsServiceAccountInfoConfig } from 'quidproquo-config-aws';
8
- import { randomUUID } from 'crypto';
8
+ import { filterLogHistoryByActionTypes } from 'quidproquo-core';
9
9
  export const storyLogger = async (result, bucketName, region) => {
10
10
  try {
11
11
  const s3Client = new S3Client({ region });
@@ -17,8 +17,8 @@ export const storyLogger = async (result, bucketName, region) => {
17
17
  };
18
18
  await s3Client.send(new PutObjectCommand(commandParams));
19
19
  }
20
- catch {
21
- console.log(`Failed to log story result to S3 [${result.correlation}]`);
20
+ catch (error) {
21
+ console.log(`Failed to log story result to S3 [${result.correlation}]:`, error);
22
22
  }
23
23
  };
24
24
  export const storyLoggerFs = async (result) => {
@@ -56,6 +56,7 @@ export const getLogger = (qpqConfig) => {
56
56
  // If we have no log service, just return nothing.
57
57
  if (!awsSettings.logServiceName || awsSettings.disableLogs || process.env.storageDriveName === 'qpq-logs') {
58
58
  return {
59
+ enableLogs: async () => { },
59
60
  log: async () => { },
60
61
  waitToFinishWriting: async () => { },
61
62
  moveToPermanentStorage: async () => { },
@@ -65,28 +66,40 @@ export const getLogger = (qpqConfig) => {
65
66
  const application = qpqCoreUtils.getApplicationName(qpqConfig);
66
67
  const environment = qpqCoreUtils.getApplicationModuleEnvironment(qpqConfig);
67
68
  const feature = qpqCoreUtils.getApplicationModuleFeature(qpqConfig);
68
- console.log('Env for bucket: ', environment);
69
69
  // Workout the bucket name.
70
70
  const bucketName = getConfigRuntimeResourceName('qpq-logs', application, service, environment, feature);
71
71
  // Where is this bucket?
72
72
  const regionForBucket = getAwsServiceAccountInfoByDeploymentInfo(qpqConfig, service, environment, feature, application).awsRegion;
73
- console.log('Bucket for logs: ', bucketName, regionForBucket);
74
73
  const logs = [];
74
+ let disabledLogCorrelations = [];
75
75
  return {
76
+ enableLogs: async (enable, reason, correlation) => {
77
+ if (!enable) {
78
+ disabledLogCorrelations = [...disabledLogCorrelations, correlation];
79
+ }
80
+ else {
81
+ disabledLogCorrelations = disabledLogCorrelations.filter((dlc) => dlc !== correlation);
82
+ }
83
+ },
76
84
  log: async (result) => {
77
- const promise = storyLogger(result, bucketName, regionForBucket).catch((e) => {
85
+ let modifyableResult = !disabledLogCorrelations.includes(result.correlation)
86
+ ? result
87
+ : {
88
+ ...result,
89
+ history: filterLogHistoryByActionTypes(result.history, [
90
+ LogActionType.Create,
91
+ LogActionType.TemplateLiteral,
92
+ LogActionType.DisableEventHistory,
93
+ ]),
94
+ };
95
+ // TODO: Filter and flatten histories log histories
96
+ const promise = storyLogger(modifyableResult, bucketName, regionForBucket).catch((e) => {
78
97
  console.log('Failed to log story result to S3', JSON.stringify(e, null, 2));
79
98
  });
80
99
  logs.push(promise);
81
- console.log('Added to logs', logs.length);
82
100
  },
83
101
  waitToFinishWriting: async () => {
84
- console.log('logs.length', logs.length);
85
- const id = randomUUID();
86
- console.time(`Writing Logs ${id}`);
87
102
  await Promise.all(logs);
88
- console.timeEnd(`Writing Logs ${id}`);
89
- console.log('done writing logs');
90
103
  },
91
104
  moveToPermanentStorage: async () => {
92
105
  await moveLogsToPerminateStorage(bucketName, regionForBucket);
@@ -1,2 +1 @@
1
1
  export * from './getQpqConfig';
2
- export * from './logger';
@@ -1,2 +1 @@
1
1
  export * from './getQpqConfig';
2
- export * from './logger';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quidproquo-actionprocessor-awslambda",
3
- "version": "0.0.241",
3
+ "version": "0.0.243",
4
4
  "description": "",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -55,9 +55,9 @@
55
55
  "lodash": "^4.17.21",
56
56
  "node-cache": "^5.1.2",
57
57
  "node-match-path": "^0.6.3",
58
- "quidproquo-config-aws": "0.0.241",
59
- "quidproquo-core": "0.0.241",
60
- "quidproquo-webserver": "0.0.241"
58
+ "quidproquo-config-aws": "0.0.243",
59
+ "quidproquo-core": "0.0.243",
60
+ "quidproquo-webserver": "0.0.243"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@types/aws-lambda": "^8.10.109",
@@ -65,7 +65,7 @@
65
65
  "@types/jsonwebtoken": "^9.0.2",
66
66
  "@types/lodash": "^4.14.194",
67
67
  "@types/node": "^18.11.9",
68
- "quidproquo-tsconfig": "0.0.241",
68
+ "quidproquo-tsconfig": "0.0.243",
69
69
  "typescript": "^4.9.3"
70
70
  }
71
71
  }
@@ -1,5 +0,0 @@
1
- import { QPQConfig, QpqLogger, StoryResult } from 'quidproquo-core';
2
- export declare const storyLogger: (result: StoryResult<any>, bucketName: string, region: string) => Promise<void>;
3
- export declare const storyLoggerFs: (result: StoryResult<any>) => Promise<void>;
4
- export declare const moveLogsToPerminateStorage: (bucketName: string, region: string) => Promise<void>;
5
- export declare const getLogger: (qpqConfig: QPQConfig) => QpqLogger;
@@ -1,111 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.getLogger = exports.moveLogsToPerminateStorage = exports.storyLoggerFs = exports.storyLogger = void 0;
16
- const quidproquo_core_1 = require("quidproquo-core");
17
- const fs_1 = __importDefault(require("fs"));
18
- const path_1 = __importDefault(require("path"));
19
- const client_s3_1 = require("@aws-sdk/client-s3");
20
- const tempDirectory = '/tmp/qpqlogs';
21
- const quidproquo_config_aws_1 = require("quidproquo-config-aws");
22
- const awsNamingUtils_1 = require("../../awsNamingUtils");
23
- const storyLogger = (result, bucketName, region) => __awaiter(void 0, void 0, void 0, function* () {
24
- try {
25
- const s3Client = new client_s3_1.S3Client({ region });
26
- const commandParams = {
27
- Key: `${result.correlation}.json`,
28
- Bucket: bucketName,
29
- Body: JSON.stringify(result),
30
- StorageClass: 'INTELLIGENT_TIERING',
31
- };
32
- yield s3Client.send(new client_s3_1.PutObjectCommand(commandParams));
33
- }
34
- catch (_a) {
35
- console.log(`Failed to log story result to S3 [${result.correlation}]`);
36
- }
37
- });
38
- exports.storyLogger = storyLogger;
39
- const storyLoggerFs = (result) => __awaiter(void 0, void 0, void 0, function* () {
40
- try {
41
- yield fs_1.default.promises.mkdir(tempDirectory, { recursive: true });
42
- const filePath = path_1.default.join(tempDirectory, `${result.correlation}.json`);
43
- yield fs_1.default.promises.writeFile(filePath, JSON.stringify(result));
44
- console.log(`Story result logged to temporary file [${filePath}]`);
45
- }
46
- catch (error) {
47
- console.log(`Failed to log story result to temporary file [${result.correlation}]`);
48
- console.error(error);
49
- }
50
- });
51
- exports.storyLoggerFs = storyLoggerFs;
52
- const moveLogsToPerminateStorage = (bucketName, region) => __awaiter(void 0, void 0, void 0, function* () {
53
- try {
54
- yield fs_1.default.promises.mkdir(tempDirectory, { recursive: true });
55
- const files = yield fs_1.default.promises.readdir(tempDirectory);
56
- for (const file of files) {
57
- const filePath = path_1.default.join(tempDirectory, file);
58
- const data = yield fs_1.default.promises.readFile(filePath, 'utf-8');
59
- const result = JSON.parse(data);
60
- yield (0, exports.storyLogger)(result, bucketName, region);
61
- yield fs_1.default.promises.unlink(filePath);
62
- console.log(`Moved log file [${file}] to S3 and deleted from temporary directory`);
63
- }
64
- }
65
- catch (error) {
66
- console.error('Failed to move logs to permanent storage');
67
- console.error(error);
68
- }
69
- });
70
- exports.moveLogsToPerminateStorage = moveLogsToPerminateStorage;
71
- const getLogger = (qpqConfig) => {
72
- const awsSettings = (0, quidproquo_config_aws_1.getAwsServiceAccountInfoConfig)(qpqConfig);
73
- // If we have no log service, just return nothing.
74
- if (!awsSettings.logServiceName || awsSettings.disableLogs || process.env.storageDriveName === 'qpq-logs') {
75
- return {
76
- log: () => __awaiter(void 0, void 0, void 0, function* () { }),
77
- waitToFinishWriting: () => __awaiter(void 0, void 0, void 0, function* () { }),
78
- moveToPermanentStorage: () => __awaiter(void 0, void 0, void 0, function* () { }),
79
- };
80
- }
81
- const service = awsSettings.logServiceName;
82
- const application = quidproquo_core_1.qpqCoreUtils.getApplicationName(qpqConfig);
83
- const environment = quidproquo_core_1.qpqCoreUtils.getApplicationModuleEnvironment(qpqConfig);
84
- const feature = quidproquo_core_1.qpqCoreUtils.getApplicationModuleFeature(qpqConfig);
85
- // Workout the bucket name.
86
- const bucketName = (0, awsNamingUtils_1.getConfigRuntimeResourceName)('qpq-logs', application, service, environment, feature);
87
- // Where is this bucket?
88
- const regionForBucket = (0, quidproquo_config_aws_1.getAwsServiceAccountInfoByDeploymentInfo)(qpqConfig, service, environment, feature, application).awsRegion;
89
- console.log('Bucket for logs: ', bucketName, regionForBucket);
90
- const logs = [];
91
- return {
92
- log: (result) => __awaiter(void 0, void 0, void 0, function* () {
93
- const promise = (0, exports.storyLogger)(result, bucketName, regionForBucket).catch((e) => {
94
- console.log('Failed to log story result to S3', JSON.stringify(e, null, 2));
95
- });
96
- logs.push(promise);
97
- console.log('Added to logs', logs.length);
98
- }),
99
- waitToFinishWriting: () => __awaiter(void 0, void 0, void 0, function* () {
100
- console.log('logs.length', logs.length);
101
- console.time('Writing Logs');
102
- yield Promise.all(logs);
103
- console.timeEnd('Writing Logs');
104
- console.log('done writing logs');
105
- }),
106
- moveToPermanentStorage: () => __awaiter(void 0, void 0, void 0, function* () {
107
- yield (0, exports.moveLogsToPerminateStorage)(bucketName, regionForBucket);
108
- }),
109
- };
110
- };
111
- exports.getLogger = getLogger;
@@ -1,5 +0,0 @@
1
- import { QPQConfig, QpqLogger, StoryResult } from 'quidproquo-core';
2
- export declare const storyLogger: (result: StoryResult<any>, bucketName: string, region: string) => Promise<void>;
3
- export declare const storyLoggerFs: (result: StoryResult<any>) => Promise<void>;
4
- export declare const moveLogsToPerminateStorage: (bucketName: string, region: string) => Promise<void>;
5
- export declare const getLogger: (qpqConfig: QPQConfig) => QpqLogger;
@@ -1,92 +0,0 @@
1
- import { qpqCoreUtils } from 'quidproquo-core';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
5
- const tempDirectory = '/tmp/qpqlogs';
6
- import { getAwsServiceAccountInfoByDeploymentInfo, getAwsServiceAccountInfoConfig } from 'quidproquo-config-aws';
7
- import { getConfigRuntimeResourceName } from '../../awsNamingUtils';
8
- export const storyLogger = async (result, bucketName, region) => {
9
- try {
10
- const s3Client = new S3Client({ region });
11
- const commandParams = {
12
- Key: `${result.correlation}.json`,
13
- Bucket: bucketName,
14
- Body: JSON.stringify(result),
15
- StorageClass: 'INTELLIGENT_TIERING',
16
- };
17
- await s3Client.send(new PutObjectCommand(commandParams));
18
- }
19
- catch {
20
- console.log(`Failed to log story result to S3 [${result.correlation}]`);
21
- }
22
- };
23
- export const storyLoggerFs = async (result) => {
24
- try {
25
- await fs.promises.mkdir(tempDirectory, { recursive: true });
26
- const filePath = path.join(tempDirectory, `${result.correlation}.json`);
27
- await fs.promises.writeFile(filePath, JSON.stringify(result));
28
- console.log(`Story result logged to temporary file [${filePath}]`);
29
- }
30
- catch (error) {
31
- console.log(`Failed to log story result to temporary file [${result.correlation}]`);
32
- console.error(error);
33
- }
34
- };
35
- export const moveLogsToPerminateStorage = async (bucketName, region) => {
36
- try {
37
- await fs.promises.mkdir(tempDirectory, { recursive: true });
38
- const files = await fs.promises.readdir(tempDirectory);
39
- for (const file of files) {
40
- const filePath = path.join(tempDirectory, file);
41
- const data = await fs.promises.readFile(filePath, 'utf-8');
42
- const result = JSON.parse(data);
43
- await storyLogger(result, bucketName, region);
44
- await fs.promises.unlink(filePath);
45
- console.log(`Moved log file [${file}] to S3 and deleted from temporary directory`);
46
- }
47
- }
48
- catch (error) {
49
- console.error('Failed to move logs to permanent storage');
50
- console.error(error);
51
- }
52
- };
53
- export const getLogger = (qpqConfig) => {
54
- const awsSettings = getAwsServiceAccountInfoConfig(qpqConfig);
55
- // If we have no log service, just return nothing.
56
- if (!awsSettings.logServiceName || awsSettings.disableLogs || process.env.storageDriveName === 'qpq-logs') {
57
- return {
58
- log: async () => { },
59
- waitToFinishWriting: async () => { },
60
- moveToPermanentStorage: async () => { },
61
- };
62
- }
63
- const service = awsSettings.logServiceName;
64
- const application = qpqCoreUtils.getApplicationName(qpqConfig);
65
- const environment = qpqCoreUtils.getApplicationModuleEnvironment(qpqConfig);
66
- const feature = qpqCoreUtils.getApplicationModuleFeature(qpqConfig);
67
- // Workout the bucket name.
68
- const bucketName = getConfigRuntimeResourceName('qpq-logs', application, service, environment, feature);
69
- // Where is this bucket?
70
- const regionForBucket = getAwsServiceAccountInfoByDeploymentInfo(qpqConfig, service, environment, feature, application).awsRegion;
71
- console.log('Bucket for logs: ', bucketName, regionForBucket);
72
- const logs = [];
73
- return {
74
- log: async (result) => {
75
- const promise = storyLogger(result, bucketName, regionForBucket).catch((e) => {
76
- console.log('Failed to log story result to S3', JSON.stringify(e, null, 2));
77
- });
78
- logs.push(promise);
79
- console.log('Added to logs', logs.length);
80
- },
81
- waitToFinishWriting: async () => {
82
- console.log('logs.length', logs.length);
83
- console.time('Writing Logs');
84
- await Promise.all(logs);
85
- console.timeEnd('Writing Logs');
86
- console.log('done writing logs');
87
- },
88
- moveToPermanentStorage: async () => {
89
- await moveLogsToPerminateStorage(bucketName, regionForBucket);
90
- },
91
- };
92
- };