Skip to content

Commit

Permalink
Project stats 4.22.4 (#3504)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwasniew committed Apr 12, 2023
1 parent ed47e56 commit 5208038
Show file tree
Hide file tree
Showing 14 changed files with 224 additions and 409 deletions.
2 changes: 2 additions & 0 deletions src/lib/__snapshots__/create-config.test.ts.snap
Expand Up @@ -89,6 +89,7 @@ exports[`should create default config 1`] = `
"projectScopedSegments": false,
"projectScopedStickiness": false,
"projectStatusApi": false,
"projectStatusApiImprovements": false,
"responseTimeWithAppNameKillSwitch": false,
"strictSchemaValidation": false,
},
Expand Down Expand Up @@ -117,6 +118,7 @@ exports[`should create default config 1`] = `
"projectScopedSegments": false,
"projectScopedStickiness": false,
"projectStatusApi": false,
"projectStatusApiImprovements": false,
"responseTimeWithAppNameKillSwitch": false,
"strictSchemaValidation": false,
},
Expand Down
10 changes: 5 additions & 5 deletions src/lib/db/feature-toggle-store.ts
Expand Up @@ -110,16 +110,16 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
return rows.map(this.rowToFeature);
}

async getByDate(queryModifiers: {
async countByDate(queryModifiers: {
archived?: boolean;
project?: string;
date?: string;
range?: string[];
dateAccessor: string;
}): Promise<FeatureToggle[]> {
}): Promise<number> {
const { project, archived, dateAccessor } = queryModifiers;
let query = this.db
.select(FEATURE_COLUMNS)
.count()
.from(TABLE)
.where({ project })
.modify(FeatureToggleStore.filterByArchived, archived);
Expand All @@ -135,8 +135,8 @@ export default class FeatureToggleStore implements IFeatureToggleStore {
]);
}

const rows = await query;
return rows.map(this.rowToFeature);
const queryResult = await query.first();
return parseInt(queryResult.count || 0);
}

/**
Expand Down
39 changes: 38 additions & 1 deletion src/lib/db/project-stats-store.ts
Expand Up @@ -4,7 +4,10 @@ import metricsHelper from '../util/metrics-helper';
import { DB_TIME } from '../metric-events';
import EventEmitter from 'events';
import { IProjectStats } from 'lib/services/project-service';
import { IProjectStatsStore } from 'lib/types/stores/project-stats-store-type';
import {
ICreateEnabledDates,
IProjectStatsStore,
} from 'lib/types/stores/project-stats-store-type';
import { Db } from './db';

const TABLE = 'project_stats';
Expand Down Expand Up @@ -107,6 +110,40 @@ class ProjectStatsStore implements IProjectStatsStore {
row.project_members_added_current_window,
};
}

// we're not calculating time difference in a DB as it requires specialized
// time aware libraries
async getTimeToProdDates(
projectId: string,
): Promise<ICreateEnabledDates[]> {
const result = await this.db
.select('events.feature_name')
// select only first enabled event, distinct works with orderBy
.distinctOn('events.feature_name')
.select(
this.db.raw(
'events.created_at as enabled, features.created_at as created',
),
)
.from('events')
.innerJoin(
'environments',
'environments.name',
'=',
'events.environment',
)
.innerJoin('features', 'features.name', '=', 'events.feature_name')
.where('events.type', '=', 'feature-environment-enabled')
.where('environments.type', '=', 'production')
.where('features.type', '=', 'release')
// exclude events for features that were previously deleted
.where(this.db.raw('events.created_at > features.created_at'))
.where('features.project', '=', projectId)
.orderBy('events.feature_name')
// first enabled event
.orderBy('events.created_at', 'asc');
return result;
}
}

export default ProjectStatsStore;
@@ -0,0 +1,26 @@
import { calculateAverageTimeToProd } from './time-to-production';

describe('calculate average time to production', () => {
test('should calculate average correctly', () => {
const timeToProduction = calculateAverageTimeToProd([
{
created: new Date('2022-12-05T09:37:32.483Z'),
enabled: new Date('2023-01-25T09:37:32.504Z'),
},
{
created: new Date('2023-01-19T09:37:32.484Z'),
enabled: new Date('2023-01-31T09:37:32.506Z'),
},
{
created: new Date('2023-01-19T09:37:32.484Z'),
enabled: new Date('2023-02-02T09:37:32.509Z'),
},
{
created: new Date('2023-01-19T09:37:32.486Z'),
enabled: new Date('2023-01-26T09:37:32.508Z'),
},
]);

expect(timeToProduction).toBe(21);
});
});
@@ -0,0 +1,20 @@
import { differenceInDays } from 'date-fns';
import { ICreateEnabledDates } from '../../../types/stores/project-stats-store-type';

const calculateTimeToProdForFeatures = (
items: ICreateEnabledDates[],
): number[] =>
items.map((item) => differenceInDays(item.enabled, item.created));

export const calculateAverageTimeToProd = (
items: ICreateEnabledDates[],
): number => {
const timeToProdPerFeature = calculateTimeToProdForFeatures(items);
if (timeToProdPerFeature.length) {
const sum = timeToProdPerFeature.reduce((acc, curr) => acc + curr, 0);

return Number((sum / Object.keys(items).length).toFixed(1));
}

return 0;
};
216 changes: 0 additions & 216 deletions src/lib/read-models/time-to-production/time-to-production.test.ts

This file was deleted.

0 comments on commit 5208038

Please sign in to comment.