Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hawk.api",
"version": "1.3.1",
"version": "1.3.2",
"main": "index.ts",
"license": "BUSL-1.1",
"scripts": {
Expand Down
43 changes: 34 additions & 9 deletions src/models/eventsFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const MAX_DB_READ_BATCH_SIZE = Number(process.env.MAX_DB_READ_BATCH_SIZE);
const ChartType = {
Accepted: 'accepted',
RateLimited: 'rate-limited',
AffectedUsers: 'affected-users',
};

/**
Expand Down Expand Up @@ -523,15 +524,35 @@ class EventsFactory extends Factory {
];
}

/**
* Get event daily chart data of affected users from MongoDB only
*
* @param {string} groupHash - event's group hash
* @param {number} days - how many days to fetch
* @param {number} timezoneOffset - user's local timezone offset in minutes
* @returns {Promise<Array>}
*/
async getEventDailyAffectedUsersChart(groupHash, days, timezoneOffset = 0) {
const data = await this.findChartData(days, timezoneOffset, groupHash, 'affectedUsers');

return [
{
label: ChartType.AffectedUsers,
data,
},
];
}

/**
* Fetch timestamps and total count of errors (or target error) for each day since
Comment thread
slaveeks marked this conversation as resolved.
Outdated
*
* @param {number} days - how many days we need to fetch for displaying in a chart
* @param {number} timezoneOffset - user's local timezone offset in minutes
* @param {string} groupHash - event's group hash for showing only target event
* @param {'count'|'affectedUsers'} valueField - field to aggregate
* @return {ProjectChartItem[]}
*/
async findChartData(days, timezoneOffset = 0, groupHash = '') {
async findChartData(days, timezoneOffset = 0, groupHash = '', valueField = 'count') {
const today = new Date();
const since = today.setDate(today.getDate() - days) / 1000;

Expand All @@ -554,13 +575,15 @@ class EventsFactory extends Factory {
};
}

const projection = {
lastRepetitionTime: 1,
groupingTimestamp: 1,
[valueField]: 1,
};

const dailyEventsCursor = await this.getCollection(this.TYPES.DAILY_EVENTS)
.find(options, {
projection: {
lastRepetitionTime: 1,
groupingTimestamp: 1,
count: 1,
},
projection,
})
.batchSize(MAX_DB_READ_BATCH_SIZE);

Expand All @@ -576,11 +599,13 @@ class EventsFactory extends Factory {
const key = `groupingTimestamp:${groupingTimestamp}`;
const current = groupedCounts[key] || 0;

if (item.count === undefined || item.count === null) {
console.warn(`Missing 'count' field for daily event with key ${key}. Defaulting to 0.`);
const value = item[valueField];

if (value === undefined || value === null) {
console.warn(`Missing '${valueField}' field for daily event with key ${key}. Defaulting to 0.`);
groupedCounts[key] = current;
} else {
groupedCounts[key] = current + item.count;
groupedCounts[key] = current + value;
}
}

Expand Down
15 changes: 15 additions & 0 deletions src/resolvers/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,21 @@ module.exports = {
return factory.getEventDailyChart(groupHash, days, timezoneOffset);
},

/**
* Return chart data for affected users of target event occured in last few days
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSDoc comment has a typo: "occured" should be "occurred".

Copilot uses AI. Check for mistakes.
*
* @param {string} projectId - event's project
* @param {string} groupHash - event's groupHash
* @param {number} days - how many days we need to fetch for displaying in a charts
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSDoc comment contains a grammatical error: "displaying in a charts" should be "displaying in a chart" (or "displaying in charts").

Copilot uses AI. Check for mistakes.
* @param {number} timezoneOffset - user's local timezone offset in minutes
* @returns {Promise<ProjectChartItem[]>}
*/
async affectedUsersChartData({ projectId, groupHash }, { days, timezoneOffset }, context) {
const factory = getEventsFactory(context, projectId);

return factory.getEventDailyAffectedUsersChart(groupHash, days, timezoneOffset);
},

/**
* Return AI suggestion for the event
*
Expand Down
5 changes: 5 additions & 0 deletions src/sso/saml/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export default class SamlController {
res.redirect(redirectUrl.toString());
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';

this.log(
'error',
'SSO initiation error for workspace:',
Expand Down Expand Up @@ -271,6 +272,7 @@ export default class SamlController {

if (!isValidRequest) {
const requestIdShort = samlData.inResponseTo.slice(0, 8);

this.log(
'error',
'[ACS] InResponseTo validation failed for workspace:',
Expand All @@ -285,6 +287,7 @@ export default class SamlController {
}
} catch (error) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error';

this.log(
'error',
'[ACS] SAML validation error for workspace:',
Expand Down Expand Up @@ -387,6 +390,7 @@ export default class SamlController {
*/
if (error instanceof Error && error.message.includes('SAML')) {
const errorMessage = error.message;

this.log(
'error',
'[ACS] SAML processing error for workspace:',
Expand All @@ -400,6 +404,7 @@ export default class SamlController {
}

const errorMessage = error instanceof Error ? error.message : 'Unknown error';

this.log(
'error',
'[ACS] ACS callback error for workspace:',
Expand Down
15 changes: 15 additions & 0 deletions src/typeDefs/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,21 @@ type Event {
"""
timezoneOffset: Int! = 0
): [ChartLine!]!

"""
Return graph of affected users dynamics for the specified period
"""
affectedUsersChartData(
"""
How many days we need to fetch for displaying in a chart
"""
days: Int! = 0

"""
User's local timezone offset in minutes
"""
timezoneOffset: Int! = 0
): [ChartLine!]!
}

"""
Expand Down
Loading