Skip to content
24 changes: 11 additions & 13 deletions packages/relay/src/lib/clients/cache/localLRUCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,10 @@
const cache = this.getCacheInstance(key);
const value = cache.get(prefixedKey);
if (value !== undefined) {
const censoredKey = key.replace(Utils.IP_ADDRESS_REGEX, '<REDACTED>');
const censoredValue = JSON.stringify(value).replace(/"ipAddress":"[^"]+"/, '"ipAddress":"<REDACTED>"');
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`Returning cached value ${censoredKey}:${censoredValue} on ${callingMethod} call`);
const censoredKey = key.replace(Utils.IP_ADDRESS_REGEX, '<REDACTED>');
const censoredValue = JSON.stringify(value).replace(/"ipAddress":"[^"]+"/, '"ipAddress":"<REDACTED>"');
this.logger.trace('Returning cached value %s:%s on %s call', censoredKey, censoredValue, callingMethod);

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
}
return value;
}
Expand All @@ -144,9 +144,8 @@
const prefixedKey = this.prefixKey(key);
const cache = this.getCacheInstance(key);
const remainingTtl = cache.getRemainingTTL(prefixedKey); // in milliseconds
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`returning remaining TTL ${key}:${remainingTtl} on ${callingMethod} call`);
}
this.logger.trace(`returning remaining TTL %s:%s on %s call`, key, remainingTtl, callingMethod);

return remainingTtl;
}

Expand All @@ -173,7 +172,7 @@
const message = `Caching ${censoredKey}:${censoredValue} on ${callingMethod} for ${
resolvedTtl > 0 ? `${resolvedTtl} ms` : 'indefinite time'
}`;
this.logger.trace(`${message} (cache size: ${this.cache.size}, max: ${this.options.max})`);
this.logger.trace(`%s (cache size: %s, max: %s)`, message, this.cache.size, this.options.max);

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
}
}

Expand Down Expand Up @@ -214,9 +213,9 @@
*/
public async delete(key: string, callingMethod: string): Promise<void> {
const prefixedKey = this.prefixKey(key);
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`delete cache for ${key} on ${callingMethod} call`);
}

this.logger.trace(`delete cache for %s on %s call`, key, callingMethod);

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.

const cache = this.getCacheInstance(key);
cache.delete(prefixedKey);
}
Expand Down Expand Up @@ -275,9 +274,8 @@

const matchingKeys = keys.filter((key) => regex.test(key));

if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`retrieving keys matching ${pattern} on ${callingMethod} call`);
}
this.logger.trace(`retrieving keys matching %s on %s call`, pattern, callingMethod);

// Remove the prefix from the returned keys
return matchingKeys.map((key) => key.substring(LocalLRUCache.CACHE_KEY_PREFIX.length));
}
Expand Down
55 changes: 25 additions & 30 deletions packages/relay/src/lib/clients/cache/redisCache/redisCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export class RedisCache implements ICacheClient {
if (this.logger.isLevelEnabled('trace')) {
const censoredKey = key.replace(Utils.IP_ADDRESS_REGEX, '<REDACTED>');
const censoredValue = result.replace(/"ipAddress":"[^"]+"/, '"ipAddress":"<REDACTED>"');
this.logger.trace(`Returning cached value ${censoredKey}:${censoredValue} on ${callingMethod} call`);
this.logger.trace(`Returning cached value %s:%s on %s call`, censoredKey, censoredValue, callingMethod);
}
// TODO: add metrics
return JSON.parse(result);
Expand All @@ -106,13 +106,13 @@ export class RedisCache implements ICacheClient {
await this.client.set(prefixedKey, serializedValue);
}

const censoredKey = key.replace(Utils.IP_ADDRESS_REGEX, '<REDACTED>');
const censoredValue = serializedValue.replace(/"ipAddress":"[^"]+"/, '"ipAddress":"<REDACTED>"');
const message = `Caching ${censoredKey}:${censoredValue} on ${callingMethod} for ${
resolvedTtl > 0 ? `${resolvedTtl} ms` : 'indefinite time'
}`;
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`${message}`);
const censoredKey = key.replace(Utils.IP_ADDRESS_REGEX, '<REDACTED>');
const censoredValue = serializedValue.replace(/"ipAddress":"[^"]+"/, '"ipAddress":"<REDACTED>"');
const message = `Caching ${censoredKey}:${censoredValue} on ${callingMethod} for ${
resolvedTtl > 0 ? `${resolvedTtl} ms` : 'indefinite time'
}`;
this.logger.trace(`%s`, message);
}
// TODO: add metrics
}
Expand All @@ -138,9 +138,12 @@ export class RedisCache implements ICacheClient {
await this.client.mSet(serializedKeyValuePairs);

// Log the operation
const entriesLength = Object.keys(keyValuePairs).length;
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`caching multiple keys via ${callingMethod}, total keys: ${entriesLength}`);
this.logger.trace(
`caching multiple keys via %s, total keys: %s`,
callingMethod,
Object.keys(keyValuePairs).length,
);
}
}

Expand All @@ -166,10 +169,13 @@ export class RedisCache implements ICacheClient {
// Execute pipeline operation
await pipeline.execAsPipeline();

// Log the operation
if (this.logger.isLevelEnabled('trace')) {
// Log the operation
const entriesLength = Object.keys(keyValuePairs).length;
this.logger.trace(`caching multiple keys via ${callingMethod}, total keys: ${entriesLength}`);
this.logger.trace(
`caching multiple keys via %s, total keys: %s`,
callingMethod,
Object.keys(keyValuePairs).length,
);
}
}

Expand All @@ -183,9 +189,7 @@ export class RedisCache implements ICacheClient {
async delete(key: string, callingMethod: string): Promise<void> {
const prefixedKey = this.prefixKey(key);
await this.client.del(prefixedKey);
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`delete cache for ${key} on ${callingMethod} call`);
}
this.logger.trace(`delete cache for %s on %s call`, key, callingMethod);
// TODO: add metrics
}

Expand All @@ -200,9 +204,7 @@ export class RedisCache implements ICacheClient {
async incrBy(key: string, amount: number, callingMethod: string): Promise<number> {
const prefixedKey = this.prefixKey(key);
const result = await this.client.incrBy(prefixedKey, amount);
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`incrementing ${key} by ${amount} on ${callingMethod} call`);
}
this.logger.trace(`incrementing %s by %s on %s call`, key, amount, callingMethod);
return result;
}

Expand All @@ -218,9 +220,7 @@ export class RedisCache implements ICacheClient {
async lRange(key: string, start: number, end: number, callingMethod: string): Promise<any[]> {
const prefixedKey = this.prefixKey(key);
const result = await this.client.lRange(prefixedKey, start, end);
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`retrieving range [${start}:${end}] from ${key} on ${callingMethod} call`);
}
this.logger.trace(`retrieving range [%s:%s] from %s on %s call`, start, end, key, callingMethod);
return result.map((item) => JSON.parse(item));
}

Expand All @@ -236,9 +236,8 @@ export class RedisCache implements ICacheClient {
const prefixedKey = this.prefixKey(key);
const serializedValue = JSON.stringify(value);
const result = await this.client.rPush(prefixedKey, serializedValue);
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`pushing ${serializedValue} to ${key} on ${callingMethod} call`);
}
this.logger.trace(`pushing %s to %s on %s call`, serializedValue, key, callingMethod);

return result;
}

Expand All @@ -251,9 +250,7 @@ export class RedisCache implements ICacheClient {
async keys(pattern: string, callingMethod: string): Promise<string[]> {
const prefixedPattern = this.prefixKey(pattern);
const result = await this.client.keys(prefixedPattern);
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`retrieving keys matching ${pattern} on ${callingMethod} call`);
}
this.logger.trace(`retrieving keys matching %s on %s call`, pattern, callingMethod);
// Remove the prefix from the returned keys
return result.map((key) => key.substring(RedisCache.CACHE_KEY_PREFIX.length));
}
Expand All @@ -277,9 +274,7 @@ export class RedisCache implements ICacheClient {

await pipeline.exec();

if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`Cleared ${keysToDelete.length} cache keys`);
}
this.logger.trace(`Cleared %s cache keys`, keysToDelete.length);
}
}
}
89 changes: 51 additions & 38 deletions packages/relay/src/lib/clients/mirrorNodeClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,9 +224,7 @@
retries: mirrorNodeRetries,
retryDelay: (retryCount, error) => {
const delay = mirrorNodeRetryDelay * retryCount;
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`Retry delay ${delay} ms on '${error?.request?.path}'`);
}
this.logger.trace(`Retry delay %s ms on '%s'`, delay, error?.request?.path);
return delay;
},
retryCondition: (error) => {
Expand Down Expand Up @@ -290,7 +288,9 @@
});

this.logger.info(
`Mirror Node client successfully configured to REST url: ${this.restUrl} and Web3 url: ${this.web3Url} `,
`Mirror Node client successfully configured to REST url: %s and Web3 url: %s `,
this.restUrl,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
this.web3Url,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
);
this.cacheService = cacheService;

Expand Down Expand Up @@ -377,7 +377,7 @@
try {
return JSONBigInt.parse(data);
} catch (error) {
this.logger.warn(`Failed to parse response data from Mirror Node: ${error}`);
this.logger.warn(`Failed to parse response data from Mirror Node: %s`, error);
}
}

Expand All @@ -394,9 +394,12 @@
const ms = Date.now() - start;
if (this.logger.isLevelEnabled('debug')) {
this.logger.debug(
`Successfully received response from mirror node server: method=${method}, path=${path}, status=${
response.status
}, duration:${ms}ms, data:${JSON.stringify(response.data)}`,
`Successfully received response from mirror node server: method=%s, path=%s, status=%s, duration:%sms, data:%s`,
method,
path,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
response.status,
ms,
JSON.stringify(response.data),
);
}
this.mirrorResponseHistogram.labels(pathLabel, response.status?.toString()).observe(ms);
Expand Down Expand Up @@ -451,27 +454,35 @@
const acceptedErrorResponses = MirrorNodeClient.acceptedErrorStatusesResponsePerRequestPathMap.get(pathLabel);

if (error.response && acceptedErrorResponses?.includes(effectiveStatusCode)) {
if (this.logger.isLevelEnabled('debug')) {
this.logger.debug(
`An accepted error occurred while communicating with the mirror node server: method=${method}, path=${path}, status=${effectiveStatusCode}`,
);
}
this.logger.debug(
`An accepted error occurred while communicating with the mirror node server: method=%s, path=%s, status=%s}`,
method,
path,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
effectiveStatusCode,
);
return null;
}

// Contract Call returns 400 for a CONTRACT_REVERT but is a valid response, expected and should not be logged as error:
if (pathLabel === MirrorNodeClient.CONTRACT_CALL_ENDPOINT && effectiveStatusCode === 400) {
if (this.logger.isLevelEnabled('debug')) {
this.logger.debug(
`[${method}] ${path} Contract Revert: ( StatusCode: '${effectiveStatusCode}', StatusText: '${
error.response.statusText
}', Detail: '${JSON.stringify(error.response.detail)}',Data: '${JSON.stringify(error.response.data)}')`,
`[%s] %s Contract Revert: ( StatusCode: '%s', StatusText: '%s', Detail: '%s',Data: '%s')`,
method,
path,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
effectiveStatusCode,
error.response.statusText,
JSON.stringify(error.response.detail),
JSON.stringify(error.response.data),
);
}
} else {
this.logger.error(
new Error(error.message),
`Error encountered while communicating with the mirror node server: method=${method}, path=${path}, status=${effectiveStatusCode}`,
`Error encountered while communicating with the mirror node server: method=%s, path=%s, status=%s`,
method,
path,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
effectiveStatusCode,
);
}

Expand All @@ -496,9 +507,7 @@

if (page === pageMax) {
// max page reached
if (this.logger.isLevelEnabled('trace')) {
this.logger.trace(`Max page reached ${pageMax} with ${results.length} results`);
}
this.logger.trace(`Max page reached %s with %s results`, pageMax, results.length);
throw predefined.PAGINATION_MAX(pageMax);
}

Expand Down Expand Up @@ -575,15 +584,15 @@
const match = url.match(regex);
const accountId = match ? match[1] : null;
if (!accountId) {
this.logger.error(`Unable to extract evm address from url ${url}`);
this.logger.error(`Unable to extract evm address from url %s`, url);
}
return String(accountId);
} else {
// account id
const match = url.match(MirrorNodeClient.EVM_ADDRESS_REGEX);
const accountId = match ? match[1] : null;
if (!accountId) {
this.logger.error(`Unable to extract account ID from url ${url}`);
this.logger.error(`Unable to extract account ID from url %s`, url);
}
return String(accountId);
}
Expand Down Expand Up @@ -802,9 +811,9 @@
// Found immature record, log the info, set flag and exit record traversal
if (this.logger.isLevelEnabled('debug')) {
this.logger.debug(
`Contract result contains nullable transaction_index or block_number, or block_hash is an empty hex (0x): contract_result=${JSON.stringify(
contractObject,
)}. ${!isLastAttempt ? `Retrying after a delay of ${mirrorNodeRetryDelay} ms.` : ``}`,
`Contract result contains nullable transaction_index or block_number, or block_hash is an empty hex (0x): contract_result=%s. %s}`,
JSON.stringify(contractObject),
!isLastAttempt ? `Retrying after a delay of ${mirrorNodeRetryDelay} ms.` : ``,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
);
}

Expand Down Expand Up @@ -991,9 +1000,9 @@
// Found immature record, log the info, set flag and exit record traversal
if (this.logger.isLevelEnabled('debug')) {
this.logger.debug(
`Contract result log contains nullable transaction_index, block_number, index, or block_hash is an empty hex (0x): log=${JSON.stringify(
log,
)}. ${!isLastAttempt ? `Retrying after a delay of ${mirrorNodeRetryDelay} ms.` : ``}`,
`Contract result log contains nullable transaction_index, block_number, index, or block_hash is an empty hex (0x): log=%s. %s`,
JSON.stringify(log),
!isLastAttempt ? `Retrying after a delay of ${mirrorNodeRetryDelay} ms.` : ``,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
);
}

Expand Down Expand Up @@ -1484,7 +1493,9 @@
} else {
this.logger.warn(
e,
`Error raised during polling mirror node for updated records: method=${methodName}, args=${args}`,
`Error raised during polling mirror node for updated records: method=%s, args=%s`,
methodName,
args,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
);
}
}
Expand All @@ -1495,9 +1506,12 @@

if (this.logger.isLevelEnabled('debug')) {
this.logger.debug(
`Repeating request ${methodName} with args ${JSON.stringify(
args,
)} retry count ${i} of ${repeatCount}. Waiting ${this.MIRROR_NODE_RETRY_DELAY} ms before repeating request`,
`Repeating request %s with args %s retry count %s of %s. Waiting %s ms before repeating request`,
methodName,
JSON.stringify(args),

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
i,
repeatCount,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
this.MIRROR_NODE_RETRY_DELAY,

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information High

This logs sensitive data returned by
process environment
as clear text.
);
}

Expand All @@ -1523,12 +1537,11 @@
operatorAccountId: string,
requestDetails: RequestDetails,
): Promise<ITransactionRecordMetric> {
if (this.logger.isLevelEnabled('debug')) {
this.logger.debug(
`Get transaction record via mirror node: transactionId=${transactionId}, txConstructorName=${txConstructorName}`,
);
}

this.logger.debug(
`Get transaction record via mirror node: transactionId=%s, txConstructorName=%s`,
transactionId,
txConstructorName,
);
// Create a modified copy of requestDetails
const modifiedRequestDetails = new RequestDetails({
requestId: requestDetails.requestId,
Expand Down
Loading
Loading