Skip to content

Commit

Permalink
Merge pull request #50 from bcgov/feature/winston-logging
Browse files Browse the repository at this point in the history
Added winston logging
  • Loading branch information
timwekkenbc authored Nov 5, 2024
2 parents 7375dba + c389b69 commit 405a845
Show file tree
Hide file tree
Showing 22 changed files with 403 additions and 57 deletions.
302 changes: 297 additions & 5 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@
"csv-parser": "^3.0.0",
"mongoose": "^8.3.0",
"multer": "^1.4.5-lts.1",
"nest-winston": "^1.9.7",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1"
"rxjs": "^7.8.1",
"winston": "^3.16.0"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
Expand Down
9 changes: 8 additions & 1 deletion src/api/decisions/decisions.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ConfigService } from '@nestjs/config';
import { Test, TestingModule } from '@nestjs/testing';
import { Logger } from '@nestjs/common';
import { ZenEngine, ZenDecision, ZenEvaluateOptions } from '@gorules/zen-engine';
import { DecisionsService } from './decisions.service';
import { ValidationService } from './validations/validations.service';
Expand All @@ -25,7 +26,13 @@ describe('DecisionsService', () => {
};

const module: TestingModule = await Test.createTestingModule({
providers: [ConfigService, DecisionsService, ValidationService, { provide: ZenEngine, useValue: mockEngine }],
providers: [
ConfigService,
DecisionsService,
ValidationService,
{ provide: ZenEngine, useValue: mockEngine },
Logger,
],
}).compile();

service = module.get<DecisionsService>(DecisionsService);
Expand Down
9 changes: 6 additions & 3 deletions src/api/decisions/decisions.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { Injectable, HttpException, HttpStatus, Logger } from '@nestjs/common';
import { ZenEngine, ZenEvaluateOptions } from '@gorules/zen-engine';
import { ConfigService } from '@nestjs/config';
import { RuleContent } from '../ruleMapping/ruleMapping.interface';
Expand All @@ -11,7 +11,10 @@ export class DecisionsService {
engine: ZenEngine;
rulesDirectory: string;

constructor(private configService: ConfigService) {
constructor(
private configService: ConfigService,
private readonly logger: Logger,
) {
this.rulesDirectory = this.configService.get<string>('RULES_DIRECTORY');
const loader = async (key: string) => readFileSafely(this.rulesDirectory, key);
this.engine = new ZenEngine({ loader });
Expand All @@ -28,7 +31,7 @@ export class DecisionsService {
if (error instanceof ValidationError) {
throw new ValidationError(`Invalid input: ${error.message}`);
} else {
console.error(error.message);
this.logger.warn(error.message);
throw new Error(`Failed to run decision: ${error.message}`);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/api/klamm/klamm.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Module } from '@nestjs/common';
import { Module, Logger } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { RuleDataModule } from '../ruleData/ruleData.module';
import { RuleMappingModule } from '../ruleMapping/ruleMapping.module';
Expand All @@ -14,6 +14,6 @@ import { KlammService } from './klamm.service';
MongooseModule.forFeature([{ name: KlammSyncMetadata.name, schema: KlammSyncMetadataSchema }]),
],
controllers: [KlammController],
providers: [KlammService, DocumentsService],
providers: [KlammService, DocumentsService, Logger],
})
export class KlammModule {}
3 changes: 2 additions & 1 deletion src/api/klamm/klamm.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Model } from 'mongoose';
import { Logger } from '@nestjs/common';
import { KlammService, GITHUB_RULES_REPO } from './klamm.service';
import { RuleDataService } from '../ruleData/ruleData.service';
import { RuleMappingService } from '../ruleMapping/ruleMapping.service';
Expand Down Expand Up @@ -29,7 +30,7 @@ describe('KlammService', () => {
findOne: jest.fn(),
} as unknown as Model<KlammSyncMetadataDocument>;

service = new KlammService(ruleDataService, ruleMappingService, documentsService, klammSyncMetadata);
service = new KlammService(ruleDataService, ruleMappingService, documentsService, klammSyncMetadata, new Logger());
});

afterEach(() => {
Expand Down
41 changes: 21 additions & 20 deletions src/api/klamm/klamm.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { Injectable, HttpException, HttpStatus, Logger } from '@nestjs/common';
import { Model } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import axios, { AxiosInstance } from 'axios';
Expand Down Expand Up @@ -29,6 +29,7 @@ export class KlammService {
private readonly ruleMappingService: RuleMappingService,
private readonly documentsService: DocumentsService,
@InjectModel(KlammSyncMetadata.name) private klammSyncMetadata: Model<KlammSyncMetadataDocument>,
private readonly logger: Logger,
) {
this.axiosKlammInstance = axios.create({
headers: { Authorization: `Bearer ${process.env.KLAMM_API_AUTH_TOKEN}`, 'Content-Type': 'application/json' },
Expand All @@ -42,21 +43,21 @@ export class KlammService {

async onModuleInit() {
try {
console.info('Syncing existing rules with Klamm...');
this.logger.log('Syncing existing rules with Klamm...');
const { updatedFilesSinceLastDeploy, lastCommitAsyncTimestamp } = await this._getUpdatedFilesFromGithub();
if (lastCommitAsyncTimestamp != undefined) {
console.info(
this.logger.log(
`Files updated since last deploy up to ${new Date(lastCommitAsyncTimestamp)}:`,
updatedFilesSinceLastDeploy,
);
await this._syncRules(updatedFilesSinceLastDeploy);
console.info('Completed syncing existing rules with Klamm');
this.logger.log('Completed syncing existing rules with Klamm');
await this._updateLastSyncTimestamp(lastCommitAsyncTimestamp);
} else {
console.info('Klamm file syncing up to date');
this.logger.log('Klamm file syncing up to date');
}
} catch (error) {
console.error('Unable to sync latest updates to Klamm:', error.message);
this.logger.error('Unable to sync latest updates to Klamm:', error.message);
}
}

Expand Down Expand Up @@ -98,12 +99,12 @@ export class KlammService {
const rule = await this.ruleDataService.getRuleDataByFilepath(ruleFilepath);
if (rule) {
await this._syncRuleWithKlamm(rule);
console.info(`Rule ${rule.name} synced`);
this.logger.log(`Rule ${rule.name} synced`);
} else {
console.warn(`No rule found for changed file: ${ruleFilepath}`);
this.logger.warn(`No rule found for changed file: ${ruleFilepath}`);
}
} catch (error) {
console.error(`Failed to sync rule from file ${ruleFilepath}:`, error.message);
this.logger.error(`Failed to sync rule from file ${ruleFilepath}:`, error.message);
errors.push(`Failed to sync rule from file ${ruleFilepath}: ${error.message}`);
}
}
Expand All @@ -121,7 +122,7 @@ export class KlammService {
const timestamp = await this._getLastSyncTimestamp();
const date = new Date(timestamp);
const formattedDate = date.toISOString().split('.')[0] + 'Z'; // Format required for github api
console.log(`Getting files from Github from ${formattedDate} onwards...`);
this.logger.log(`Getting files from Github from ${formattedDate} onwards...`);
// Fetch commits since the specified timestamp
const commitsResponse = await this.axiosGithubInstance.get(
`${GITHUB_RULES_REPO}/commits?since=${formattedDate}&sha=${process.env.GITHUB_RULES_BRANCH}`,
Expand All @@ -144,7 +145,7 @@ export class KlammService {
}
return { updatedFilesSinceLastDeploy: Array.from(updatedFiles), lastCommitAsyncTimestamp };
} catch (error) {
console.error('Error fetching updated files from GitHub:', error);
this.logger.error('Error fetching updated files from GitHub:', error);
throw new Error('Error fetching updated files from GitHub');
}
}
Expand All @@ -166,7 +167,7 @@ export class KlammService {
// Add or update the rule in Klamm
await this._addOrUpdateRuleInKlamm(payloadToAddOrUpdate);
} catch (error) {
console.error(`Error syncing ${rule.name}`, error.message);
this.logger.error(`Error syncing ${rule.name}`, error.message);
throw new Error(`Error syncing ${rule.name}`);
}
}
Expand All @@ -181,7 +182,7 @@ export class KlammService {
const outputResults = this._getFieldsFromIds(klammFields, outputIds);
return { inputs: inputResults, outputs: outputResults };
} catch (error) {
console.error(`Error getting input/output fields for rule ${rule.name}`, error.message);
this.logger.error(`Error getting input/output fields for rule ${rule.name}`, error.message);
throw new Error(`Error getting input/output fields for rule ${rule.name}`);
}
}
Expand All @@ -201,7 +202,7 @@ export class KlammService {
const response = await this.axiosKlammInstance.get(`${process.env.KLAMM_API_URL}/api/brerules`);
return response.data.data;
} catch (error) {
console.error('Error fetching fields from Klamm', error.message);
this.logger.error('Error fetching fields from Klamm', error.message);
throw new Error(`Error fetching fields from Klamm: ${error.message}`);
}
}
Expand All @@ -217,7 +218,7 @@ export class KlammService {
const results = await Promise.all(promises);
return results.map((response) => response);
} catch (error) {
console.error(`Error gettting child rules for ${rule.name}:`, error.message);
this.logger.error(`Error gettting child rules for ${rule.name}:`, error.message);
throw new Error(`Error gettting child rules for ${rule.name}`);
}
}
Expand All @@ -239,7 +240,7 @@ export class KlammService {
});
return data.data[0];
} catch (error) {
console.error(`Error getting rule ${ruleName} from Klamm:`, error.message);
this.logger.error(`Error getting rule ${ruleName} from Klamm:`, error.message);
throw new Error(`Error getting rule ${ruleName} from Klamm`);
}
}
Expand All @@ -248,7 +249,7 @@ export class KlammService {
try {
await this.axiosKlammInstance.post(`${process.env.KLAMM_API_URL}/api/brerules`, rulePayload);
} catch (error) {
console.error('Error adding rule to Klamm:', error.message);
this.logger.error('Error adding rule to Klamm:', error.message);
throw new Error('Error adding rule to Klamm');
}
}
Expand All @@ -257,7 +258,7 @@ export class KlammService {
try {
await this.axiosKlammInstance.put(`${process.env.KLAMM_API_URL}/api/brerules/${currentKlamRuleId}`, rulePayload);
} catch (error) {
console.error(`Error updating rule ${currentKlamRuleId} in Klamm:`, error.message);
this.logger.error(`Error updating rule ${currentKlamRuleId} in Klamm:`, error.message);
throw new Error(`Error updating rule ${currentKlamRuleId} in Klamm`);
}
}
Expand All @@ -270,7 +271,7 @@ export class KlammService {
{ upsert: true, new: true },
);
} catch (error) {
console.error('Failed to update last sync timestamp', error.message);
this.logger.error('Failed to update last sync timestamp', error.message);
throw new Error('Failed to update last sync timestamp');
}
}
Expand All @@ -280,7 +281,7 @@ export class KlammService {
const record = await this.klammSyncMetadata.findOne({ key: 'singleton' });
return record ? record.lastSyncTimestamp : 0;
} catch (error) {
console.error('Failed to get last sync timestamp:', error.message);
this.logger.error('Failed to get last sync timestamp:', error.message);
throw new Error('Failed to get last sync timestamp');
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/api/ruleData/ruleData.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Module } from '@nestjs/common';
import { Logger, Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { RuleData, RuleDataSchema } from './ruleData.schema';
import { RuleDraft, RuleDraftSchema } from './ruleDraft.schema';
Expand All @@ -14,7 +14,7 @@ import { DocumentsService } from '../documents/documents.service';
]),
],
controllers: [RuleDataController],
providers: [RuleDataService, DocumentsService],
providers: [RuleDataService, DocumentsService, Logger],
exports: [RuleDataService],
})
export class RuleDataModule {}
2 changes: 2 additions & 0 deletions src/api/ruleData/ruleData.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Test, TestingModule } from '@nestjs/testing';
import { Logger } from '@nestjs/common';
import { getModelToken } from '@nestjs/mongoose';
import { DocumentsService } from '../documents/documents.service';
import { RuleDataService } from './ruleData.service';
Expand Down Expand Up @@ -45,6 +46,7 @@ export const mockServiceProviders = [
getAllJSONFiles: jest.fn().mockResolvedValue(['doc1.json', 'doc2.json']),
},
},
Logger,
];

describe('RuleDataService', () => {
Expand Down
11 changes: 6 additions & 5 deletions src/api/ruleData/ruleData.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ObjectId } from 'mongodb';
import { Model, Types } from 'mongoose';
import { Injectable } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import axios from 'axios';
import { DocumentsService } from '../documents/documents.service';
Expand All @@ -18,10 +18,11 @@ export class RuleDataService {
@InjectModel(RuleData.name) private ruleDataModel: Model<RuleDataDocument>,
@InjectModel(RuleDraft.name) private ruleDraftModel: Model<RuleDraftDocument>,
private documentsService: DocumentsService,
private readonly logger: Logger,
) {}

async onModuleInit() {
console.info('Syncing existing rules with any updates to the rules repository');
this.logger.log('Syncing existing rules with any updates to the rules repository');
const existingRules = await this.getAllRuleData();
const { data: existingRuleData } = existingRules;
this.updateCategories(existingRuleData);
Expand Down Expand Up @@ -161,7 +162,7 @@ export class RuleDataService {
this.updateCategories(existingRules.data);
return response;
} catch (error) {
console.error(error.message);
this.logger.error(error.message);
throw new Error(`Failed to add rule data: ${error.message}`);
}
}
Expand All @@ -179,7 +180,7 @@ export class RuleDataService {
Object.assign(existingRuleData, updatedData);
return await existingRuleData.save();
} catch (error) {
console.error('Error updating rule', error.message);
this.logger.error('Error updating rule', error.message);
throw new Error(`Failed to update rule data: ${error.message}`);
}
}
Expand Down Expand Up @@ -220,7 +221,7 @@ export class RuleDataService {
});
}
} catch (error) {
console.error('Error updating review status:', error.message);
this.logger.error('Error updating review status:', error.message);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/api/scenarioData/scenarioData.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Test, TestingModule } from '@nestjs/testing';
import { Logger } from '@nestjs/common';
import { ScenarioDataService } from './scenarioData.service';
import { getModelToken } from '@nestjs/mongoose';
import { Types, Model } from 'mongoose';
Expand Down Expand Up @@ -69,6 +70,7 @@ describe('ScenarioDataService', () => {
get: jest.fn().mockReturnValue('mocked_value'),
},
},
Logger,
],
}).compile();

Expand Down
9 changes: 5 additions & 4 deletions src/api/scenarioData/scenarioData.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable } from '@nestjs/common';
import { Injectable, Logger } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model, Types } from 'mongoose';
import { ScenarioData, ScenarioDataDocument } from './scenarioData.schema';
Expand Down Expand Up @@ -26,6 +26,7 @@ export class ScenarioDataService {
private ruleMappingService: RuleMappingService,
private documentsService: DocumentsService,
@InjectModel(ScenarioData.name) private scenarioDataModel: Model<ScenarioDataDocument>,
private readonly logger: Logger,
) {}

async getAllScenarioData(): Promise<ScenarioData[]> {
Expand Down Expand Up @@ -55,7 +56,7 @@ export class ScenarioDataService {
const response = await newScenarioData.save();
return response;
} catch (error) {
console.error('Error in createScenarioData:', error);
this.logger.error('Error in createScenarioData:', error);
throw new Error(`Failed to add scenario data: ${error.message}`);
}
}
Expand Down Expand Up @@ -147,7 +148,7 @@ export class ScenarioDataService {

results[scenario.title.toString()] = scenarioResult;
} catch (error) {
console.error(`Error running decision for scenario ${scenario._id}: ${error.message}`);
this.logger.error(`Error running decision for scenario ${scenario._id}: ${error.message}`);
const scenarioResult = {
inputs: formattedVariablesObject,
outputs: null,
Expand Down Expand Up @@ -511,7 +512,7 @@ export class ScenarioDataService {
},
};
} catch (error) {
console.error(`Error running decision for scenario ${title}: ${error.message}`);
this.logger.error(`Error running decision for scenario ${title}: ${error.message}`);
return {
title,
scenarioResult: {
Expand Down
4 changes: 2 additions & 2 deletions src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Module } from '@nestjs/common';
import { Logger, Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MongooseModule } from '@nestjs/mongoose';
import { GithubAuthModule } from './auth/github-auth/github-auth.module';
Expand Down Expand Up @@ -31,6 +31,6 @@ import { ScenarioDataService } from './api/scenarioData/scenarioData.service';
KlammModule,
],
controllers: [DecisionsController, DocumentsController, ScenarioDataController],
providers: [DecisionsService, DocumentsService, ScenarioDataService],
providers: [Logger, DecisionsService, DocumentsService, ScenarioDataService],
})
export class AppModule {}
Loading

0 comments on commit 405a845

Please sign in to comment.