Log GQL requests in watcher (#517)

* Update config for server GQL

* Add winston logger for GQL requests

* Fix codegen templates for resolver and package

* Update package versions

---------

Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
This commit is contained in:
Nabarun Gogoi 2024-06-06 16:54:49 +05:30 committed by GitHub
parent 836fe45aa5
commit 8d052add2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 379 additions and 101 deletions

View File

@ -2,7 +2,7 @@
"packages": [
"packages/*"
],
"version": "0.2.93",
"version": "0.2.94",
"npmClient": "yarn",
"useWorkspaces": true,
"command": {

View File

@ -1,6 +1,6 @@
{
"name": "@cerc-io/cache",
"version": "0.2.93",
"version": "0.2.94",
"description": "Generic object cache",
"main": "dist/index.js",
"scripts": {

View File

@ -1,6 +1,6 @@
{
"name": "@cerc-io/cli",
"version": "0.2.93",
"version": "0.2.94",
"main": "dist/index.js",
"license": "AGPL-3.0",
"scripts": {
@ -15,13 +15,13 @@
},
"dependencies": {
"@apollo/client": "^3.7.1",
"@cerc-io/cache": "^0.2.93",
"@cerc-io/ipld-eth-client": "^0.2.93",
"@cerc-io/cache": "^0.2.94",
"@cerc-io/ipld-eth-client": "^0.2.94",
"@cerc-io/libp2p": "^0.42.2-laconic-0.1.4",
"@cerc-io/nitro-node": "^0.1.15",
"@cerc-io/peer": "^0.2.93",
"@cerc-io/rpc-eth-client": "^0.2.93",
"@cerc-io/util": "^0.2.93",
"@cerc-io/peer": "^0.2.94",
"@cerc-io/rpc-eth-client": "^0.2.94",
"@cerc-io/util": "^0.2.94",
"@ethersproject/providers": "^5.4.4",
"@graphql-tools/utils": "^9.1.1",
"@ipld/dag-cbor": "^8.0.0",

View File

@ -11,6 +11,7 @@ import assert from 'assert';
import { ConnectionOptions } from 'typeorm';
import express, { Application } from 'express';
import { ApolloServer } from 'apollo-server-express';
import winston from 'winston';
import { JsonRpcProvider } from '@ethersproject/providers';
import {
@ -30,7 +31,8 @@ import {
Consensus,
readParty,
UpstreamConfig,
fillBlocks
fillBlocks,
createGQLLogger
} from '@cerc-io/util';
import { TypeSource } from '@graphql-tools/utils';
import type {
@ -268,7 +270,11 @@ export class ServerCmd {
}
async exec (
createResolvers: (indexer: IndexerInterface, eventWatcher: EventWatcher) => Promise<any>,
createResolvers: (
indexer: IndexerInterface,
eventWatcher: EventWatcher,
gqlLogger: winston.Logger
) => Promise<any>,
typeDefs: TypeSource,
paymentsManager?: PaymentsManager
): Promise<{
@ -308,7 +314,8 @@ export class ServerCmd {
await eventWatcher.start();
}
const resolvers = await createResolvers(indexer, eventWatcher);
const gqlLogger = createGQLLogger(config.server.gql.logDir);
const resolvers = await createResolvers(indexer, eventWatcher, gqlLogger);
// Create an Express app
const app: Application = express();

View File

@ -1,6 +1,6 @@
{
"name": "@cerc-io/codegen",
"version": "0.2.93",
"version": "0.2.94",
"description": "Code generator",
"private": true,
"main": "index.js",
@ -20,7 +20,7 @@
},
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
"dependencies": {
"@cerc-io/util": "^0.2.93",
"@cerc-io/util": "^0.2.94",
"@graphql-tools/load-files": "^6.5.2",
"@npmcli/package-json": "^5.0.0",
"@poanet/solidity-flattener": "https://github.com/vulcanize/solidity-flattener.git",

View File

@ -4,3 +4,5 @@ out/
.vscode
.idea
gql-logs/

View File

@ -2,7 +2,6 @@
host = "127.0.0.1"
port = {{port}}
kind = "{{watcherKind}}"
gqlPath = "/graphql"
# Checkpointing state.
checkpointing = true
@ -24,25 +23,32 @@
clearEntitiesCacheInterval = 1000
{{/if}}
# Max block range for which to return events in eventsInRange GQL query.
# Use -1 for skipping check on block range.
maxEventsBlockRange = 1000
# Flag to specify whether RPC endpoint supports block hash as block tag parameter
rpcSupportsBlockHashParam = true
# GQL cache settings
[server.gqlCache]
enabled = true
# Server GQL config
[server.gql]
path = "/graphql"
# Max in-memory cache size (in bytes) (default 8 MB)
# maxCacheSize
# Max block range for which to return events in eventsInRange GQL query.
# Use -1 for skipping check on block range.
maxEventsBlockRange = 1000
# GQL cache-control max-age settings (in seconds)
maxAge = 15
{{#if (subgraphPath)}}
timeTravelMaxAge = 86400 # 1 day
{{/if}}
# Log directory for GQL requests
logDir = "./gql-logs"
# GQL cache settings
[server.gql.cache]
enabled = true
# Max in-memory cache size (in bytes) (default 8 MB)
# maxCacheSize
# GQL cache-control max-age settings (in seconds)
maxAge = 15
{{#if (subgraphPath)}}
timeTravelMaxAge = 86400 # 1 day
{{/if}}
[metrics]
host = "127.0.0.1"

View File

@ -660,7 +660,7 @@ export class Indexer implements IndexerInterface {
}
async getEventsInRange (fromBlockNumber: number, toBlockNumber: number): Promise<Array<Event>> {
return this._baseIndexer.getEventsInRange(fromBlockNumber, toBlockNumber, this._serverConfig.maxEventsBlockRange);
return this._baseIndexer.getEventsInRange(fromBlockNumber, toBlockNumber, this._serverConfig.gql.maxEventsBlockRange);
}
async getSyncStatus (): Promise<SyncStatus | undefined> {

View File

@ -41,12 +41,12 @@
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
"dependencies": {
"@apollo/client": "^3.3.19",
"@cerc-io/cli": "^0.2.93",
"@cerc-io/ipld-eth-client": "^0.2.93",
"@cerc-io/solidity-mapper": "^0.2.93",
"@cerc-io/util": "^0.2.93",
"@cerc-io/cli": "^0.2.94",
"@cerc-io/ipld-eth-client": "^0.2.94",
"@cerc-io/solidity-mapper": "^0.2.94",
"@cerc-io/util": "^0.2.94",
{{#if (subgraphPath)}}
"@cerc-io/graph-node": "^0.2.93",
"@cerc-io/graph-node": "^0.2.94",
{{/if}}
"@ethersproject/providers": "^5.4.4",
"debug": "^4.3.1",
@ -75,6 +75,7 @@
"eslint-plugin-standard": "^5.0.0",
"husky": "^7.0.2",
"ts-node": "^10.2.1",
"typescript": "^5.0.2"
"typescript": "^5.0.2",
"winston": "^3.13.0"
}
}

View File

@ -63,7 +63,7 @@
To enable GQL requests caching:
* Update the `server.gqlCache` config with required settings.
* Update the `server.gql.cache` config with required settings.
* In the GQL [schema file](./src/schema.gql), use the `cacheControl` directive to apply cache hints at schema level.

View File

@ -5,6 +5,8 @@
import assert from 'assert';
import debug from 'debug';
import { GraphQLResolveInfo } from 'graphql';
import { ExpressContext } from 'apollo-server-express';
import winston from 'winston';
import {
{{#if queries}}
@ -37,25 +39,57 @@ import { {{query.entityName}} } from './entity/{{query.entityName}}';
const log = debug('vulcanize:resolver');
const executeAndRecordMetrics = async (gqlLabel: string, operation: () => Promise<any>) => {
const executeAndRecordMetrics = async (
indexer: Indexer,
gqlLogger: winston.Logger,
opName: string,
expressContext: ExpressContext,
operation: () => Promise<any>
) => {
gqlTotalQueryCount.inc(1);
gqlQueryCount.labels(gqlLabel).inc(1);
const endTimer = gqlQueryDuration.labels(gqlLabel).startTimer();
gqlQueryCount.labels(opName).inc(1);
const endTimer = gqlQueryDuration.labels(opName).startTimer();
try {
const result = await operation();
const [result, syncStatus] = await Promise.all([
operation(),
indexer.getSyncStatus()
]);
gqlLogger.info({
opName,
query: expressContext.req.body.query,
variables: expressContext.req.body.variables,
latestIndexedBlockNumber: syncStatus?.latestIndexedBlockNumber,
urlPath: expressContext.req.path,
apiKey: expressContext.req.header('x-api-key'),
origin: expressContext.req.headers.origin
});
return result;
} catch (error) {
gqlLogger.error({
opName,
error,
query: expressContext.req.body.query,
variables: expressContext.req.body.variables,
urlPath: expressContext.req.path,
apiKey: expressContext.req.header('x-api-key'),
origin: expressContext.req.headers.origin
});
} finally {
endTimer();
}
};
export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher: EventWatcher): Promise<any> => {
export const createResolvers = async (
indexerArg: IndexerInterface,
eventWatcher: EventWatcher,
gqlLogger: winston.Logger
): Promise<any> => {
const indexer = indexerArg as Indexer;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const gqlCacheConfig = indexer.serverConfig.gqlCache;
const gqlCacheConfig = indexer.serverConfig.gql.cache;
return {
BigInt: GraphQLBigInt,
@ -93,7 +127,7 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
{{~#each this.params}}, {{this.name~}} {{/each}} }: { blockHash: string, contractAddress: string
{{~#each this.params}}, {{this.name}}: {{this.type~}} {{/each}} },
// eslint-disable-next-line @typescript-eslint/no-unused-vars
__: any,
expressContext: ExpressContext,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
info: GraphQLResolveInfo
): Promise<ValueResult> => {
@ -104,7 +138,10 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
// setGQLCacheHints(info, {}, gqlCacheConfig);
return executeAndRecordMetrics(
indexer,
gqlLogger,
'{{this.name}}',
expressContext,
async () => indexer.{{this.name}}(blockHash, contractAddress
{{~#each this.params}}, {{this.name~}} {{/each}})
);
@ -116,7 +153,7 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
{{this.queryName}}: async (
_: any,
{ id, block = {} }: { id: string, block: BlockHeight },
__: any,
expressContext: ExpressContext,
info: GraphQLResolveInfo
) => {
log('{{this.queryName}}', id, JSON.stringify(block, jsonBigIntStringReplacer));
@ -125,7 +162,10 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
// setGQLCacheHints(info, block, gqlCacheConfig);
return executeAndRecordMetrics(
indexer,
gqlLogger,
'{{this.queryName}}',
expressContext,
async () => indexer.getSubgraphEntity({{this.entityName}}, id, block, info)
);
},
@ -133,7 +173,7 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
{{this.pluralQueryName}}: async (
_: any,
{ block = {}, where, first, skip, orderBy, orderDirection }: { block: BlockHeight, where: { [key: string]: any }, first: number, skip: number, orderBy: string, orderDirection: OrderDirection },
__: any,
expressContext: ExpressContext,
info: GraphQLResolveInfo
) => {
log('{{this.pluralQueryName}}', JSON.stringify(block, jsonBigIntStringReplacer), JSON.stringify(where, jsonBigIntStringReplacer), first, skip, orderBy, orderDirection);
@ -142,7 +182,10 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
// setGQLCacheHints(info, block, gqlCacheConfig);
return executeAndRecordMetrics(
indexer,
gqlLogger,
'{{this.pluralQueryName}}',
expressContext,
async () => indexer.getSubgraphEntities(
{{this.entityName}},
block,
@ -154,11 +197,18 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
},
{{/each}}
events: async (_: any, { blockHash, contractAddress, name }: { blockHash: string, contractAddress: string, name?: string }) => {
events: async (
_: any,
{ blockHash, contractAddress, name }: { blockHash: string, contractAddress: string, name?: string },
expressContext: ExpressContext
) => {
log('events', blockHash, contractAddress, name);
return executeAndRecordMetrics(
indexer,
gqlLogger,
'events',
expressContext,
async () => {
const block = await indexer.getBlockProgress(blockHash);
if (!block || !block.isComplete) {
@ -171,11 +221,18 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
);
},
eventsInRange: async (_: any, { fromBlockNumber, toBlockNumber }: { fromBlockNumber: number, toBlockNumber: number }) => {
eventsInRange: async (
_: any,
{ fromBlockNumber, toBlockNumber }: { fromBlockNumber: number, toBlockNumber: number },
expressContext: ExpressContext
) => {
log('eventsInRange', fromBlockNumber, toBlockNumber);
return executeAndRecordMetrics(
indexer,
gqlLogger,
'eventsInRange',
expressContext,
async () => {
const syncStatus = await indexer.getSyncStatus();
@ -193,11 +250,18 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
);
},
getStateByCID: async (_: any, { cid }: { cid: string }) => {
getStateByCID: async (
_: any,
{ cid }: { cid: string },
expressContext: ExpressContext
) => {
log('getStateByCID', cid);
return executeAndRecordMetrics(
indexer,
gqlLogger,
'getStateByCID',
expressContext,
async () => {
const state = await indexer.getStateByCID(cid);
@ -206,11 +270,18 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
);
},
getState: async (_: any, { blockHash, contractAddress, kind }: { blockHash: string, contractAddress: string, kind: string }) => {
getState: async (
_: any,
{ blockHash, contractAddress, kind }: { blockHash: string, contractAddress: string, kind: string },
expressContext: ExpressContext
) => {
log('getState', blockHash, contractAddress, kind);
return executeAndRecordMetrics(
indexer,
gqlLogger,
'getState',
expressContext,
async () => {
const state = await indexer.getPrevState(blockHash, contractAddress, kind);
@ -222,22 +293,33 @@ export const createResolvers = async (indexerArg: IndexerInterface, eventWatcher
_meta: async (
_: any,
{ block = {} }: { block: BlockHeight }
{ block = {} }: { block: BlockHeight },
expressContext: ExpressContext
) => {
log('_meta');
return executeAndRecordMetrics(
indexer,
gqlLogger,
'_meta',
expressContext,
async () => indexer.getMetaData(block)
);
},
{{/if}}
getSyncStatus: async () => {
getSyncStatus: async (
_: any,
__: Record<string, never>,
expressContext: ExpressContext
) => {
log('getSyncStatus');
return executeAndRecordMetrics(
indexer,
gqlLogger,
'getSyncStatus',
expressContext,
async () => indexer.getSyncStatus()
);
}

View File

@ -1,10 +1,10 @@
{
"name": "@cerc-io/graph-node",
"version": "0.2.93",
"version": "0.2.94",
"main": "dist/index.js",
"license": "AGPL-3.0",
"devDependencies": {
"@cerc-io/solidity-mapper": "^0.2.93",
"@cerc-io/solidity-mapper": "^0.2.94",
"@ethersproject/providers": "^5.4.4",
"@graphprotocol/graph-ts": "^0.22.0",
"@nomiclabs/hardhat-ethers": "^2.0.2",
@ -51,9 +51,9 @@
"dependencies": {
"@apollo/client": "^3.3.19",
"@cerc-io/assemblyscript": "0.19.10-watcher-ts-0.1.2",
"@cerc-io/cache": "^0.2.93",
"@cerc-io/ipld-eth-client": "^0.2.93",
"@cerc-io/util": "^0.2.93",
"@cerc-io/cache": "^0.2.94",
"@cerc-io/ipld-eth-client": "^0.2.94",
"@cerc-io/util": "^0.2.94",
"@types/json-diff": "^0.5.2",
"@types/yargs": "^17.0.0",
"bn.js": "^4.11.9",

View File

@ -1,6 +1,6 @@
{
"name": "@cerc-io/ipld-eth-client",
"version": "0.2.93",
"version": "0.2.94",
"description": "IPLD ETH Client",
"main": "dist/index.js",
"scripts": {
@ -20,8 +20,8 @@
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
"dependencies": {
"@apollo/client": "^3.7.1",
"@cerc-io/cache": "^0.2.93",
"@cerc-io/util": "^0.2.93",
"@cerc-io/cache": "^0.2.94",
"@cerc-io/util": "^0.2.94",
"cross-fetch": "^3.1.4",
"debug": "^4.3.1",
"ethers": "^5.4.4",

View File

@ -1,6 +1,6 @@
{
"name": "@cerc-io/peer",
"version": "0.2.93",
"version": "0.2.94",
"description": "libp2p module",
"main": "dist/index.js",
"exports": "./dist/index.js",

View File

@ -1,6 +1,6 @@
{
"name": "@cerc-io/rpc-eth-client",
"version": "0.2.93",
"version": "0.2.94",
"description": "RPC ETH Client",
"main": "dist/index.js",
"scripts": {
@ -19,9 +19,9 @@
},
"homepage": "https://github.com/cerc-io/watcher-ts#readme",
"dependencies": {
"@cerc-io/cache": "^0.2.93",
"@cerc-io/ipld-eth-client": "^0.2.93",
"@cerc-io/util": "^0.2.93",
"@cerc-io/cache": "^0.2.94",
"@cerc-io/ipld-eth-client": "^0.2.94",
"@cerc-io/util": "^0.2.94",
"chai": "^4.3.4",
"ethers": "^5.4.4",
"left-pad": "^1.3.0",

View File

@ -1,6 +1,6 @@
{
"name": "@cerc-io/solidity-mapper",
"version": "0.2.93",
"version": "0.2.94",
"main": "dist/index.js",
"license": "AGPL-3.0",
"devDependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "@cerc-io/test",
"version": "0.2.93",
"version": "0.2.94",
"main": "dist/index.js",
"license": "AGPL-3.0",
"private": true,

View File

@ -1,6 +1,6 @@
{
"name": "@cerc-io/tracing-client",
"version": "0.2.93",
"version": "0.2.94",
"description": "ETH VM tracing client",
"main": "dist/index.js",
"scripts": {

View File

@ -1,13 +1,13 @@
{
"name": "@cerc-io/util",
"version": "0.2.93",
"version": "0.2.94",
"main": "dist/index.js",
"license": "AGPL-3.0",
"dependencies": {
"@apollo/utils.keyvaluecache": "^1.0.1",
"@cerc-io/nitro-node": "^0.1.15",
"@cerc-io/peer": "^0.2.93",
"@cerc-io/solidity-mapper": "^0.2.93",
"@cerc-io/peer": "^0.2.94",
"@cerc-io/solidity-mapper": "^0.2.94",
"@cerc-io/ts-channel": "1.0.3-ts-nitro-0.1.1",
"@ethersproject/properties": "^5.7.0",
"@ethersproject/providers": "^5.4.4",
@ -49,11 +49,12 @@
"toml": "^3.0.0",
"typeorm": "0.2.37",
"typeorm-naming-strategies": "^2.0.0",
"winston": "^3.13.0",
"ws": "^8.11.0",
"yargs": "^17.0.1"
},
"devDependencies": {
"@cerc-io/cache": "^0.2.93",
"@cerc-io/cache": "^0.2.94",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@types/bunyan": "^1.8.8",
"@types/express": "^4.17.14",

View File

@ -203,23 +203,16 @@ export interface P2PConfig {
consensus: ConsensusConfig;
}
export interface ServerConfig {
host: string;
port: number;
mode: string;
gqlPath: string;
kind: string;
enableConfigValidation: boolean;
checkpointing: boolean;
checkpointInterval: number;
subgraphPath: string;
enableState: boolean;
wasmRestartBlocksInterval: number;
// GQL config
export interface GQLConfig {
path: string;
maxEventsBlockRange: number;
clearEntitiesCacheInterval: number;
// Boolean to skip updating entity fields required in state creation and not required in the frontend
skipStateFieldsUpdate: boolean;
// GQL cache-control max-age settings (in seconds)
cache: GQLCacheConfig;
// Boolean to load GQL query nested entity relations sequentially
loadRelationsSequential: boolean;
// Max GQL API requests to process simultaneously (defaults to 1)
maxSimultaneousRequests?: number;
@ -227,11 +220,28 @@ export interface ServerConfig {
// Max GQL API requests in queue until reject (defaults to -1, means do not reject)
maxRequestQueueLimit?: number;
// Boolean to load GQL query nested entity relations sequentially
loadRelationsSequential: boolean;
// Log directory for GQL requests
logDir?: string;
}
// GQL cache-control max-age settings (in seconds)
gqlCache: GQLCacheConfig;
export interface ServerConfig {
host: string;
port: number;
mode: string;
kind: string;
enableConfigValidation: boolean;
checkpointing: boolean;
checkpointInterval: number;
subgraphPath: string;
enableState: boolean;
wasmRestartBlocksInterval: number;
clearEntitiesCacheInterval: number;
// Boolean to skip updating entity fields required in state creation and not required in the frontend
skipStateFieldsUpdate: boolean;
// GQL config for server
gql: GQLConfig
p2p: P2PConfig;

View File

@ -763,7 +763,7 @@ export class GraphDatabase {
const relationSelections = selections.filter((selection) => selection.kind === 'Field' && Boolean(relations[selection.name.value]));
if (this._serverConfig.loadRelationsSequential) {
if (this._serverConfig.gql.loadRelationsSequential) {
for (const selection of relationSelections) {
await this.loadRelation(queryRunner, block, relationsMap, relations, entities, selection, queryInfo);
}

View File

@ -27,3 +27,4 @@ export * from './payments';
export * from './eth';
export * from './consensus';
export * from './validate-config';
export * from './logger';

View File

@ -0,0 +1,18 @@
import winston from 'winston';
import path from 'path';
export const createGQLLogger = (logsDir = ''): winston.Logger => {
return winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
// Write all logs with importance level of `error` or less to `watcher-gql-error.log`
new winston.transports.File({ filename: path.resolve(logsDir, 'watcher-gql-error.log'), level: 'error' }),
// Write all logs with importance level of `info` or less to `watcher-gql.log`
new winston.transports.File({ filename: path.resolve(logsDir, 'watcher-gql.log') })
]
});
};

View File

@ -231,10 +231,10 @@ const registerWatcherConfigMetrics = async ({ server, upstream, jobQueue }: Conf
watcherConfigMetric.set({ category: 'server', field: 'is_active' }, Number(server.kind === 'active'));
watcherConfigMetric.set({ category: 'server', field: 'is_subgraph_watcher' }, Number(server.subgraphPath?.length > 0));
watcherConfigMetric.set({ category: 'server', field: 'max_events_block_range' }, Number(server.maxEventsBlockRange));
watcherConfigMetric.set({ category: 'server', field: 'max_events_block_range' }, Number(server.gql.maxEventsBlockRange));
watcherConfigMetric.set({ category: 'server', field: 'clear_entities_cache_interval' }, Number(server.clearEntitiesCacheInterval));
watcherConfigMetric.set({ category: 'server', field: 'max_simultaneous_requests' }, Number(server.maxSimultaneousRequests));
watcherConfigMetric.set({ category: 'server', field: 'max_request_queue_limit' }, Number(server.maxRequestQueueLimit));
watcherConfigMetric.set({ category: 'server', field: 'max_simultaneous_requests' }, Number(server.gql.maxSimultaneousRequests));
watcherConfigMetric.set({ category: 'server', field: 'max_request_queue_limit' }, Number(server.gql.maxRequestQueueLimit));
watcherConfigMetric.set({ category: 'upstream', field: 'is_using_rpc_client' }, Number(upstream.ethServer.rpcClient));
watcherConfigMetric.set({ category: 'upstream', field: 'is_fevm' }, Number(upstream.ethServer.isFEVM));

View File

@ -1,5 +1,5 @@
import { Application } from 'express';
import { ApolloServer } from 'apollo-server-express';
import { ApolloServer, ExpressContext } from 'apollo-server-express';
import { createServer } from 'http';
import { WebSocketServer } from 'ws';
import { useServer } from 'graphql-ws/lib/use/ws';
@ -33,10 +33,12 @@ export const createAndStartServer = async (
const {
host,
port,
gqlCache: gqlCacheConfig,
maxSimultaneousRequests,
maxRequestQueueLimit,
gqlPath = DEFAULT_GQL_PATH
gql: {
cache: gqlCacheConfig,
maxSimultaneousRequests,
maxRequestQueueLimit,
path: gqlPath = DEFAULT_GQL_PATH
}
} = serverConfig;
app.use(queue({ activeLimit: maxSimultaneousRequests || 1, queuedLimit: maxRequestQueueLimit || -1 }));
@ -62,6 +64,9 @@ export const createAndStartServer = async (
}
const server = new ApolloServer({
context: (expressContext: ExpressContext) => {
return expressContext;
},
schema,
csrfPrevention: true,
cache: gqlCache,

149
yarn.lock
View File

@ -506,6 +506,11 @@
it-pushable "^3.1.0"
uint8arraylist "^2.3.2"
"@colors/colors@1.6.0", "@colors/colors@^1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0"
integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==
"@cspotcode/source-map-support@^0.8.0":
version "0.8.1"
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
@ -513,6 +518,15 @@
dependencies:
"@jridgewell/trace-mapping" "0.3.9"
"@dabh/diagnostics@^2.0.2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a"
integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==
dependencies:
colorspace "1.1.x"
enabled "2.0.x"
kuler "^2.0.0"
"@ensdomains/ens@^0.4.4":
version "0.4.5"
resolved "https://registry.npmjs.org/@ensdomains/ens/-/ens-0.4.5.tgz"
@ -3935,6 +3949,11 @@
"@types/glob" "~7.2.0"
"@types/node" "*"
"@types/triple-beam@^1.3.2":
version "1.3.5"
resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c"
integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==
"@types/ws@^8.5.3":
version "8.5.4"
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5"
@ -4750,6 +4769,11 @@ async@^2.4.0:
dependencies:
lodash "^4.17.14"
async@^3.2.3:
version "3.2.5"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66"
integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==
asyncify-wasm@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/asyncify-wasm/-/asyncify-wasm-1.2.1.tgz#a15c0480e858619a4f971e44e6fc05c49015d9e8"
@ -6168,7 +6192,7 @@ collection-visit@^1.0.0:
map-visit "^1.0.0"
object-visit "^1.0.0"
color-convert@^1.9.0:
color-convert@^1.9.0, color-convert@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@ -6187,11 +6211,35 @@ color-name@1.1.3:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@~1.1.4:
color-name@^1.0.0, color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-string@^1.6.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
dependencies:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
color@^3.1.3:
version "3.2.1"
resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164"
integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==
dependencies:
color-convert "^1.9.3"
color-string "^1.6.0"
colorspace@1.1.x:
version "1.1.4"
resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243"
integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==
dependencies:
color "^3.1.3"
text-hex "1.0.x"
columnify@^1.5.4:
version "1.5.4"
resolved "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz"
@ -7150,6 +7198,11 @@ emoji-regex@^9.2.2:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
enabled@2.0.x:
version "2.0.0"
resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==
encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz"
@ -8285,6 +8338,11 @@ fastq@^1.6.0:
dependencies:
reusify "^1.0.4"
fecha@^4.2.0:
version "4.2.3"
resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd"
integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==
fetch-ponyfill@^4.0.0:
version "4.1.0"
resolved "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz"
@ -8436,6 +8494,11 @@ flow-stoplight@^1.0.0:
resolved "https://registry.npmjs.org/flow-stoplight/-/flow-stoplight-1.0.0.tgz"
integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s=
fn.name@1.x.x:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
follow-redirects@^1.0.0:
version "1.15.3"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a"
@ -9899,6 +9962,11 @@ is-arrayish@^0.2.1:
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
is-arrayish@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
is-bigint@^1.0.1:
version "1.0.2"
resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz"
@ -10864,6 +10932,11 @@ klaw@^1.0.0:
optionalDependencies:
graceful-fs "^4.1.9"
kuler@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
lcid@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz"
@ -11299,6 +11372,18 @@ log-symbols@4.1.0:
chalk "^4.1.0"
is-unicode-supported "^0.1.0"
logform@^2.3.2, logform@^2.4.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/logform/-/logform-2.6.0.tgz#8c82a983f05d6eaeb2d75e3decae7a768b2bf9b5"
integrity sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==
dependencies:
"@colors/colors" "1.6.0"
"@types/triple-beam" "^1.3.2"
fecha "^4.2.0"
ms "^2.1.1"
safe-stable-stringify "^2.3.1"
triple-beam "^1.3.0"
loglevel@^1.6.8:
version "1.8.1"
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4"
@ -12764,6 +12849,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
one-time@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45"
integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==
dependencies:
fn.name "1.x.x"
onetime@^5.1.0, onetime@^5.1.2:
version "5.1.2"
resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz"
@ -14512,6 +14604,11 @@ safe-regex@^1.1.0:
dependencies:
ret "~0.1.10"
safe-stable-stringify@^2.3.1:
version "2.4.3"
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886"
integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==
"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
@ -14841,6 +14938,13 @@ simple-get@^2.7.0:
once "^1.3.1"
simple-concat "^1.0.0"
simple-swizzle@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==
dependencies:
is-arrayish "^0.3.1"
simple-update-notifier@^1.0.7:
version "1.1.0"
resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82"
@ -15135,6 +15239,11 @@ ssri@^8.0.0, ssri@^8.0.1:
dependencies:
minipass "^3.1.1"
stack-trace@0.0.x:
version "0.0.10"
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==
stacktrace-parser@^0.1.10:
version "0.1.10"
resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a"
@ -15512,6 +15621,11 @@ text-extensions@^1.0.0:
resolved "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz"
integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==
text-hex@1.0.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
@ -15686,6 +15800,11 @@ trim-right@^1.0.1:
resolved "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz"
integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
triple-beam@^1.3.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984"
integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==
truncate-utf8-bytes@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz#405923909592d56f78a5818434b0b78489ca5f2b"
@ -16755,6 +16874,32 @@ window-size@^0.2.0:
resolved "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz"
integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=
winston-transport@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.7.0.tgz#e302e6889e6ccb7f383b926df6936a5b781bd1f0"
integrity sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==
dependencies:
logform "^2.3.2"
readable-stream "^3.6.0"
triple-beam "^1.3.0"
winston@^3.13.0:
version "3.13.0"
resolved "https://registry.yarnpkg.com/winston/-/winston-3.13.0.tgz#e76c0d722f78e04838158c61adc1287201de7ce3"
integrity sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==
dependencies:
"@colors/colors" "^1.6.0"
"@dabh/diagnostics" "^2.0.2"
async "^3.2.3"
is-stream "^2.0.0"
logform "^2.4.0"
one-time "^1.0.0"
readable-stream "^3.4.0"
safe-stable-stringify "^2.3.1"
stack-trace "0.0.x"
triple-beam "^1.3.0"
winston-transport "^4.7.0"
word-wrap@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"