Skip to content

Commit ddb466a

Browse files
authored
Merge pull request #301 from codex-team/domain-logs
feat: add logs to domain services
2 parents 7aa34e4 + 1679632 commit ddb466a

13 files changed

Lines changed: 313 additions & 27 deletions

File tree

app-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ logging:
3030
s3Storage: info
3131
middlewares: info
3232
policies: info
33+
domain: info
3334

3435
s3:
3536
accessKeyId: 'secret'

src/domain/index.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import AIService from './service/ai.js';
88
import EditorToolsService from '@domain/service/editorTools.js';
99
import FileUploaderService from './service/fileUploader.service.js';
1010
import NoteVisitsService from './service/noteVisits.js';
11+
import { PinoDomainLoggerAdapter } from '@infrastructure/logging/pinoDomainLoggerAdapter.js';
1112

1213
/**
1314
* Interface for initiated services
@@ -60,19 +61,23 @@ export interface DomainServices {
6061
* @param appConfig - app config
6162
*/
6263
export function init(repositories: Repositories, appConfig: AppConfig): DomainServices {
64+
/** Create a shared logger instance for all domain services */
65+
const domainLogger = new PinoDomainLoggerAdapter();
66+
6367
/**
6468
* @todo use shared methods for uncoupling repositories unrelated to note service
6569
*/
66-
const noteService = new NoteService(repositories.noteRepository, repositories.noteRelationsRepository, repositories.noteVisitsRepository, repositories.editorToolsRepository, repositories.noteHistoryRepository);
67-
const noteVisitsService = new NoteVisitsService(repositories.noteVisitsRepository);
70+
const noteService = new NoteService(repositories.noteRepository, repositories.noteRelationsRepository, repositories.noteVisitsRepository, repositories.editorToolsRepository, repositories.noteHistoryRepository, domainLogger);
71+
const noteVisitsService = new NoteVisitsService(repositories.noteVisitsRepository, domainLogger);
6872
const authService = new AuthService(
6973
appConfig.auth.accessSecret,
7074
appConfig.auth.accessExpiresIn,
7175
appConfig.auth.refreshExpiresIn,
72-
repositories.userSessionRepository
76+
repositories.userSessionRepository,
77+
domainLogger
7378
);
74-
const editorToolsService = new EditorToolsService(repositories.editorToolsRepository);
75-
const fileUploaderService = new FileUploaderService(repositories.objectStorageRepository, repositories.fileRepository);
79+
const editorToolsService = new EditorToolsService(repositories.editorToolsRepository, domainLogger);
80+
const fileUploaderService = new FileUploaderService(repositories.objectStorageRepository, repositories.fileRepository, domainLogger);
7681

7782
const sharedServices = {
7883
editorTools: editorToolsService,
@@ -83,8 +88,8 @@ export function init(repositories: Repositories, appConfig: AppConfig): DomainSe
8388
*/
8489
};
8590

86-
const userService = new UserService(repositories.userRepository, sharedServices);
87-
const noteSettingsService = new NoteSettingsService(repositories.noteSettingsRepository, repositories.teamRepository, sharedServices);
91+
const userService = new UserService(repositories.userRepository, sharedServices, domainLogger);
92+
const noteSettingsService = new NoteSettingsService(repositories.noteSettingsRepository, repositories.teamRepository, sharedServices, domainLogger);
8893
const aiService = new AIService(repositories.aiRepository);
8994

9095
return {

src/domain/service/auth.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type AuthPayload from '@domain/entities/authPayload.js';
33
import { nanoid } from 'nanoid';
44
import type UserSessionRepository from '@repository/userSession.repository.js';
55
import type UserSession from '@domain/entities/userSession.js';
6+
import type { DomainLogger } from '@infrastructure/logging/domainLoggerInterface.js';
67

78
/**
89
* Auth service
@@ -28,18 +29,30 @@ export default class AuthService {
2829
*/
2930
private readonly userSessionRepository: UserSessionRepository;
3031

32+
/**
33+
* Logger instance
34+
*/
35+
private readonly logger: DomainLogger;
36+
37+
/**
38+
* Number of last characters to log from the refresh token
39+
*/
40+
private readonly logTokenLength: number = 4;
41+
3142
/**
3243
* Creates jwt service instance
3344
* @param accessSecret - access token secret key
3445
* @param accessTokenExpiresIn - access token expiration time
3546
* @param refreshTokenExpiresIn - refresh token expiration time
3647
* @param userSessionRepository - user session repository instance
48+
* @param logger - domain logger
3749
*/
38-
constructor(accessSecret: string, accessTokenExpiresIn: number, refreshTokenExpiresIn: number, userSessionRepository: UserSessionRepository) {
50+
constructor(accessSecret: string, accessTokenExpiresIn: number, refreshTokenExpiresIn: number, userSessionRepository: UserSessionRepository, logger: DomainLogger) {
3951
this.accessSecret = accessSecret;
4052
this.accessExpiresIn = accessTokenExpiresIn;
4153
this.refreshExpiresIn = refreshTokenExpiresIn;
4254
this.userSessionRepository = userSessionRepository;
55+
this.logger = logger;
4356
}
4457

4558
/**
@@ -77,6 +90,10 @@ export default class AuthService {
7790

7891
const userSession = await this.userSessionRepository.addUserSession(userId, token, new Date(Date.now() + this.refreshExpiresIn));
7992

93+
this.logger.debug('Refresh token issued', {
94+
userId,
95+
});
96+
8097
return userSession.refreshToken;
8198
}
8299

@@ -101,6 +118,10 @@ export default class AuthService {
101118
if (session.refreshTokenExpiresAt.getTime() < Date.now()) {
102119
await this.userSessionRepository.removeUserSessionByRefreshToken(token);
103120

121+
this.logger.warn('Refresh token expired', {
122+
token: session.refreshToken.slice(-this.logTokenLength),
123+
});
124+
104125
return null;
105126
}
106127

@@ -113,5 +134,7 @@ export default class AuthService {
113134
*/
114135
public async removeSessionByRefreshToken(token: string): Promise<void> {
115136
await this.userSessionRepository.removeUserSessionByRefreshToken(token);
137+
138+
this.logger.debug('Session revoked');
116139
}
117140
}

src/domain/service/editorTools.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type EditorTool from '@domain/entities/editorTools.js';
33
import type EditorToolsServiceSharedMethods from './shared/editorTools.js';
44
import type User from '@domain/entities/user.js';
55
import type { EditorToolCreationAttributes } from '@domain/entities/editorTools.js';
6+
import type { DomainLogger } from '@infrastructure/logging/domainLoggerInterface.js';
67

78
/**
89
* Editor tools service
@@ -13,12 +14,19 @@ export default class EditorToolsService implements EditorToolsServiceSharedMetho
1314
*/
1415
private readonly repository: EditorToolsRepository;
1516

17+
/**
18+
* Logger instance
19+
*/
20+
private readonly logger: DomainLogger;
21+
1622
/**
1723
* Editor tools service constructor
1824
* @param repository - user repository instance
25+
* @param logger - domain logger
1926
*/
20-
constructor(repository: EditorToolsRepository) {
27+
constructor(repository: EditorToolsRepository, logger: DomainLogger) {
2128
this.repository = repository;
29+
this.logger = logger;
2230
}
2331

2432
/**
@@ -58,9 +66,16 @@ export default class EditorToolsService implements EditorToolsServiceSharedMetho
5866
* @returns editor tool data
5967
*/
6068
public async addTool(editorTool: Omit<EditorToolCreationAttributes, 'userId'>, userId: User['id']): Promise<EditorTool> {
61-
return await this.repository.addTool({
69+
const createdTool = await this.repository.addTool({
6270
userId,
6371
...editorTool,
6472
});
73+
74+
this.logger.info('Editor tool created', {
75+
toolId: createdTool.id,
76+
userId,
77+
});
78+
79+
return createdTool;
6580
}
6681
}

src/domain/service/fileUploader.service.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type ObjectRepository from '@repository/object.repository.js';
77
import { DomainError } from '@domain/entities/DomainError.js';
88
import mime from 'mime';
99
import { isEmpty } from '@infrastructure/utils/empty.js';
10+
import type { DomainLogger } from '@infrastructure/logging/domainLoggerInterface.js';
1011

1112
/**
1213
* File data for upload
@@ -40,14 +41,21 @@ export default class FileUploaderService {
4041
*/
4142
private readonly fileRepository: FileRepository;
4243

44+
/**
45+
* Logger instance
46+
*/
47+
private readonly logger: DomainLogger;
48+
4349
/**
4450
* File uploader service constructor
4551
* @param objectRepository - repository for objects
4652
* @param fileRepository - repository for files data
53+
* @param logger - domain logger
4754
*/
48-
constructor(objectRepository: ObjectRepository, fileRepository: FileRepository) {
55+
constructor(objectRepository: ObjectRepository, fileRepository: FileRepository, logger: DomainLogger) {
4956
this.objectRepository = objectRepository;
5057
this.fileRepository = fileRepository;
58+
this.logger = logger;
5159
}
5260

5361
/**
@@ -96,6 +104,14 @@ export default class FileUploaderService {
96104
throw new DomainError('File was not uploaded');
97105
}
98106

107+
this.logger.info('File uploaded', {
108+
key: file.key,
109+
type,
110+
size: fileData.data.length,
111+
bucket,
112+
userId: file.metadata.userId,
113+
});
114+
99115
return file.key;
100116
}
101117

@@ -170,6 +186,12 @@ export default class FileUploaderService {
170186
if (isRemovedFromObjectStorage === false || isRemovedFromDatabase === false) {
171187
throw new DomainError('Cannot delete file');
172188
}
189+
190+
this.logger.info('File deleted', {
191+
key,
192+
type: fileType,
193+
bucket,
194+
});
173195
}
174196

175197
/**

src/domain/service/note.ts

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type { NoteList } from '@domain/entities/noteList.js';
1010
import type NoteHistoryRepository from '@repository/noteHistory.repository.js';
1111
import type { NoteHistoryMeta, NoteHistoryRecord, NoteHistoryPublic } from '@domain/entities/noteHistory.js';
1212
import type { NoteHierarchy } from '@domain/entities/NoteHierarchy.js';
13+
import type { DomainLogger } from '@infrastructure/logging/domainLoggerInterface.js';
1314

1415
/**
1516
* Note service
@@ -40,6 +41,11 @@ export default class NoteService {
4041
*/
4142
public noteHistoryRepository: NoteHistoryRepository;
4243

44+
/**
45+
* Logger instance
46+
*/
47+
private logger: DomainLogger;
48+
4349
/**
4450
* Number of the notes to be displayed on one page
4551
* it is used to calculate offset and limit for getting notes that the user has recently opened
@@ -58,13 +64,15 @@ export default class NoteService {
5864
* @param noteVisitsRepository - note visits repository
5965
* @param editorToolsRepository - editor tools repositoryn
6066
* @param noteHistoryRepository - note history repository
67+
* @param logger - domain logger
6168
*/
62-
constructor(noteRepository: NoteRepository, noteRelationsRepository: NoteRelationsRepository, noteVisitsRepository: NoteVisitsRepository, editorToolsRepository: EditorToolsRepository, noteHistoryRepository: NoteHistoryRepository) {
69+
constructor(noteRepository: NoteRepository, noteRelationsRepository: NoteRelationsRepository, noteVisitsRepository: NoteVisitsRepository, editorToolsRepository: EditorToolsRepository, noteHistoryRepository: NoteHistoryRepository, logger: DomainLogger) {
6370
this.noteRepository = noteRepository;
6471
this.noteRelationsRepository = noteRelationsRepository;
6572
this.noteVisitsRepository = noteVisitsRepository;
6673
this.editorToolsRepository = editorToolsRepository;
6774
this.noteHistoryRepository = noteHistoryRepository;
75+
this.logger = logger;
6876
}
6977

7078
/**
@@ -103,6 +111,12 @@ export default class NoteService {
103111
await this.noteRelationsRepository.addNoteRelation(note.id, parentNote.id);
104112
}
105113

114+
this.logger.info('Note created', {
115+
noteId: note.id,
116+
creatorId,
117+
parentPublicId,
118+
});
119+
106120
return note;
107121
}
108122

@@ -139,6 +153,11 @@ export default class NoteService {
139153
throw new DomainError(`Note with id ${id} was not deleted`);
140154
}
141155

156+
this.logger.info('Note deleted', {
157+
noteId: id,
158+
hadRelation: hasRelation,
159+
});
160+
142161
return isNoteDeleted;
143162
}
144163

@@ -168,6 +187,11 @@ export default class NoteService {
168187
throw new DomainError(`Note with id ${id} was not updated`);
169188
}
170189

190+
this.logger.debug('Note updated', {
191+
noteId: id,
192+
userId,
193+
});
194+
171195
return updatedNote;
172196
}
173197

@@ -176,7 +200,13 @@ export default class NoteService {
176200
* @param noteId - id of note to unlink parent
177201
*/
178202
public async unlinkParent(noteId: NoteInternalId): Promise<boolean> {
179-
return this.noteRelationsRepository.unlinkParent(noteId);
203+
const result = await this.noteRelationsRepository.unlinkParent(noteId);
204+
205+
this.logger.info('Note parent unlinked', {
206+
noteId,
207+
});
208+
209+
return result;
180210
}
181211

182212
/**
@@ -292,6 +322,11 @@ export default class NoteService {
292322
throw new DomainError(`Relation was not created`);
293323
}
294324

325+
this.logger.info('Note relation created', {
326+
noteId,
327+
parentNoteId: parentNote.id,
328+
});
329+
295330
return parentNote;
296331
}
297332

@@ -301,6 +336,8 @@ export default class NoteService {
301336
* @param parentPublicId - id of the new parent note
302337
*/
303338
public async updateNoteRelation(noteId: NoteInternalId, parentPublicId: NotePublicId): Promise<boolean> {
339+
const currentParentId = await this.noteRelationsRepository.getParentNoteIdByNoteId(noteId);
340+
304341
const parentNote = await this.noteRepository.getNoteByPublicId(parentPublicId);
305342

306343
if (parentNote === null) {
@@ -320,7 +357,15 @@ export default class NoteService {
320357
parentNoteId = await this.noteRelationsRepository.getParentNoteIdByNoteId(parentNoteId);
321358
}
322359

323-
return await this.noteRelationsRepository.updateNoteRelationById(noteId, parentNote.id);
360+
const result = await this.noteRelationsRepository.updateNoteRelationById(noteId, parentNote.id);
361+
362+
this.logger.info('Note relation changed', {
363+
noteId,
364+
oldParentId: currentParentId ?? undefined,
365+
newParentId: parentNote.id,
366+
});
367+
368+
return result;
324369
};
325370

326371
/**

0 commit comments

Comments
 (0)