Skip to content

Commit

Permalink
feat(log): improve logging for contract build and interactions (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
rahulyadav-57 authored Jul 31, 2024
1 parent 9c88678 commit 4331631
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 57 deletions.
16 changes: 0 additions & 16 deletions public/assets/js/log.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,16 @@ const ContractInteraction: FC<Props> = ({
}, [isLoading, tonConnector, network, contractAddress, contract]);

const send = async (data: string) => {
await sendMessage(data, contractAddress, contract, network, wallet!);
const messageResponse = await sendMessage(
data,
contractAddress,
contract,
network,
wallet!,
);
messageResponse?.logs?.map((log) => {
createLog(log, 'info');
});
};

if (!contractAddress) {
Expand Down
35 changes: 0 additions & 35 deletions src/components/workspace/WorkSpace/WorkSpace.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,6 @@ const WorkSpace: FC = () => {
globalWorkspace.sandboxWallet = wallet;
};

const interceptConsoleError = (e: CustomEvent<{ data?: string[] }>) => {
if (!e.detail.data || e.detail.data.length === 0) return;
const _log = e.detail.data.join(', ');
// Some of the error aren't getting thrown by Tact compiler instead then are logged.
// console.error is not getting intercepted by the workspace because they stores reference to the original console.error method. So I have created global script(public/assets/js/log.js) which is getting loaded before any other script and it listens to the console.error and dispatches an event with the error message.

createLog(_log, 'error', true, true);
};

const onKeydown = (e: KeyboardEvent) => {
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
e.preventDefault();
Expand All @@ -93,41 +84,15 @@ const WorkSpace: FC = () => {

useEffect(() => {
document.addEventListener('keydown', onKeydown);
const originalConsoleLog = console.log;

console.log = (...args) => {
// console.trace(args);
originalConsoleLog(...args); // Call the original console.log
const _log = args.join(' ');
if (!_log.includes('DEBUG') || activeProject?.language === 'tact') {
return;
}
const splittedLog = _log.split('\n');

for (const log of splittedLog) {
createLog(log, 'info', true, true);
}
};

Analytics.track('Project Opened', {
platform: 'IDE',
type: 'TON-func',
});

document.addEventListener(
'consoleError',
interceptConsoleError as unknown as EventListener,
);

return () => {
console.log = originalConsoleLog;
try {
document.removeEventListener('keydown', onKeydown);
document.removeEventListener(
'consoleError',
interceptConsoleError as unknown as EventListener,
);

clearLog();
} catch (error) {
/* empty */
Expand Down
9 changes: 9 additions & 0 deletions src/components/workspace/globalWorkspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,18 @@ import { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox';
interface GlobalWorkspace {
sandboxBlockchain: Blockchain | null;
sandboxWallet: SandboxContract<TreasuryContract> | null;
getDebugLogs: () => string[];
}

export const globalWorkspace: GlobalWorkspace = {
sandboxBlockchain: null,
sandboxWallet: null,
getDebugLogs: () => {
if (!globalWorkspace.sandboxBlockchain) {
return [];
}
const blockchain = globalWorkspace.sandboxBlockchain as Blockchain;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (blockchain.executor as any).debugLogs ?? [];
},
};
25 changes: 20 additions & 5 deletions src/hooks/contract.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ParameterType,
Project,
} from '@/interfaces/workspace.interface';
import EventEmitter from '@/utility/eventEmitter';
import {
capitalizeFirstLetter,
convertToText,
Expand Down Expand Up @@ -233,12 +234,15 @@ export function useContractAction() {
await message.error('The contract has not been deployed yet.');
return;
}
await contract.sendData(
const response = await contract.sendData(
wallet.getSender(),
_dataCell,
tonAmountForInteraction,
);
return;
return {
message: 'Message sent successfully',
logs: terminalLogMessages([response], [contract as Contract]),
};
}
try {
const params: SendTransactionRequest = {
Expand Down Expand Up @@ -404,6 +408,7 @@ export function useContractAction() {
capitalizeFirstLetter(methodName)) as keyof Contract;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const response = await (contract as any)[_method](...(params as any));
printDebugLog();
responseValues.push({
method: methodName,
value: convertToText(response),
Expand All @@ -413,6 +418,7 @@ export function useContractAction() {
methodName,
parsedStack as TupleItem[],
);
printDebugLog();
while (call.stack.remaining) {
const parsedData = parseReponse(call.stack.pop());
if (parsedData) {
Expand Down Expand Up @@ -565,9 +571,7 @@ function terminalLogMessages(
if (transaction.inMessage.info.type === 'internal') {
if (transaction.debugLogs) {
const splittedLog = transaction.debugLogs.split('\n');
for (const log of splittedLog) {
messages.push(log);
}
messages.push(splittedLog.join('\r\n'));
}
if (transaction.description.type === 'generic') {
if (transaction.description.computePhase.type === 'vm') {
Expand Down Expand Up @@ -705,3 +709,14 @@ function shorten(
}
return '';
}

function printDebugLog() {
const debugLogs = globalWorkspace.getDebugLogs();
if (debugLogs.length > 0) {
EventEmitter.emit('LOG', {
type: 'info',
text: debugLogs.join('\r\n'),
timestamp: new Date().toISOString(),
});
}
}
2 changes: 2 additions & 0 deletions src/hooks/project.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import stdLibFiles from '@tact-lang/compiler/dist/imports/stdlib';
import { precompile } from '@tact-lang/compiler/dist/pipeline/precompile';
import { getType } from '@tact-lang/compiler/dist/types/resolveDescriptors';

import TactLogger from '@/utility/tactLogger';
import { CompilerContext } from '@tact-lang/compiler/dist/context';
import {
CompileResult,
Expand Down Expand Up @@ -216,6 +217,7 @@ export function useProjectActions() {
},
project: fs,
stdlib: '@stdlib',
logger: new TactLogger(),
});
if (!response.ok) {
throw new Error('Error while building');
Expand Down
39 changes: 39 additions & 0 deletions src/utility/tactLogger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { LogLevel, LogMethods, Logger } from '@tact-lang/compiler';
import EventEmitter from './eventEmitter';

const logLevelToMethodName: { [key in LogLevel]: keyof LogMethods | null } = {
[LogLevel.NONE]: null,
[LogLevel.ERROR]: 'error',
[LogLevel.WARN]: 'warn',
[LogLevel.INFO]: 'info',
[LogLevel.DEBUG]: 'debug',
};

function getLoggingMethod(level: LogLevel): keyof LogMethods | null {
return logLevelToMethodName[level];
}

export default class TactLogger extends Logger {
private levelLevel: LogLevel;
constructor(level: LogLevel = LogLevel.INFO) {
super(level);
this.levelLevel = level;
}
protected log(level: LogLevel, message: string | Error): void {
if (this.levelLevel === LogLevel.NONE) {
return;
}

message = message instanceof Error ? message.message : message;

if (level > this.levelLevel) return;
const loggingMethod = getLoggingMethod(level);
if (!loggingMethod) return;

EventEmitter.emit('LOG', {
text: message,
type: loggingMethod as Exclude<keyof LogMethods, 'debug' | 'warn'>,
timestamp: new Date().toISOString(),
});
}
}

0 comments on commit 4331631

Please sign in to comment.