Add logging on currentWorkspaceMember query (#6706)

We are experiencing slow GetCurrentUser endpoint, this is helping us
troubleshoot
This commit is contained in:
Charles Bochet
2024-08-21 11:48:20 +02:00
committed by GitHub
parent 6caa78008f
commit 614a81860f
6 changed files with 55 additions and 12 deletions

View File

@ -1,7 +1,7 @@
import { TypeOrmModuleOptions } from '@nestjs/typeorm'; import { TypeOrmModuleOptions } from '@nestjs/typeorm';
import { DataSource, DataSourceOptions } from 'typeorm';
import { config } from 'dotenv'; import { config } from 'dotenv';
import { DataSource, DataSourceOptions } from 'typeorm';
config(); config();
export const typeORMCoreModuleOptions: TypeOrmModuleOptions = { export const typeORMCoreModuleOptions: TypeOrmModuleOptions = {

View File

@ -40,18 +40,24 @@ export class UserService extends TypeOrmQueryService<User> {
return null; return null;
} }
console.time('loadWorkspaceMember repo');
const workspaceMemberRepository = const workspaceMemberRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>( await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
user.defaultWorkspaceId, user.defaultWorkspaceId,
'workspaceMember', 'workspaceMember',
); );
console.timeEnd('loadWorkspaceMember repo');
console.time('loadWorkspaceMember find');
const workspaceMember = await workspaceMemberRepository.findOne({ const workspaceMember = await workspaceMemberRepository.findOne({
where: { where: {
userId: user.id, userId: user.id,
}, },
}); });
console.timeEnd('loadWorkspaceMember find');
return workspaceMember; return workspaceMember;
} }
@ -60,13 +66,22 @@ export class UserService extends TypeOrmQueryService<User> {
return []; return [];
} }
console.time('loadWorkspaceMembers repo');
const workspaceMemberRepository = const workspaceMemberRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>( await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
workspace.id, workspace.id,
'workspaceMember', 'workspaceMember',
); );
return workspaceMemberRepository.find(); console.timeEnd('loadWorkspaceMembers repo');
console.time('loadWorkspaceMembers find');
const workspaceMembers = workspaceMemberRepository.find();
console.timeEnd('loadWorkspaceMembers find');
return workspaceMembers;
} }
async deleteUser(userId: string): Promise<User> { async deleteUser(userId: string): Promise<User> {

View File

@ -98,6 +98,7 @@ export class UserResolver {
nullable: true, nullable: true,
}) })
async workspaceMember(@Parent() user: User): Promise<WorkspaceMember | null> { async workspaceMember(@Parent() user: User): Promise<WorkspaceMember | null> {
console.time('resolver workspaceMember');
const workspaceMember = await this.userService.loadWorkspaceMember(user); const workspaceMember = await this.userService.loadWorkspaceMember(user);
if (workspaceMember && workspaceMember.avatarUrl) { if (workspaceMember && workspaceMember.avatarUrl) {
@ -108,6 +109,7 @@ export class UserResolver {
workspaceMember.avatarUrl = `${workspaceMember.avatarUrl}?token=${avatarUrlToken}`; workspaceMember.avatarUrl = `${workspaceMember.avatarUrl}?token=${avatarUrlToken}`;
} }
console.timeEnd('resolver workspaceMember');
// TODO: Fix typing disrepency between Entity and DTO // TODO: Fix typing disrepency between Entity and DTO
return workspaceMember as WorkspaceMember | null; return workspaceMember as WorkspaceMember | null;
@ -117,6 +119,7 @@ export class UserResolver {
nullable: true, nullable: true,
}) })
async workspaceMembers(@Parent() user: User): Promise<WorkspaceMember[]> { async workspaceMembers(@Parent() user: User): Promise<WorkspaceMember[]> {
console.time('resolver workspaceMembers');
const workspaceMembers = await this.userService.loadWorkspaceMembers( const workspaceMembers = await this.userService.loadWorkspaceMembers(
user.defaultWorkspace, user.defaultWorkspace,
); );
@ -132,6 +135,8 @@ export class UserResolver {
} }
} }
console.timeEnd('resolver workspaceMembers');
// TODO: Fix typing disrepency between Entity and DTO // TODO: Fix typing disrepency between Entity and DTO
return workspaceMembers as WorkspaceMember[]; return workspaceMembers as WorkspaceMember[];
} }

View File

@ -26,6 +26,7 @@ export class WorkspaceEntityManager extends EntityManager {
target: EntityTarget<Entity>, target: EntityTarget<Entity>,
): WorkspaceRepository<Entity> { ): WorkspaceRepository<Entity> {
// find already created repository instance and return it if found // find already created repository instance and return it if found
const repoFromMap = this.repositories.get(target); const repoFromMap = this.repositories.get(target);
if (repoFromMap) { if (repoFromMap) {

View File

@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { EntitySchema, Repository } from 'typeorm'; import { EntitySchema, Repository } from 'typeorm';
import { v4 } from 'uuid';
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service'; import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
@ -28,11 +29,19 @@ export class WorkspaceDatasourceFactory {
workspaceId: string, workspaceId: string,
workspaceMetadataVersion: string | null, workspaceMetadataVersion: string | null,
): Promise<WorkspaceDataSource> { ): Promise<WorkspaceDataSource> {
const desiredWorkspaceMetadataVersion = const logId = v4();
workspaceMetadataVersion ??
(await this.workspaceMetadataVersionService.getMetadataVersion( console.time(`fetch in datasource factory ${logId}`);
const latestWorkspaceMetadataVersion =
await this.workspaceMetadataVersionService.getMetadataVersion(
workspaceId, workspaceId,
)); );
console.timeEnd(`fetch in datasource factory ${logId}`);
const desiredWorkspaceMetadataVersion =
workspaceMetadataVersion ?? latestWorkspaceMetadataVersion;
if (!desiredWorkspaceMetadataVersion) { if (!desiredWorkspaceMetadataVersion) {
throw new Error( throw new Error(
@ -40,11 +49,6 @@ export class WorkspaceDatasourceFactory {
); );
} }
const latestWorkspaceMetadataVersion =
await this.workspaceMetadataVersionService.getMetadataVersion(
workspaceId,
);
if (latestWorkspaceMetadataVersion !== desiredWorkspaceMetadataVersion) { if (latestWorkspaceMetadataVersion !== desiredWorkspaceMetadataVersion) {
throw new Error( throw new Error(
`Workspace metadata version mismatch detected for workspace ${workspaceId}. Current version: ${latestWorkspaceMetadataVersion}. Desired version: ${desiredWorkspaceMetadataVersion}`, `Workspace metadata version mismatch detected for workspace ${workspaceId}. Current version: ${latestWorkspaceMetadataVersion}. Desired version: ${desiredWorkspaceMetadataVersion}`,
@ -80,6 +84,9 @@ export class WorkspaceDatasourceFactory {
const workspaceDataSource = await workspaceDataSourceCacheInstance.execute( const workspaceDataSource = await workspaceDataSourceCacheInstance.execute(
`${workspaceId}-${latestWorkspaceMetadataVersion}`, `${workspaceId}-${latestWorkspaceMetadataVersion}`,
async () => { async () => {
const logId = v4();
console.log('Creating workspace fresh data source...' + logId);
const dataSourceMetadata = const dataSourceMetadata =
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId( await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId(
workspaceId, workspaceId,
@ -97,6 +104,7 @@ export class WorkspaceDatasourceFactory {
); );
} }
console.time('create entity schema' + logId);
const cachedEntitySchemaOptions = const cachedEntitySchemaOptions =
await this.workspaceCacheStorageService.getORMEntitySchema( await this.workspaceCacheStorageService.getORMEntitySchema(
workspaceId, workspaceId,
@ -122,7 +130,9 @@ export class WorkspaceDatasourceFactory {
cachedEntitySchemas = entitySchemas; cachedEntitySchemas = entitySchemas;
} }
console.timeEnd('create entity schema' + logId);
console.time('create workspace data source' + logId);
const workspaceDataSource = new WorkspaceDataSource( const workspaceDataSource = new WorkspaceDataSource(
{ {
workspaceId, workspaceId,
@ -146,7 +156,11 @@ export class WorkspaceDatasourceFactory {
}, },
); );
console.timeEnd('create workspace data source' + logId);
console.time('initialize workspace data source' + logId);
await workspaceDataSource.initialize(); await workspaceDataSource.initialize();
console.timeEnd('initialize workspace data source' + logId);
return workspaceDataSource; return workspaceDataSource;
}, },

View File

@ -1,6 +1,7 @@
import { Injectable, Type } from '@nestjs/common'; import { Injectable, Type } from '@nestjs/common';
import { ObjectLiteral } from 'typeorm'; import { ObjectLiteral } from 'typeorm';
import { v4 } from 'uuid';
import { WorkspaceDatasourceFactory } from 'src/engine/twenty-orm/factories/workspace-datasource.factory'; import { WorkspaceDatasourceFactory } from 'src/engine/twenty-orm/factories/workspace-datasource.factory';
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository'; import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
@ -36,12 +37,19 @@ export class TwentyORMGlobalManager {
); );
} }
const logId = v4();
console.time(`createDataSource in orm ${logId}`);
const workspaceDataSource = await this.workspaceDataSourceFactory.create( const workspaceDataSource = await this.workspaceDataSourceFactory.create(
workspaceId, workspaceId,
null, null,
); );
return workspaceDataSource.getRepository<T>(objectMetadataName); console.timeEnd(`createDataSource in orm ${logId}`);
const repository = workspaceDataSource.getRepository<T>(objectMetadataName);
return repository;
} }
async getDataSourceForWorkspace(workspaceId: string) { async getDataSourceForWorkspace(workspaceId: string) {