Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make users capable of integrating modern logging library #1215

Merged
merged 9 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/nervous-bugs-doubt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"near-api-js": minor
"@near-js/accounts": patch
"@near-js/providers": patch
"@near-js/utils": patch
"@near-js/wallet-account": patch
---

Internal logging library with capabilities for integration with modern logging libraries like Pino, Winston, etc
2 changes: 2 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ const {
format,
logWarning,
rpc_errors,
Logger
} = utils;
const {
formatNearAmount,
Expand Down Expand Up @@ -316,5 +317,6 @@ import {
parseNearAmount,
parseResultError,
parseRpcError,
Logger
} from '@near-js/utils';
```
10 changes: 4 additions & 6 deletions packages/accounts/src/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
import {
baseDecode,
baseEncode,
logWarning,
Logger,
parseResultError,
DEFAULT_FUNCTION_CALL_GAS,
printTxOutcomeLogs,
Expand Down Expand Up @@ -223,12 +223,12 @@ export class Account {
return await this.connection.provider.sendTransaction(signedTx);
} catch (error) {
if (error.type === 'InvalidNonce') {
logWarning(`Retrying transaction ${receiverId}:${baseEncode(txHash)} with new nonce.`);
Logger.warn(`Retrying transaction ${receiverId}:${baseEncode(txHash)} with new nonce.`);
delete this.accessKeyByPublicKeyCache[publicKey.toString()];
return null;
}
if (error.type === 'Expired') {
logWarning(`Retrying transaction ${receiverId}:${baseEncode(txHash)} due to expired block hash`);
Logger.warn(`Retrying transaction ${receiverId}:${baseEncode(txHash)} due to expired block hash`);
return null;
}

Expand Down Expand Up @@ -360,9 +360,7 @@ export class Account {
* @param beneficiaryId The NEAR account that will receive the remaining Ⓝ balance from the account being deleted
*/
async deleteAccount(beneficiaryId: string) {
if (!(typeof process === 'object' && process.env['NEAR_NO_LOGS'])) {
console.log('Deleting an account does not automatically transfer NFTs and FTs to the beneficiary address. Ensure to transfer assets before deleting.');
}
Logger.log('Deleting an account does not automatically transfer NFTs and FTs to the beneficiary address. Ensure to transfer assets before deleting.');
return this.signAndSendTransaction({
receiverId: this.accountId,
actions: [deleteAccount(beneficiaryId)]
Expand Down
7 changes: 4 additions & 3 deletions packages/accounts/src/account_2fa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { PublicKey } from '@near-js/crypto';
import { FinalExecutionOutcome, TypedError, FunctionCallPermissionView } from '@near-js/types';
import { fetchJson } from '@near-js/providers';
import { actionCreators } from '@near-js/transactions';
import { Logger } from '@near-js/utils'
import BN from 'bn.js';

import { SignAndSendTransactionOptions } from './account';
Expand Down Expand Up @@ -84,7 +85,7 @@ export class Account2FA extends AccountMultisig {
deployContract(contractBytes),
];
const newFunctionCallActionBatch = actions.concat(functionCall('new', newArgs, MULTISIG_GAS, MULTISIG_DEPOSIT));
console.log('deploying multisig contract for', accountId);
Logger.log('deploying multisig contract for', accountId);

const { stateStatus: multisigStateStatus } = await this.checkMultisigCodeAndStateStatus(contractBytes);
switch (multisigStateStatus) {
Expand Down Expand Up @@ -185,7 +186,7 @@ export class Account2FA extends AccountMultisig {
...(await this.get2faDisableKeyConversionActions()),
deployContract(contractBytes),
];
console.log('disabling 2fa for', this.accountId);
Logger.log('disabling 2fa for', this.accountId);
return await this.signAndSendTransaction({
receiverId: this.accountId,
actions
Expand Down Expand Up @@ -217,7 +218,7 @@ export class Account2FA extends AccountMultisig {
// TODO: Parse error from result for real (like in normal account.signAndSendTransaction)
return result;
} catch (e) {
console.warn('Error validating security code:', e);
Logger.warn('Error validating security code:', e);
if (e.toString().includes('invalid 2fa code provided') || e.toString().includes('2fa code not valid')) {
return await this.promptAndVerify();
}
Expand Down
3 changes: 2 additions & 1 deletion packages/accounts/src/account_multisig.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Action, actionCreators } from '@near-js/transactions';
import { FinalExecutionOutcome } from '@near-js/types';
import { Logger } from '@near-js/utils';

import { Account, SignAndSendTransactionOptions } from './account';
import { Connection } from './connection';
Expand Down Expand Up @@ -156,7 +157,7 @@ export class AccountMultisig extends Account {
actions: [functionCall('delete_request', { request_id: requestIdToDelete }, MULTISIG_GAS, MULTISIG_DEPOSIT)]
});
} catch (e) {
console.warn('Attempt to delete an earlier request before 15 minutes failed. Will try again.');
Logger.warn('Attempt to delete an earlier request before 15 minutes failed. Will try again.');
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/accounts/src/contract.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getTransactionLastResult } from '@near-js/utils';
import { getTransactionLastResult, Logger } from '@near-js/utils';
import { ArgumentTypeError, PositionalArgsError } from '@near-js/types';
import { LocalViewExecution } from './local-view-execution';
import Ajv from 'ajv';
Expand Down Expand Up @@ -194,8 +194,8 @@ export class Contract {
...options,
});
} catch (error) {
console.warn(`Local view execution failed with: "${error.message}"`);
console.warn(`Fallback to normal RPC call`);
Logger.warn(`Local view execution failed with: "${error.message}"`);
Logger.warn(`Fallback to normal RPC call`);
}
}

Expand Down
41 changes: 23 additions & 18 deletions packages/accounts/test/account.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { getTransactionLastResult } = require('@near-js/utils');
const { getTransactionLastResult, Logger } = require('@near-js/utils');
const { actionCreators } = require('@near-js/transactions');
const { TypedError } = require('@near-js/types');
const BN = require('bn.js');
Expand Down Expand Up @@ -90,19 +90,23 @@ test('findAccessKey returns the same access key when fetched simultaneously', as
});

describe('errors', () => {
let oldLog;
let logs;

beforeEach(async () => {
oldLog = console.log;
logs = [];
console.log = function () {
logs.push(Array.from(arguments).join(' '));
beforeAll(async () => {
const custom = {
log: (...args) => {
logs.push(args.join(' '));
},
warn: () => {},
error: () => {},
};

Logger.overrideLogger(custom);
});

afterEach(async () => {
console.log = oldLog;
beforeEach(async () => {
logs = [];

});

test('create existing account', async() => {
Expand All @@ -112,7 +116,6 @@ describe('errors', () => {
});

describe('with deploy contract', () => {
let oldLog;
let logs;
let contractId = testUtils.generateUniqueString('test_contract');
let contract;
Expand All @@ -125,18 +128,20 @@ describe('with deploy contract', () => {
viewMethods: ['hello', 'getValue', 'returnHiWithLogs'],
changeMethods: ['setValue', 'generateLogs', 'triggerAssert', 'testSetRemove', 'crossContract']
});
});

beforeEach(async () => {
oldLog = console.log;
logs = [];
console.log = function () {
logs.push(Array.from(arguments).join(' '));
const custom = {
log: (...args) => {
logs.push(args.join(' '));
},
warn: () => {},
error: () => {},
};

Logger.overrideLogger(custom);
});

afterEach(async () => {
console.log = oldLog;
beforeEach(async () => {
logs = [];
});

test('cross-contact assertion and panic', async () => {
Expand Down
24 changes: 19 additions & 5 deletions packages/near-api-js/src/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,21 @@
* })
* }
* ```
* @example disable library logs
* ```js
* async function initNear() {
* const near = await connect({
* networkId: 'testnet',
* nodeUrl: 'https://rpc.testnet.near.org',
* logger: false
* })
* }
* @module connect
*/
import { readKeyFile } from './key_stores/unencrypted_file_system_keystore';
import { InMemoryKeyStore, MergeKeyStore } from './key_stores';
import { Near, NearConfig } from './near';
import { logWarning } from './utils';
import { Logger } from '@near-js/utils';

export interface ConnectConfig extends NearConfig {
/**
Expand All @@ -38,6 +47,13 @@ export interface ConnectConfig extends NearConfig {
* Initialize connection to Near network.
*/
export async function connect(config: ConnectConfig): Promise<Near> {
if (config.logger === false) {
// disables logging
Logger.overrideLogger(undefined);
} else if (config.logger !== undefined && config.logger !== null) {
Logger.overrideLogger(config.logger);
}

// Try to find extra key in `KeyPath` if provided.
if (config.keyPath && (config.keyStore || config.deps?.keyStore)) {
try {
Expand All @@ -54,12 +70,10 @@ export async function connect(config: ConnectConfig): Promise<Near> {
keyPathStore,
config.keyStore || config.deps?.keyStore
], { writeKeyStoreIndex: 1 });
if (!(typeof process === 'object' && process.env['NEAR_NO_LOGS'])) {
console.log(`Loaded master account ${accountKeyFile[0]} key from ${config.keyPath} with public key = ${keyPair.getPublicKey()}`);
}
Logger.log(`Loaded master account ${accountKeyFile[0]} key from ${config.keyPath} with public key = ${keyPair.getPublicKey()}`);
}
} catch (error) {
logWarning(`Failed to load master account key from ${config.keyPath}: ${error}`);
Logger.warn(`Failed to load master account key from ${config.keyPath}: ${error}`);
}
}
return new Near(config);
Expand Down
2 changes: 2 additions & 0 deletions packages/near-api-js/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as rpc_errors from './rpc_errors';

import { PublicKey, KeyPair, KeyPairEd25519 } from './key_pair';
import { logWarning } from './errors';
import { Logger } from './logger';

export {
key_pair,
Expand All @@ -20,4 +21,5 @@ export {
KeyPairEd25519,
rpc_errors,
logWarning,
Logger
};
1 change: 1 addition & 0 deletions packages/near-api-js/src/utils/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Logger } from '@near-js/utils';
9 changes: 4 additions & 5 deletions packages/providers/src/fetch_json.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { TypedError } from '@near-js/types';
import { Logger } from '@near-js/utils';
import createError from 'http-errors';

import { exponentialBackoff } from './exponential-backoff';
Expand All @@ -16,8 +17,6 @@ export interface ConnectionInfo {
headers?: { [key: string]: string | number };
}

const logWarning = (...args) => !(typeof process === 'object' && process.env['NEAR_NO_LOGS']) && console.warn(...args);

export async function fetchJson(connectionInfoOrUrl: string | ConnectionInfo, json?: string): Promise<any> {
let connectionInfo: ConnectionInfo = { url: null };
if (typeof (connectionInfoOrUrl) === 'string') {
Expand All @@ -36,18 +35,18 @@ export async function fetchJson(connectionInfoOrUrl: string | ConnectionInfo, js
});
if (!response.ok) {
if (response.status === 503) {
logWarning(`Retrying HTTP request for ${connectionInfo.url} as it's not available now`);
Logger.warn(`Retrying HTTP request for ${connectionInfo.url} as it's not available now`);
return null;
} else if (response.status === 408) {
logWarning(`Retrying HTTP request for ${connectionInfo.url} as the previous connection was unused for some time`);
Logger.warn(`Retrying HTTP request for ${connectionInfo.url} as the previous connection was unused for some time`);
return null;
}
throw createError(response.status, await response.text());
}
return response;
} catch (error) {
if (error.toString().includes('FetchError') || error.toString().includes('Failed to fetch')) {
logWarning(`Retrying HTTP request for ${connectionInfo.url} because of error: ${error}`);
Logger.warn(`Retrying HTTP request for ${connectionInfo.url} because of error: ${error}`);
return null;
}
throw error;
Expand Down
5 changes: 2 additions & 3 deletions packages/providers/src/json-rpc-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import {
baseEncode,
getErrorTypeFromErrorMessage,
Logger,
parseRpcError,
} from '@near-js/utils';
import {
Expand Down Expand Up @@ -372,9 +373,7 @@ export class JsonRpcProvider extends Provider {
return response;
} catch (error) {
if (error.type === 'TimeoutError') {
if (!(typeof process === 'object' && process.env['NEAR_NO_LOGS'])) {
console.warn(`Retrying request to ${method} as it has timed out`, params);
}
Logger.warn(`Retrying request to ${method} as it has timed out`, params);
return null;
}

Expand Down
8 changes: 5 additions & 3 deletions packages/utils/src/errors/errors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Logger } from '../logger';

/** @deprecated */
export function logWarning(...args: any[]): void {
if (!(typeof process === 'object' && process.env['NEAR_NO_LOGS'])){
console.warn(...args);
}
const [message, ...optinalParams] = args;
Logger.warn(message, ...optinalParams);
}
1 change: 1 addition & 0 deletions packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './format';
export * from './logging';
export * from './provider';
export * from './validators';
export * from './logger';
Loading