Skip to content

Commit 24626be

Browse files
authored
Merge pull request #4285 from airqo-platform/hf-api-user-logs
Enhancing the logging for API usage for Analytics
2 parents 0241f44 + e0bbc81 commit 24626be

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

src/auth-service/config/log4js.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const constants = require("./constants");
1010
const log4js = {
1111
appenders: {
1212
console: { type: "console" },
13+
out: { type: "stdout" }, // Log to standard output (essential for Cloud Run/Functions)
1314
access: {
1415
type: "dateFile",
1516
filename: "log/access.log",
@@ -39,9 +40,10 @@ const log4js = {
3940
},
4041
},
4142
categories: {
42-
default: { appenders: ["alerts"], level: "info" },
43+
default: { appenders: ["alerts", "out"], level: "info" },
4344
error: { appenders: ["alerts", "errors"], level: "error" },
4445
http: { appenders: ["access"], level: "DEBUG" },
46+
"api-usage-logger": { appenders: ["out"], level: "info" }, // API Usage logs *only* to stdout, not to slack!
4547
},
4648
};
4749

src/auth-service/utils/token.util.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const moment = require("moment-timezone");
2525
const ObjectId = mongoose.Types.ObjectId;
2626
const log4js = require("log4js");
2727
const logger = log4js.getLogger(`${constants.ENVIRONMENT} -- token-util`);
28+
const apiUsageLogger = log4js.getLogger("api-usage-logger");
2829
const async = require("async");
2930
const { Kafka } = require("kafkajs");
3031
const kafka = new Kafka({
@@ -415,6 +416,56 @@ const isIPBlacklistedHelper = async (
415416
const isIPBlacklisted = (...args) =>
416417
trampoline(() => isIPBlacklistedHelper(...args));
417418

419+
//Create async queue for handling API Usage logs
420+
const apiUsageQueue = async.queue(async (task, callback) => {
421+
try {
422+
const {
423+
timestamp,
424+
token,
425+
client_id,
426+
endpoint,
427+
ip_address,
428+
user_agent,
429+
response_code,
430+
latency,
431+
} = task;
432+
433+
const logPayload = {
434+
timestamp,
435+
token,
436+
client_id,
437+
endpoint,
438+
ip_address,
439+
user_agent,
440+
response_code,
441+
latency,
442+
};
443+
444+
logger.info(JSON.stringify(logPayload)); // Log the structured data
445+
callback();
446+
} catch (error) {
447+
logger.error(
448+
`🐛🐛 API Usage Queue Internal Server Error --- ${error.message}`
449+
);
450+
}
451+
}, 1); // Adjust concurrency as needed
452+
453+
const logAPIUsage = async (logData) => {
454+
try {
455+
// Asynchronous Logging using a queue (recommended)
456+
apiUsageQueue.push(logData);
457+
} catch (error) {
458+
// Handle logging errors gracefully
459+
logger.error(`Error logging API usage: ${error.message}`); // Ensure 'logger' is defined
460+
}
461+
};
462+
463+
const calculateLatency = (startTime, endTime = process.hrtime.bigint()) => {
464+
const nanoseconds = Number(endTime - startTime);
465+
const milliseconds = nanoseconds / 1000000;
466+
return milliseconds;
467+
};
468+
418469
const token = {
419470
verifyEmail: async (request, next) => {
420471
try {
@@ -672,6 +723,7 @@ const token = {
672723
verifyToken: async (request, next) => {
673724
try {
674725
logText("I have just entered the verifyToken() function");
726+
const startTime = process.hrtime.bigint(); // Start measuring latency
675727
const ip =
676728
request.headers["x-client-ip"] ||
677729
request.headers["x-client-original-ip"];
@@ -715,6 +767,30 @@ const token = {
715767
clientOriginalIp: ip,
716768
endpoint: endpoint ? endpoint : "unknown",
717769
});
770+
771+
const endTime = process.hrtime.bigint();
772+
const latency = calculateLatency(startTime, endTime);
773+
774+
await AccessTokenModel("airqo").updateOne(
775+
{ token },
776+
{ $set: { last_used_at: new Date(), last_ip_address: ip } }
777+
);
778+
const logPayload = {
779+
timestamp: new Date().toISOString(),
780+
token: accessToken.token,
781+
client_id: accessToken.client_id,
782+
endpoint,
783+
ip_address: ip,
784+
user_agent: request.headers["user-agent"],
785+
response_code: 200,
786+
latency: latency,
787+
};
788+
789+
if (constants.ENVIRONMENT === "PRODUCTION ENVIRONMENT") {
790+
}
791+
await logAPIUsage(logPayload);
792+
apiUsageLogger.info(stringify(logPayload)); // Log to stdout (for BigQuery)
793+
718794
return createValidTokenResponse();
719795
}
720796
}

0 commit comments

Comments
 (0)