diff --git a/package-lock.json b/package-lock.json index 99d0086c..218e902f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,14 +10,14 @@ "license": "ISC", "dependencies": { "@breejs/ts-worker": "^2.0.0", - "axios": "^1.7.5", + "axios": "^1.7.8", "bcrypt": "^5.1.1", "body-parser": "^1.20.3", "boom": "^7.2.0", "bree": "^9.2.4", "compression": "^1.7.4", "dotenv": "^16.4.5", - "express": "^4.21.0", + "express": "^4.21.2", "express-winston": "^4.2.0", "fast-csv": "^4.3.6", "helmet": "^6.2.0", @@ -3312,9 +3312,9 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "node_modules/axios": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", - "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz", + "integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -4021,9 +4021,10 @@ "dev": true }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -4809,9 +4810,9 @@ } }, "node_modules/express": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", - "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", @@ -4819,7 +4820,7 @@ "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -4833,7 +4834,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -4848,6 +4849,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express-winston": { @@ -9541,9 +9546,9 @@ "dev": true }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, "node_modules/path-type": { diff --git a/package.json b/package.json index d6d2982f..0336a07e 100644 --- a/package.json +++ b/package.json @@ -19,14 +19,14 @@ "license": "ISC", "dependencies": { "@breejs/ts-worker": "^2.0.0", - "axios": "^1.7.5", + "axios": "^1.7.8", "bcrypt": "^5.1.1", "body-parser": "^1.20.3", "boom": "^7.2.0", "bree": "^9.2.4", "compression": "^1.7.4", "dotenv": "^16.4.5", - "express": "^4.21.0", + "express": "^4.21.2", "express-winston": "^4.2.0", "fast-csv": "^4.3.6", "helmet": "^6.2.0", diff --git a/src/logger.ts b/src/logger.ts index d30d28d1..45026cb2 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -1,6 +1,32 @@ import * as winston from "winston" +const LOG_LEVELS = winston.config.syslog.levels +const DEFAULT_LOG_LEVEL = "debug" + +const getLogLevel = (): string => { + const logLevelEnvVar = process.env.LOG_LEVEL + if (logLevelEnvVar) { + const isAllowedLogLevel = Object.keys(LOG_LEVELS) + .find(level => logLevelEnvVar.toLowerCase() === level.toLowerCase()) + if (!isAllowedLogLevel) { + console.log("Unsupported log level: ", logLevelEnvVar) + } else { + return isAllowedLogLevel + } + } + return DEFAULT_LOG_LEVEL + + +} + export const logger = winston.createLogger({ - levels: winston.config.syslog.levels, - transports: [ new winston.transports.Console() ], + format: winston.format.combine( + winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), + winston.format.json() + ), + level: getLogLevel(), + levels: LOG_LEVELS, + transports: [new winston.transports.Console()], }) + + diff --git a/src/server/controllers/item/shared/item-data-processing.ts b/src/server/controllers/item/shared/item-data-processing.ts index c00412e2..14be2f28 100644 --- a/src/server/controllers/item/shared/item-data-processing.ts +++ b/src/server/controllers/item/shared/item-data-processing.ts @@ -46,29 +46,40 @@ export const itemDataProcessing = async ({ projectName, scenarioName, itemId }) let rawDataArray = null try { + logger.debug("Loading overview aggregation") const aggOverview = await db.one(aggOverviewQuery(itemId)) + logger.debug("Loading label aggregation") const aggLabel = await db.many(aggLabelQuery(itemId)) + logger.debug("Loading status code distribution") const statusCodeDistribution = await db.manyOrNone(responseCodeDistribution(itemId)) + logger.debug("Loading response time per label distribution") const responseTimePerLabelDistribution = await db.manyOrNone(responseTimePerLabelHistogram(itemId)) + logger.debug("Loading response failures") const responseFailures = await db.manyOrNone(responseMessageFailures(itemId)) + logger.debug("Loading scenario settings") const scenarioSettings = await db.one(getScenarioSettings(projectName, scenarioName)) - + logger.debug("Loading raw downsampled data") let rawDownsampledData = await db.manyOrNone(getDownsampledRawData(itemId, MAX_SCATTER_CHART_POINTS)) rawDataArray = rawDownsampledData?.map(row => [row.timestamp, row.value]) rawDownsampledData = null + logger.debug("Loading grouped errors") const groupedErrors = await db.manyOrNone(findGroupedErrors(itemId)) + logger.debug("Loading top 5 errors by label") const top5ErrorsByLabel = await db.manyOrNone(findTop5ErrorsByLabel(itemId)) if (aggOverview.number_of_sut_hostnames > 1) { + logger.debug("Loading SUT overview") sutMetrics = await db.many(sutOverviewQuery(itemId)) } if (scenarioSettings.apdexSettings.enabled) { const { satisfyingThreshold, toleratingThreshold } = scenarioSettings.apdexSettings + logger.debug("Calculating apdex") apdex = await db.many(calculateApdexValues(itemId, satisfyingThreshold, toleratingThreshold)) + logger.debug("Updating apdex settings") await db.none(updateItemApdexSettings(itemId, { satisfyingThreshold, toleratingThreshold, @@ -92,13 +103,18 @@ export const itemDataProcessing = async ({ projectName, scenarioName, itemId }) // distributed mode if (aggOverview?.number_of_hostnames > 1) { + logger.debug("Loading distributed threads") distributedThreads = await db.manyOrNone(distributedThreadsQuery(interval, itemId)) } + logger.debug("Loading label chart") const labelChart = await db.many(charLabelQuery(interval, itemId)) + logger.debug("Loading overview chart") const overviewChart = await db.many(chartOverviewQuery(interval, itemId)) + logger.debug("Loading status code chart") const statusCodeChart = await db.many(chartOverviewStatusCodesQuery(interval, itemId)) + logger.debug("Loading threads per group") const threadsPerGroup = await db.manyOrNone(threadsPerThreadGroup(interval, itemId)) if (parseInt(index, 10) === 0) { // default interval chartData = prepareChartDataForSaving( diff --git a/src/server/middleware/authorization-middleware.ts b/src/server/middleware/authorization-middleware.ts index 802a7584..de459517 100644 --- a/src/server/middleware/authorization-middleware.ts +++ b/src/server/middleware/authorization-middleware.ts @@ -6,14 +6,14 @@ import { isUserAuthorizedForProject } from "../queries/user-project-access" export const authorizationMiddleware = (allowedRoles: AllowedRoles[]) => { return async (request, response, next) => { const user = request.user - logger.info(`User ${user.userId} with role ${user.role} accessing a resource with allowed roles: ${allowedRoles}`) + logger.debug(`User ${user.userId} with role ${user.role} accessing a resource with allowed roles: ${allowedRoles}`) // check project authorization const { projectName } = request.params if (projectName && user?.userId && user?.role !== AllowedRoles.Admin) { - logger.info(`User ${user.userId} with role ${user.role} accessing a resource within ${projectName} project`) + logger.debug(`User ${user.userId} with role ${user.role} accessing a resource within ${projectName} project`) const userAuthorizedForProject = await db.oneOrNone(isUserAuthorizedForProject(projectName, user.userId)) if (!userAuthorizedForProject && user.role) { - logger.info(`User ${user.userId} has no access to project ${projectName}`) + logger.debug(`User ${user.userId} has no access to project ${projectName}`) return next(boom.forbidden(`You dont have permission to access`)) } // user is authorized, we can proceed