feature/IO-3029-Enhanced-Logging-File-Based: Final Enhancements

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-11-14 08:34:21 -08:00
parent 763384f05f
commit 2439755f9e
6 changed files with 33 additions and 31 deletions

View File

@@ -21,7 +21,7 @@ const { applyRedisHelpers } = require("./server/utils/redisHelpers");
const { applyIOHelpers } = require("./server/utils/ioHelpers"); const { applyIOHelpers } = require("./server/utils/ioHelpers");
const { redisSocketEvents } = require("./server/web-sockets/redisSocketEvents"); const { redisSocketEvents } = require("./server/web-sockets/redisSocketEvents");
const { ElastiCacheClient, DescribeCacheClustersCommand } = require("@aws-sdk/client-elasticache"); const { ElastiCacheClient, DescribeCacheClustersCommand } = require("@aws-sdk/client-elasticache");
const { default: InstanceManager } = require("./server/utils/instanceMgr"); const { InstanceRegion } = require("./server/utils/instanceMgr");
const CLUSTER_RETRY_BASE_DELAY = 100; const CLUSTER_RETRY_BASE_DELAY = 100;
const CLUSTER_RETRY_MAX_DELAY = 5000; const CLUSTER_RETRY_MAX_DELAY = 5000;
@@ -114,10 +114,7 @@ const applyRoutes = ({ app }) => {
*/ */
const getRedisNodesFromAWS = async () => { const getRedisNodesFromAWS = async () => {
const client = new ElastiCacheClient({ const client = new ElastiCacheClient({
region: InstanceManager({ region: InstanceRegion()
imex: "ca-central-1",
rome: "us-east-2"
})
}); });
const params = { const params = {

View File

@@ -1,6 +1,6 @@
const { isString, isEmpty } = require("lodash"); const { isString, isEmpty } = require("lodash");
const { defaultProvider } = require("@aws-sdk/credential-provider-node"); const { defaultProvider } = require("@aws-sdk/credential-provider-node");
const { default: InstanceManager } = require("../utils/instanceMgr"); const { InstanceRegion } = require("../utils/instanceMgr");
const aws = require("@aws-sdk/client-ses"); const aws = require("@aws-sdk/client-ses");
const nodemailer = require("nodemailer"); const nodemailer = require("nodemailer");
const logger = require("../utils/logger"); const logger = require("../utils/logger");
@@ -10,12 +10,7 @@ const isLocal = isString(process.env?.LOCALSTACK_HOSTNAME) && !isEmpty(process.e
const sesConfig = { const sesConfig = {
apiVersion: "latest", apiVersion: "latest",
credentials: defaultProvider(), credentials: defaultProvider(),
region: isLocal region: InstanceRegion()
? "ca-central-1"
: InstanceManager({
imex: "ca-central-1",
rome: "us-east-2"
})
}; };
if (isLocal) { if (isLocal) {

View File

@@ -17,12 +17,10 @@ require("dotenv").config({
const domain = process.env.NODE_ENV ? "secure" : "test"; const domain = process.env.NODE_ENV ? "secure" : "test";
const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager"); const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager");
const { InstanceRegion } = require("../utils/instanceMgr");
const client = new SecretsManagerClient({ const client = new SecretsManagerClient({
region: InstanceManager({ region: InstanceRegion()
imex: "ca-central-1",
rome: "us-east-2"
})
}); });
const gqlClient = require("../graphql-client/graphql-client").client; const gqlClient = require("../graphql-client/graphql-client").client;

View File

@@ -44,4 +44,10 @@ function InstanceManager({ args, instance, debug, executeFunction, rome, promana
return propToReturn === undefined ? null : propToReturn; return propToReturn === undefined ? null : propToReturn;
} }
exports.InstanceRegion = () =>
InstanceManager({
imex: "ca-central-1",
rome: "us-east-2"
});
exports.default = InstanceManager; exports.default = InstanceManager;

View File

@@ -11,6 +11,7 @@ const { isString, isEmpty } = require("lodash");
const { networkInterfaces, hostname } = require("node:os"); const { networkInterfaces, hostname } = require("node:os");
const { uploadFileToS3 } = require("./s3"); const { uploadFileToS3 } = require("./s3");
const { v4 } = require("uuid"); const { v4 } = require("uuid");
const { InstanceRegion } = require("./instanceMgr");
const LOG_LEVELS = { const LOG_LEVELS = {
error: { level: 0, name: "error" }, error: { level: 0, name: "error" },
@@ -29,12 +30,18 @@ const S3_BUCKET_NAME = InstanceManager({
rome: "rome-large-log" rome: "rome-large-log"
}); });
const region = InstanceRegion();
const estimateLogSize = (logEntry) => { const estimateLogSize = (logEntry) => {
let estimatedSize = 0; let estimatedSize = 0;
for (const key in logEntry) { for (const key in logEntry) {
if (logEntry.hasOwnProperty(key)) { if (logEntry.hasOwnProperty(key)) {
const value = logEntry[key]; const value = logEntry[key];
estimatedSize += key.length + (typeof value === "string" ? value.length : JSON.stringify(value).length); if (value === undefined || value === null) {
estimatedSize += key.length; // Only count the key length if value is undefined or null
} else {
estimatedSize += key.length + (typeof value === "string" ? value.length : JSON.stringify(value).length);
}
} }
} }
return estimatedSize; return estimatedSize;
@@ -50,10 +57,7 @@ const createLogger = () => {
const winstonCloudwatchTransportDefaults = { const winstonCloudwatchTransportDefaults = {
logGroupName: logGroupName, logGroupName: logGroupName,
awsOptions: { awsOptions: {
region: InstanceManager({ region
imex: "ca-central-1",
rome: "us-east-2"
})
}, },
jsonMessage: true jsonMessage: true
}; };
@@ -154,17 +158,23 @@ const createLogger = () => {
meta meta
}; };
//https://${S3_BUCKET_NAME}.s3.${region}.amazonaws.com/%5Btest%5D-%5Bip-172-31-42-218%5D-%5B2024-11-14T04-15-52.708Z%5D-%5B7a03efb9-9547-4f6b-acd4-c63a2d58a0c8%5D.json
const uploadLogToS3 = (logEntry, message, type, user) => { const uploadLogToS3 = (logEntry, message, type, user) => {
const uniqueId = v4(); const uniqueId = v4();
const dateTimeString = new Date().toISOString().replace(/:/g, "-"); const dateTimeString = new Date().toISOString().replace(/:/g, "-");
const envName = process.env?.NODE_ENV ? process.env.NODE_ENV : ""; const envName = process.env?.NODE_ENV ? process.env.NODE_ENV : "";
const logStreamName = `[${envName}]-[${internalHostname}]-[${dateTimeString}]-[${uniqueId}].json`; const logStreamName = `${envName}-${internalHostname}-${dateTimeString}-${uniqueId}.json`;
const logString = JSON.stringify(logEntry); const logString = JSON.stringify(logEntry);
const webPath = isLocal
? `https://${S3_BUCKET_NAME}.s3.localhost.localstack.cloud:4566/${logStreamName}`
: `https://${S3_BUCKET_NAME}.s3.${region}.amazonaws.com/${logStreamName}`;
uploadFileToS3({ bucketName: S3_BUCKET_NAME, key: logStreamName, content: logString }) uploadFileToS3({ bucketName: S3_BUCKET_NAME, key: logStreamName, content: logString })
.then(() => { .then(() => {
log("A log file has been uploaded to S3", "info", "S3", null, { log("A log file has been uploaded to S3", "info", "S3", null, {
logStreamName, logStreamName,
webPath,
message: message?.slice(0, 200), message: message?.slice(0, 200),
type, type,
user user
@@ -173,6 +183,7 @@ const createLogger = () => {
.catch((err) => { .catch((err) => {
log("Error in S3 Upload", "error", "S3", null, { log("Error in S3 Upload", "error", "S3", null, {
logStreamName, logStreamName,
webPath,
message: message?.slice(0, 100), message: message?.slice(0, 100),
type, type,
user, user,
@@ -182,16 +193,14 @@ const createLogger = () => {
}; };
const checkAndUploadLog = () => { const checkAndUploadLog = () => {
const logString = JSON.stringify(logEntry); const estimatedSize = estimateLogSize(logEntry);
const logSize = Buffer.byteLength(logString, "utf8");
if (logSize > LOG_LENGTH_LIMIT * 0.9 || logSize > LOG_LENGTH_LIMIT) { if (estimatedSize > LOG_LENGTH_LIMIT * 0.9 || estimatedSize > LOG_LENGTH_LIMIT) {
uploadLogToS3(logEntry, message, type, user); uploadLogToS3(logEntry, message, type, user);
return true; return true;
} }
return false; return false;
}; };
// Upload log immediately if upload is true, otherwise check the log size. // Upload log immediately if upload is true, otherwise check the log size.
if (upload) { if (upload) {
uploadLogToS3(logEntry, message, type, user); uploadLogToS3(logEntry, message, type, user);

View File

@@ -7,15 +7,12 @@ const {
CopyObjectCommand CopyObjectCommand
} = require("@aws-sdk/client-s3"); } = require("@aws-sdk/client-s3");
const { defaultProvider } = require("@aws-sdk/credential-provider-node"); const { defaultProvider } = require("@aws-sdk/credential-provider-node");
const { default: InstanceManager } = require("./instanceMgr"); const { InstanceRegion } = require("./instanceMgr");
const { isString, isEmpty } = require("lodash"); const { isString, isEmpty } = require("lodash");
const createS3Client = () => { const createS3Client = () => {
const S3Options = { const S3Options = {
region: InstanceManager({ region: InstanceRegion(),
imex: "ca-central-1",
rome: "us-east-2"
}),
credentials: defaultProvider() credentials: defaultProvider()
}; };