From b5ac74e42c3ed8c39733b3ecb85006d543797a79 Mon Sep 17 00:00:00 2001 From: mfullmore Date: Wed, 4 Sep 2024 17:13:23 -0700 Subject: [PATCH] adding support for LWC logging example --- .forceignore | 5 +- .vscode/settings.json | 3 + .../classes/TritonDmlDemoController.cls | 12 ++++ .../TritonDmlDemoController.cls-meta.xml | 5 ++ force-app/main/default/classes/TritonLwc.cls | 63 ++++++++++--------- force-app/main/default/classes/TritonTest.cls | 2 +- force-app/main/default/lwc/triton/triton.js | 29 +++------ .../tritonDemo/__tests__/tritonDemo.test.js | 25 ++++++++ .../default/lwc/tritonDemo/tritonDemo.html | 3 + .../main/default/lwc/tritonDemo/tritonDemo.js | 41 ++++++++++++ .../lwc/tritonDemo/tritonDemo.js-meta.xml | 8 +++ 11 files changed, 144 insertions(+), 52 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 force-app/main/default/classes/TritonDmlDemoController.cls create mode 100644 force-app/main/default/classes/TritonDmlDemoController.cls-meta.xml create mode 100644 force-app/main/default/lwc/tritonDemo/__tests__/tritonDemo.test.js create mode 100644 force-app/main/default/lwc/tritonDemo/tritonDemo.html create mode 100644 force-app/main/default/lwc/tritonDemo/tritonDemo.js create mode 100644 force-app/main/default/lwc/tritonDemo/tritonDemo.js-meta.xml diff --git a/.forceignore b/.forceignore index 7b5b5a7..3d36001 100755 --- a/.forceignore +++ b/.forceignore @@ -9,4 +9,7 @@ package.xml **/.eslintrc.json # LWC Jest -**/__tests__/** \ No newline at end of file +**/__tests__/** +**/tsconfig.json + +**/*.ts diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e7c268d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "salesforcedx-vscode-core.show-cli-success-msg": false +} \ No newline at end of file diff --git a/force-app/main/default/classes/TritonDmlDemoController.cls b/force-app/main/default/classes/TritonDmlDemoController.cls new file mode 100644 index 0000000..79cdffb --- /dev/null +++ b/force-app/main/default/classes/TritonDmlDemoController.cls @@ -0,0 +1,12 @@ +/** + @description LWC Apex Api Class for use to demo Triton + */ +public with sharing class TritonDmlDemoController { + + public class TritonDmlDemoControllerException extends Exception {} + + @AuraEnabled + public static String triggerDmlException() { + throw new TritonDmlDemoControllerException('Error Msg'); + } +} diff --git a/force-app/main/default/classes/TritonDmlDemoController.cls-meta.xml b/force-app/main/default/classes/TritonDmlDemoController.cls-meta.xml new file mode 100644 index 0000000..7d5f9e8 --- /dev/null +++ b/force-app/main/default/classes/TritonDmlDemoController.cls-meta.xml @@ -0,0 +1,5 @@ + + + 61.0 + Active + \ No newline at end of file diff --git a/force-app/main/default/classes/TritonLwc.cls b/force-app/main/default/classes/TritonLwc.cls index 3f11c6d..ecc5437 100644 --- a/force-app/main/default/classes/TritonLwc.cls +++ b/force-app/main/default/classes/TritonLwc.cls @@ -18,39 +18,44 @@ public with sharing class TritonLwc { /** * Create component logs from LWC * Use this method to persist logs generated from LWC components - * @param componentLogs -- a collection of ComponentLog objects + * @param componentLogs -- a collection of ComponentLog objects serialized */ @AuraEnabled - public static void saveComponentLogs(List componentLogs) { + public static void saveComponentLogs(String pComponentLogs) { + System.debug('pComponentLogs: ' + pComponentLogs); + List componentLogs = (List)JSON.deserialize( + pComponentLogs, + List.class + ); Triton logInstance = Triton.instance; - for (ComponentLog componentLog : componentLogs) { + for (TritonLwc.ComponentLog componentLog : componentLogs) { logInstance.add( - Triton.makeBuilder() - //category will be fetched from the componentLog - .category(String.isNotBlank(componentLog.category) ? componentLog.category : componentLog.component.category) - //type will be fetched from the componentLog directly, of from the error. If neither are set, Frontend will be used - .type(String.isNotBlank(componentLog.type) ? componentLog.type : - componentLog.error != null ? componentLog.error.type : TritonTypes.Type.Frontend.name()) - //area will be fetched from the componentLog directly if set. Otherwise component name will be used - .area(String.isNotBlank(componentLog.area) ? componentLog.area : componentLog.component.name) - //summary will be fetched from the componentLog directly if set. Otherwise, error message will be used if provided. - .summary(String.isNotBlank(componentLog.summary) ? componentLog.summary : - componentLog.error != null ? componentLog.error.message : null) - .stackTrace(componentLog.stack) - .details(componentLog.details) - //transaction id will be used from the componentLog, or a new transaction id will be generated - .transactionId(String.isNotBlank(componentLog.transactionId) ? componentLog.transactionId : logInstance.TRANSACTION_ID) - .attribute(Triton.USER_ID, componentLog.userId) - //apex name will be set to component.function or component.action - .attribute(Triton.APEX_NAME, componentLog.component.name + '.' + - (String.isNotBlank(componentLog.component.function) ? componentLog.component.function : componentLog.component.action)) - .attribute(Triton.RELATED_ID, componentLog.recordId) - //created timestamp will be either set from the componentLog if provided, otherwise current timestamp will be used - .attribute(Triton.CREATED_TIMESTAMP, componentLog.createdTimestamp != null ? Double.valueOf(componentLog.createdTimestamp) : Double.valueOf(System.now().getTime())) - //log level will be taken from the componentLog if provided, otherwise INFO will be used - .attribute(Triton.LOG_LEVEL, String.isNotBlank(componentLog.level) ? componentLog.level : TritonTypes.Level.INFO.name()) - .attribute(Triton.DURATION, componentLog.duration) - .build()); + Triton.makeBuilder() + //category will be fetched from the componentLog + .category(String.isNotBlank(componentLog.category) ? componentLog.category : componentLog.component.category) + //type will be fetched from the componentLog directly, of from the error. If neither are set, Frontend will be used + .type(String.isNotBlank(componentLog.type) ? componentLog.type : + componentLog.error != null ? componentLog.error.type : TritonTypes.Type.Frontend.name()) + //area will be fetched from the componentLog directly if set. Otherwise component name will be used + .area(String.isNotBlank(componentLog.area) ? componentLog.area : componentLog.component.name) + //summary will be fetched from the componentLog directly if set. Otherwise, error message will be used if provided. + .summary(String.isNotBlank(componentLog.summary) ? componentLog.summary : + componentLog.error != null ? componentLog.error.message : null) + .stackTrace(componentLog.stack) + .details(componentLog.details) + //transaction id will be used from the componentLog, or a new transaction id will be generated + .transactionId(String.isNotBlank(componentLog.transactionId) ? componentLog.transactionId : logInstance.TRANSACTION_ID) + .attribute(Triton.USER_ID, componentLog.userId) + //apex name will be set to component.function or component.action + .attribute(Triton.APEX_NAME, componentLog.component.name + '.' + + (String.isNotBlank(componentLog.component.function) ? componentLog.component.function : componentLog.component.action)) + .attribute(Triton.RELATED_ID, componentLog.recordId) + //created timestamp will be either set from the componentLog if provided, otherwise current timestamp will be used + .attribute(Triton.CREATED_TIMESTAMP, componentLog.createdTimestamp != null ? Double.valueOf(componentLog.createdTimestamp) : Double.valueOf(System.now().getTime())) + //log level will be taken from the componentLog if provided, otherwise INFO will be used + .attribute(Triton.LOG_LEVEL, String.isNotBlank(componentLog.level) ? componentLog.level : TritonTypes.Level.INFO.name()) + .attribute(Triton.DURATION, componentLog.duration) + .build()); } logInstance.flush(); } diff --git a/force-app/main/default/classes/TritonTest.cls b/force-app/main/default/classes/TritonTest.cls index a94bb62..6977727 100644 --- a/force-app/main/default/classes/TritonTest.cls +++ b/force-app/main/default/classes/TritonTest.cls @@ -247,7 +247,7 @@ private class TritonTest { component.function = 'test function'; componentLog.component = component; componentLogs.add(componentLog); - TritonLwc.saveComponentLogs(componentLogs); + TritonLwc.saveComponentLogs(JSON.serialize(componentLogs)); Test.stopTest(); List logs = [SELECT Id, pharos__Summary__c, pharos__Hash__c FROM pharos__Log__c]; diff --git a/force-app/main/default/lwc/triton/triton.js b/force-app/main/default/lwc/triton/triton.js index ff16d7d..087cdd7 100644 --- a/force-app/main/default/lwc/triton/triton.js +++ b/force-app/main/default/lwc/triton/triton.js @@ -8,18 +8,15 @@ * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * / + */ -import {LightningElement, api} from 'lwc'; -import {makeBuilder} from 'c/tritonBuilder'; +import { makeBuilder } from 'c/tritonBuilder'; import saveComponentLogs from '@salesforce/apex/TritonLwc.saveComponentLogs'; -export default class Triton extends LightningElement { - +const Triton = class { /** * Logs buffer */ - @api logs = []; /** @@ -29,7 +26,6 @@ export default class Triton extends LightningElement { * Summary is the Exception message. * Details will be a combination of Exception String and stacktrace */ - @api addException(error) { return this._makeBuilder().setError(error).setLevel(LEVEL.ERROR); } @@ -37,7 +33,6 @@ export default class Triton extends LightningElement { /** * Add Log with LWC / Aura Category. */ - @api addError() { return this._makeBuilder().setLevel(LEVEL.ERROR); } @@ -45,7 +40,6 @@ export default class Triton extends LightningElement { /** * Add Log with Warning Category. */ - @api addWarning() { return this._makeBuilder().setCategory(CATEGORY.WARNING).setLevel(LEVEL.WARNING); } @@ -53,7 +47,6 @@ export default class Triton extends LightningElement { /** * Add Log with Debug Category. */ - @api addDebug() { return this._makeBuilder().setCategory(CATEGORY.DEBUG).setLevel(LEVEL.DEBUG); } @@ -61,7 +54,6 @@ export default class Triton extends LightningElement { /** * Add Log with Event Category. */ - @api addInfo() { return this._makeBuilder().setCategory(CATEGORY.EVENT).setLevel(LEVEL.INFO); } @@ -73,7 +65,6 @@ export default class Triton extends LightningElement { * Summary is the Exception message. * Details will be a combination of Exception String and stacktrace */ - @api exception(error, transactionId) { this._makeBuilder() .setError(error) @@ -85,7 +76,6 @@ export default class Triton extends LightningElement { /** * Save Log with LWC / Aura Category. */ - @api error(type, area, summary, details, transactionId, component, duration, startTime) { this._makeBuilder() .setLevel(LEVEL.ERROR) @@ -103,7 +93,6 @@ export default class Triton extends LightningElement { /** * Save Log with Warning Category. */ - @api warning(type, area, summary, details, transactionId, component, duration, startTime) { this._makeBuilder() .setLevel(LEVEL.WARNING) @@ -122,7 +111,6 @@ export default class Triton extends LightningElement { /** * Save Log with Debug Category. */ - @api debug(type, area, summary, details, transactionId, component, duration, startTime) { this._makeBuilder() .setLevel(LEVEL.DEBUG) @@ -141,7 +129,6 @@ export default class Triton extends LightningElement { /** * Save Log with Event Category. */ - @api info(type, area, summary, details, level, transactionId, component, duration, startTime) { this._makeBuilder() .setLevel(level) @@ -160,24 +147,22 @@ export default class Triton extends LightningElement { /** * Commit all logs previously added using the addXXX() methods. */ - @api flush() { saveComponentLogs({ - componentLogs: this.logs + pComponentLogs: JSON.stringify(this.logs) }).then((data) => { }).catch(error => { console.error(error); }); this.logs = []; } - _makeBuilder() { let logBuilder = makeBuilder(); this.logs.push(logBuilder); return logBuilder; } -} +}; /** AREA */ export const AREA = { @@ -212,4 +197,6 @@ export const LEVEL = { export const TYPE = { BACKEND: 'Backend', FRONTEND: 'Frontend' -}; \ No newline at end of file +}; + +export default Triton; diff --git a/force-app/main/default/lwc/tritonDemo/__tests__/tritonDemo.test.js b/force-app/main/default/lwc/tritonDemo/__tests__/tritonDemo.test.js new file mode 100644 index 0000000..52bcbf7 --- /dev/null +++ b/force-app/main/default/lwc/tritonDemo/__tests__/tritonDemo.test.js @@ -0,0 +1,25 @@ +import { createElement } from 'lwc'; +import TritonDemo from 'c/tritonDemo'; + +describe('c-triton-demo', () => { + afterEach(() => { + // The jsdom instance is shared across test cases in a single file so reset the DOM + while (document.body.firstChild) { + document.body.removeChild(document.body.firstChild); + } + }); + + it('TODO: test case generated by CLI command, please fill in test logic', () => { + // Arrange + const element = createElement('c-triton-demo', { + is: TritonDemo + }); + + // Act + document.body.appendChild(element); + + // Assert + // const div = element.shadowRoot.querySelector('div'); + expect(1).toBe(1); + }); +}); \ No newline at end of file diff --git a/force-app/main/default/lwc/tritonDemo/tritonDemo.html b/force-app/main/default/lwc/tritonDemo/tritonDemo.html new file mode 100644 index 0000000..f5c6b23 --- /dev/null +++ b/force-app/main/default/lwc/tritonDemo/tritonDemo.html @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/force-app/main/default/lwc/tritonDemo/tritonDemo.js b/force-app/main/default/lwc/tritonDemo/tritonDemo.js new file mode 100644 index 0000000..4753f32 --- /dev/null +++ b/force-app/main/default/lwc/tritonDemo/tritonDemo.js @@ -0,0 +1,41 @@ +import { LightningElement } from 'lwc'; +import { ShowToastEvent } from "lightning/platformShowToastEvent"; + +import triggerDmlException from '@salesforce/apex/TritonDmlDemoController.triggerDmlException'; +import { AREA, TYPE } from 'c/triton'; +import Triton from 'c/triton'; + +export default class TritonDemo extends LightningElement { + + someText; + + async connectedCallback() { + + this.someText = 'Hello World!'; + // This demo will fire everytime this component renders on the page + // meaning every time you load this LWC you will get a log record + try { + const returnMsg = await triggerDmlException(); + } catch(e) { + + const tritonLogger = new Triton(); + tritonLogger.error( + TYPE.FRONTEND, + AREA.ACCOUNTS, + e.body.message, + e.body.stackTrace, + '', + 'c.tritonDemo', + '', + Date.now() + ); + + this.dispatchEvent(new ShowToastEvent({ + message: e.body.message, + title: 'Test error', + variant: {label: 'error', value: 'error' } + })); + } + } +} + \ No newline at end of file diff --git a/force-app/main/default/lwc/tritonDemo/tritonDemo.js-meta.xml b/force-app/main/default/lwc/tritonDemo/tritonDemo.js-meta.xml new file mode 100644 index 0000000..24b2342 --- /dev/null +++ b/force-app/main/default/lwc/tritonDemo/tritonDemo.js-meta.xml @@ -0,0 +1,8 @@ + + + 61.0 + false + + lightning__Tab + + \ No newline at end of file