Skip to content

Commit

Permalink
feature: logger
Browse files Browse the repository at this point in the history
Now structured and controllable using LOGGER_LEVEL env var,
 defaulting to info.
  • Loading branch information
rhyslbw committed Jan 8, 2021
1 parent 69cddb9 commit f948cf5
Show file tree
Hide file tree
Showing 25 changed files with 172 additions and 56 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports = {
2,
"unix"
],
"no-unused-expressions": 0
"no-unused-expressions": 0,
"no-useless-constructor": 0
}
}
8 changes: 7 additions & 1 deletion nix/nixos/cardano-graphql-service.nix
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ in {
default = "allegra";
};

logLevel = lib.mkOption {
type = lib.types.str;
default = "info";
};

port = lib.mkOption {
type = lib.types.int;
default = 3100;
Expand Down Expand Up @@ -143,13 +148,14 @@ in {
CARDANO_CLI_PATH = cfg.cardanoCliPackage + "/bin/cardano-cli";
CARDANO_NODE_SOCKET_PATH = cfg.cardanoNodeSocketPath;
CURRENT_ERA_FIRST_SLOT = cfg.currentEraFirstSlot;
ERA_NAME =cfg.eraName;
ERA_NAME = cfg.eraName;
POOL_METADATA_PROXY = cfg.smashUrl;
GENESIS_FILE_BYRON = cfg.genesisByron;
GENESIS_FILE_SHELLEY = cfg.genesisShelley;
HASURA_CLI_PATH = hasura-cli + "/bin/hasura";
HASURA_URI = hasuraBaseUri;
JQ_PATH = pkgs.jq + "/bin/jq";
LOGGER_LEVEL = cfg.loggerLevel;
POSTGRES_DB = cfg.db;
POSTGRES_HOST = cfg.dbHost;
POSTGRES_PASSWORD = cfg.dbPassword;
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"@graphql-codegen/typescript": "^1.15.2",
"@graphql-codegen/typescript-graphql-files-modules": "^1.15.2",
"@graphql-codegen/typescript-resolvers": "^1.15.2",
"@types/bunyan": "^1.8.6",
"@types/clear": "^0.1.0",
"@types/dockerode": "^2.5.33",
"@types/figlet": "^1.2.0",
Expand Down
Binary file added packages-cache/@types-bunyan-1.8.6.tgz
Binary file not shown.
Binary file added packages-cache/bunyan-1.8.14.tgz
Binary file not shown.
Binary file added packages-cache/dtrace-provider-0.8.8.tgz
Binary file not shown.
Binary file added packages-cache/glob-6.0.4.tgz
Binary file not shown.
Binary file added packages-cache/mv-2.1.1.tgz
Binary file not shown.
Binary file added packages-cache/ncp-2.0.0.tgz
Binary file not shown.
Binary file added packages-cache/rimraf-2.4.5.tgz
Binary file not shown.
Binary file added packages-cache/safe-json-stringify-1.2.0.tgz
Binary file not shown.
Binary file added packages-cache/ts-log-2.2.3.tgz
Binary file not shown.
3 changes: 2 additions & 1 deletion packages/api-cardano-db-hasura/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
"p-retry": "^4.2.0",
"pg": "^8.5.1",
"pg-listen": "^1.6.0",
"set-interval-async": "^1.0.33"
"set-interval-async": "^1.0.33",
"ts-log": "^2.2.3"
},
"devDependencies": {
"@cardano-graphql/util-dev": "3.1.0",
Expand Down
18 changes: 11 additions & 7 deletions packages/api-cardano-db-hasura/src/CardanoNodeClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import fs from 'fs-extra'
import { AssetSupply } from './graphql_types'
import pRetry from 'p-retry'
import util, { DataFetcher } from '@cardano-graphql/util'
import { dummyLogger, Logger } from 'ts-log'

export type LedgerState = {
accountState: {
Expand All @@ -15,22 +16,22 @@ export type LedgerState = {
}

export class CardanoNodeClient {
private cardanoCli: CardanoCli
readonly currentEraFirstSlot: number
readonly networkParams: string[]
public adaCirculatingSupply: AssetSupply['circulating']
public ledgerStateFetcher: DataFetcher<LedgerState>

constructor (
cardanoCli: CardanoCli,
private cardanoCli: CardanoCli,
pollingInterval: number,
currentEraFirstSlot: number
private currentEraFirstSlot: number,
private logger: Logger = dummyLogger
) {
this.cardanoCli = cardanoCli
this.currentEraFirstSlot = currentEraFirstSlot
this.ledgerStateFetcher = new DataFetcher<LedgerState>(
'LedgerState',
this.cardanoCli.getLedgerState,
pollingInterval
pollingInterval,
this.logger
)
}

Expand All @@ -39,7 +40,10 @@ export class CardanoNodeClient {
await fs.stat(process.env.CARDANO_NODE_SOCKET_PATH)
const { slotNo } = await this.cardanoCli.getTip()
if (slotNo < this.currentEraFirstSlot) {
throw new Error('cardano-node is still synchronizing')
this.logger.debug('cardano-node tip', { module: 'CardanoNodeClient', value: slotNo })
this.logger.debug('currentEraFirstSlot', { module: 'CardanoNodeClient', value: this.currentEraFirstSlot })
this.logger.warn('cardano-node is still synchronizing', { module: 'CardanoNodeClient' })
throw new Error()
}
}, {
factor: 1.5,
Expand Down
18 changes: 11 additions & 7 deletions packages/api-cardano-db-hasura/src/Db.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,48 @@
import { ClientConfig } from 'pg'
import createSubscriber, { Subscriber } from 'pg-listen'
import { dummyLogger, Logger } from 'ts-log'

export class Db {
pgSubscriber: Subscriber

constructor (pgClientConfig: ClientConfig) {
constructor (
pgClientConfig: ClientConfig,
private logger: Logger = dummyLogger
) {
this.pgSubscriber = createSubscriber(pgClientConfig, {
parse: (value) => value
})
}

public async init ({ onDbSetup }: { onDbSetup: Function }): Promise<void> {
this.pgSubscriber.events.on('connected', async () => {
console.log('DbClient.pgSubscriber: Connected')
this.logger.debug('DbClient.pgSubscriber: Connected')
await onDbSetup()
})
this.pgSubscriber.events.on('reconnect', (attempt) => {
console.warn(`DbClient.pgSubscriber: Reconnecting attempt ${attempt}`)
this.logger.warn(`DbClient.pgSubscriber: Reconnecting attempt ${attempt}`)
})
this.pgSubscriber.events.on('error', (error) => {
console.error('DbClient.pgSubscriber: Fatal database connection error:', error)
this.logger.error('DbClient.pgSubscriber: Fatal database connection error:', error)
process.exit(1)
})
this.pgSubscriber.notifications.on('cardano_db_sync_startup', async payload => {
switch (payload) {
case 'init' :
console.log('DbClient.pgSubscriber: cardano-db-sync-extended starting, schema will be reset')
this.logger.warn('DbClient.pgSubscriber: cardano-db-sync-extended starting, schema will be reset')
break
case 'db-setup' :
await onDbSetup()
break
default :
console.error(`DbClient.pgSubscriber: Unknown message payload ${payload}`)
this.logger.error(`DbClient.pgSubscriber: Unknown message payload ${payload}`)
}
})
try {
await this.pgSubscriber.connect()
await this.pgSubscriber.listenTo('cardano_db_sync_startup')
} catch (error) {
console.error(error)
this.logger.error(error)
}
}

Expand Down
20 changes: 12 additions & 8 deletions packages/api-cardano-db-hasura/src/HasuraClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,28 @@ import { introspectSchema, wrapSchema } from '@graphql-tools/wrap'
import pRetry from 'p-retry'
import path from 'path'
import { AssetSupply } from './graphql_types'
import { dummyLogger, Logger } from 'ts-log'

dayjs.extend(utc)

export class HasuraClient {
private client: ApolloClient<NormalizedCacheObject>
readonly hasuraCliPath: string
readonly hasuraUri: string
private applyingSchemaAndMetadata: boolean
public adaCirculatingSupplyFetcher: DataFetcher<AssetSupply['circulating']>
public schema: GraphQLSchema

constructor (hasuraCliPath: string, hasuraUri: string, pollingInterval: number) {
constructor (
readonly hasuraCliPath: string,
readonly hasuraUri: string,
pollingInterval: number,
private logger: Logger = dummyLogger
) {
this.adaCirculatingSupplyFetcher = new DataFetcher<AssetSupply['circulating']>(
'AdaCirculatingSupply',
this.getAdaCirculatingSupply.bind(this),
pollingInterval
pollingInterval,
this.logger
)
this.hasuraCliPath = hasuraCliPath
this.hasuraUri = hasuraUri
this.client = new ApolloClient({
cache: new InMemoryCache({
addTypename: false
Expand Down Expand Up @@ -94,7 +98,7 @@ export class HasuraClient {
})
return fetchResult.json()
} catch (error) {
console.error(error)
this.logger.error(error)
throw error
}
}
Expand Down Expand Up @@ -159,7 +163,7 @@ export class HasuraClient {
if (error) {
reject(error)
}
console.log(stdout)
this.logger.debug(stdout)
resolve()
}
)
Expand Down
4 changes: 3 additions & 1 deletion packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@
"apollo-server-errors": "^2.4.1",
"apollo-server-express": "^2.14.3",
"body-parser": "^1.19.0",
"bunyan": "^1.8.14",
"cors": "^2.8.5",
"express": "^4.17.1",
"fs-extra": "^9.0.1",
"graphql": "14.5.8",
"graphql-depth-limit": "^1.1.0",
"prom-client": "^11.5.3",
"ts-custom-error": "^3.2.0"
"ts-custom-error": "^3.2.0",
"ts-log": "^2.2.3"
},
"devDependencies": {
"@cardano-graphql/util-dev": "3.1.0",
Expand Down
17 changes: 11 additions & 6 deletions packages/server/src/CompleteApiServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ import {
HasuraClient
} from '@cardano-graphql/api-cardano-db-hasura'
import { GraphQLSchema } from 'graphql'
import { dummyLogger, Logger } from 'ts-log'

export * from './config'

export async function CompleteApiServer (config: Config): Promise<Server> {
export async function CompleteApiServer (
config: Config,
logger: Logger = dummyLogger
): Promise<Server> {
const schemas: GraphQLSchema[] = []
let genesis: Genesis
let cardanoNodeClient: CardanoNodeClient
Expand All @@ -26,17 +30,18 @@ export async function CompleteApiServer (config: Config): Promise<Server> {
cardanoNodeClient = new CardanoNodeClient(
createCardanoCli(config.cardanoCliPath, config.eraName, genesis.shelley, config.jqPath),
1000 * 60 * 10,
config.currentEraFirstSlot
config.currentEraFirstSlot,
logger
)
}
if (config.hasuraUri !== undefined) {
const hasuraClient = new HasuraClient(
config.hasuraCliPath,
config.hasuraUri,
config.pollingIntervalAdaSupply

config.pollingIntervalAdaSupply,
logger
)
const db = new Db(config.db)
const db = new Db(config.db, logger)
await db.init({
onDbSetup: () => Promise.all([
hasuraClient.initialize(),
Expand All @@ -45,5 +50,5 @@ export async function CompleteApiServer (config: Config): Promise<Server> {
})
schemas.push(await buildCardanoDbHasuraSchema(hasuraClient, genesis, cardanoNodeClient))
}
return new Server(schemas, config)
return new Server(schemas, config, logger)
}
21 changes: 13 additions & 8 deletions packages/server/src/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { AllowList } from './AllowList'
import { prometheusMetricsPlugin } from './apollo_server_plugins'
import { IntrospectionNotPermitted, TracingRequired } from './errors'
import { allowListMiddleware } from './express_middleware'
import { dummyLogger, Logger } from 'ts-log'
import { LogLevelString } from 'bunyan'

export type Config = {
allowIntrospection: boolean
Expand All @@ -20,6 +22,7 @@ export type Config = {
apiPort: number
cacheEnabled: boolean
listenAddress: string
loggerLevel: LogLevelString
prometheusMetrics: boolean
queryDepthLimit?: number
tracing: boolean
Expand All @@ -28,13 +31,15 @@ export type Config = {
export class Server {
public app: express.Application
private apolloServer: ApolloServer
private config: Config
private httpServer: http.Server
private schemas: GraphQLSchema[]

constructor (schemas: GraphQLSchema[], config: Config) {
constructor (
schemas: GraphQLSchema[],
private config: Config,
private logger: Logger = dummyLogger
) {
this.app = express()
this.config = config
this.schemas = schemas
}

Expand All @@ -50,9 +55,9 @@ export class Server {
const file = await fs.readFile(this.config.allowListPath, 'utf8')
allowList = JSON.parse(file)
this.app.use('/', json(), allowListMiddleware(allowList))
console.log('The server will only allow only operations from the provided list')
this.logger.info('The server will only allow only operations from the provided list')
} catch (error) {
console.error(`Cannot read or parse allow-list JSON file at ${this.config.allowListPath}`)
this.logger.error(`Cannot read or parse allow-list JSON file at ${this.config.allowListPath}`)
throw error
}
}
Expand All @@ -61,7 +66,7 @@ export class Server {
throw new TracingRequired('Prometheus')
}
plugins.push(prometheusMetricsPlugin(this.app))
console.log('Prometheus metrics will be served at /metrics')
this.logger.info('Prometheus metrics will be served at /metrics')
}
if (this.config.queryDepthLimit) {
validationRules.push(depthLimit(this.config.queryDepthLimit))
Expand All @@ -88,15 +93,15 @@ export class Server {

async start () {
this.httpServer = await listenPromise(this.app, this.config.apiPort, this.config.listenAddress)
console.log(`GraphQL HTTP server at http://${this.config.listenAddress}:` +
this.logger.info(`GraphQL HTTP server at http://${this.config.listenAddress}:` +
`${this.config.apiPort}${this.apolloServer.graphqlPath} started`
)
}

shutdown () {
if (this.httpServer !== undefined) {
this.httpServer.close()
console.log(`GraphQL HTTP server at http://${this.config.listenAddress}:` +
this.logger.info(`GraphQL HTTP server at http://${this.config.listenAddress}:` +
`${this.config.apiPort}${this.apolloServer.graphqlPath} shutting down`
)
}
Expand Down
4 changes: 4 additions & 0 deletions packages/server/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Config as ApiCardanoDbHasuraConfig } from '@cardano-graphql/api-cardano
import { MissingConfig } from './errors'
import fs from 'fs-extra'
import { Config as ServerConfig } from './Server'
import { LogLevelString } from 'bunyan'

export type Config = ServerConfig & ApiCardanoDbHasuraConfig

Expand Down Expand Up @@ -60,6 +61,7 @@ export async function getConfig (): Promise<Config> {
currentEraFirstSlot: env.currentEraFirstSlot || 16588800,
db,
eraName: env.eraName || 'allegra',
loggerLevel: env.loggerLevel || 'info' as LogLevelString,
jqPath: env.jqPath || 'jq',
listenAddress: env.listenAddress || '0.0.0.0',
pollingIntervalAdaSupply: env.pollingIntervalAdaSupply || 1000 * 60,
Expand All @@ -84,6 +86,7 @@ function filterAndTypecastEnvs (env: any) {
HASURA_URI,
JQ_PATH,
LISTEN_ADDRESS,
LOGGER_LEVEL,
POLLING_INTERVAL_ADA_SUPPLY,
POSTGRES_DB,
POSTGRES_DB_FILE,
Expand Down Expand Up @@ -115,6 +118,7 @@ function filterAndTypecastEnvs (env: any) {
hasuraUri: HASURA_URI,
jqPath: JQ_PATH,
listenAddress: LISTEN_ADDRESS,
loggerLevel: LOGGER_LEVEL as LogLevelString,
pollingIntervalAdaSupply: Number(POLLING_INTERVAL_ADA_SUPPLY),
postgresDb: POSTGRES_DB,
postgresDbFile: POSTGRES_DB_FILE,
Expand Down
Loading

0 comments on commit f948cf5

Please sign in to comment.