Skip to content

Commit e0f3108

Browse files
authored
improve logging (#137)
1 parent b5aaf2d commit e0f3108

File tree

20 files changed

+482
-247
lines changed

20 files changed

+482
-247
lines changed

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
"csv-writer": "^1.6.0",
3838
"dotenv": "^16.0.2",
3939
"lodash": "^4.17.21",
40+
"mars-liquidation": "2.3.0",
41+
"mars-rover-health-computer-node": "2.3.0-node",
4042
"marsjs-types": "2.3.0",
4143
"osmojs": "^16.5.1",
4244
"prom-client": "^15.1.3",
@@ -45,15 +47,14 @@
4547
"requests": "^0.3.0",
4648
"ts-jest": "^29.2.5",
4749
"ts-node": "^10.9.1",
48-
"uuid": "^9.0.0",
49-
"mars-rover-health-computer-node": "2.3.0-node",
50-
"mars-liquidation": "2.3.0"
50+
"uuid": "^9.0.0"
5151
},
5252
"devDependencies": {
5353
"@babel/core": "^7.21.0",
5454
"@babel/preset-env": "^7.20.2",
5555
"@babel/preset-typescript": "^7.21.0",
56-
"@types/jest": "^29.2.6",
56+
"@types/jest": "^30.0.0",
57+
"@types/node": "^24.9.2",
5758
"@typescript-eslint/eslint-plugin": "^5.48.2",
5859
"@typescript-eslint/parser": "^5.48.2",
5960
"babel-jest": "^29.4.3",

src/AmmRouter.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { ConcentratedLiquidityPool, Pool, PoolType, XYKPool } from './types/Pool
77
import { Coin, Dec, Int } from '@keplr-wallet/unit'
88
import { ConcentratedLiquidityMath, BigDec } from '@osmosis-labs/math'
99
import Long from 'long'
10+
import { logger } from './logger'
1011
// const { calcOutGivenIn, calcInGivenOut } = ConcentratedLiquidityMath
1112

1213
export interface AMMRouterInterface {
@@ -45,7 +46,7 @@ export class AMMRouter implements AMMRouterInterface {
4546
let amountAfterFees = new BigNumber(0)
4647

4748
if (tokenInAmount.isEqualTo(0)) {
48-
console.log('ERROR - cannot use token in amount of 0')
49+
logger.error('Cannot use token in amount of 0')
4950
return amountAfterFees
5051
}
5152

@@ -163,7 +164,7 @@ export class AMMRouter implements AMMRouterInterface {
163164
let amountAfterFees = new BigNumber(0)
164165

165166
if (tokenOutRequired.isEqualTo(0)) {
166-
console.log('ERROR - cannot use token out amount of 0')
167+
logger.error('Cannot use token out amount of 0')
167168
return amountAfterFees
168169
}
169170
try {

src/BaseExecutor.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { PriceResponse } from 'marsjs-types/mars-oracle-osmosis/MarsOracleOsmosi
1616
import { Market } from 'marsjs-types/mars-red-bank/MarsRedBank.types'
1717
import { Dictionary } from 'lodash'
1818
import { MetricsService } from './metrics'
19+
import { logger } from './logger'
1920

2021
export interface BaseConfig {
2122
lcdEndpoint: string
@@ -69,7 +70,7 @@ export class BaseExecutor {
6970
public ammRouter: AMMRouter = new AMMRouter(),
7071
public metrics: MetricsService = MetricsService.getInstance(),
7172
) {
72-
console.log({ config })
73+
logger.debug('BaseExecutor config', config)
7374
}
7475

7576
applyAvailableLiquidity = (market: Market): MarketInfo => {
@@ -142,14 +143,14 @@ export class BaseExecutor {
142143
fetching = response.length === limit
143144
retries = 0
144145
} catch (e) {
145-
console.warn(e)
146+
logger.warn(e)
146147
retries++
147148
if (retries >= maxRetries) {
148-
console.warn('Max retries exceeded, exiting', maxRetries)
149+
logger.warn('Max retries exceeded, exiting', maxRetries)
149150
fetching = false
150151
} else {
151152
await sleep(5000)
152-
console.info('Retrying...')
153+
logger.info('Retrying...')
153154
}
154155
}
155156
}
@@ -177,14 +178,14 @@ export class BaseExecutor {
177178
fetching = response.length === limit
178179
retries = 0
179180
} catch (e) {
180-
console.warn(e)
181+
logger.warn(e)
181182
retries++
182183
if (retries >= maxRetries) {
183-
console.warn('Max retries exceeded, exiting', maxRetries)
184+
logger.warn('Max retries exceeded, exiting', maxRetries)
184185
fetching = false
185186
} else {
186187
await sleep(5000)
187-
console.info('Retrying...')
188+
logger.info('Retrying...')
188189
}
189190
}
190191
}
@@ -230,14 +231,14 @@ export class BaseExecutor {
230231
fetching = response.length === 5
231232
retries = 0
232233
} catch (ex) {
233-
console.warn(ex)
234+
logger.warn(ex)
234235
retries++
235236
if (retries > maxRetries) {
236-
console.warn('Max retries exceeded, exiting', maxRetries)
237+
logger.warn('Max retries exceeded, exiting', maxRetries)
237238
fetching = false
238239
} else {
239240
await sleep(5000)
240-
console.info('Retrying...')
241+
logger.info('Retrying...')
241242
}
242243
}
243244
}
@@ -262,7 +263,7 @@ export class BaseExecutor {
262263
}
263264
})
264265
} catch (e) {
265-
console.error(e)
266+
logger.error(e)
266267
}
267268
}
268269

src/CsvWriter.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createObjectCsvWriter } from 'csv-writer'
2+
import { logger } from './logger'
23

34
export interface Header {
45
id: string
@@ -37,9 +38,9 @@ export class CSVWriter {
3738
path: this.filePath,
3839
header: this.headers,
3940
})
40-
console.log('writing results')
41+
logger.info('writing results')
4142
await writer.writeRecords(this.rows).then(() => {
42-
console.log('...Done')
43+
logger.info('...Done')
4344
})
4445
}
4546
}

src/helpers.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import { OsmoRoute } from './types/swapper'
4343
import { PerpPosition, Positions } from 'marsjs-types/mars-credit-manager/MarsCreditManager.types'
4444
import BigNumber from 'bignumber.js'
4545
import { PoolAsset } from './types/Pool'
46+
import { logger } from './logger'
4647

4748
const { swapExactAmountIn } = osmosis.gamm.v1beta1.MessageComposer.withTypeUrl
4849
osmosis.gamm.v1beta1.MsgSwapExactAmountIn
@@ -66,8 +67,8 @@ export function readAddresses(deployConfigPath: string): ProtocolAddresses {
6667

6768
return camelCaseKeys(deployData.addresses) as ProtocolAddresses
6869
} catch (e) {
69-
console.error(`Failed to load artifacts path - could not find ${deployConfigPath}`)
70-
process.exit(1)
70+
logger.error(`Failed to load artifacts path - could not find ${deployConfigPath}`)
71+
throw new Error(`Failed to load artifacts path - could not find ${deployConfigPath}`)
7172
}
7273
}
7374

@@ -178,8 +179,8 @@ export const queryAstroportLpUnderlyingCoins = async (
178179
JSON.stringify({ simulate_withdraw: { lp_amount: lpCoin.amount } }),
179180
).toString('base64')
180181
const url = `${process.env.LCD_ENDPOINT}/cosmwasm/wasm/v1/contract/${pairAddress}/smart/${encodedMsg}`
181-
console.log(`Querying Astroport LP underlying coins for ${lpCoin.denom}`)
182-
console.log(`URL: ${url}`)
182+
logger.info(`Querying Astroport LP underlying coins for ${lpCoin.denom}`)
183+
logger.info(`URL: ${url}`)
183184
// Fetch pair info
184185
const response = await fetch(url)
185186
return (await response.json())['data'] as AstroportSimulateWithdrawCoin[]
@@ -238,12 +239,12 @@ export const seedAddresses = async (
238239
const seededAddresses: string[] = []
239240
const sendTokenMsgs: EncodeObject[] = []
240241

241-
console.log(`seeding children for ${sender}`)
242+
logger.info(`seeding children for ${sender}`)
242243
accounts.forEach((account) => {
243244
if (account.address === sender) return
244245

245246
const addressToSeed = account.address
246-
console.log(`seeding ${addressToSeed}`)
247+
logger.info(`seeding ${addressToSeed}`)
247248

248249
// todo - optimise this into one msg
249250
const gasMsg = {

src/logger.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
type LogLevel = 'debug' | 'info' | 'warn' | 'error'
2+
3+
const levelWeights: Record<LogLevel, number> = {
4+
debug: 10,
5+
info: 20,
6+
warn: 30,
7+
error: 40,
8+
}
9+
10+
const normalizeLevel = (level: string | undefined): LogLevel => {
11+
switch (level?.toLowerCase()) {
12+
case 'debug':
13+
return 'debug'
14+
case 'warn':
15+
return 'warn'
16+
case 'error':
17+
return 'error'
18+
case 'info':
19+
default:
20+
return 'info'
21+
}
22+
}
23+
24+
class Logger {
25+
private minLevel: LogLevel
26+
27+
constructor(level?: string) {
28+
this.minLevel = normalizeLevel(level)
29+
}
30+
31+
setLevel(level: LogLevel): void {
32+
this.minLevel = level
33+
}
34+
35+
debug(message?: unknown, ...optionalParams: unknown[]): void {
36+
this.write('debug', message, ...optionalParams)
37+
}
38+
39+
info(message?: unknown, ...optionalParams: unknown[]): void {
40+
this.write('info', message, ...optionalParams)
41+
}
42+
43+
warn(message?: unknown, ...optionalParams: unknown[]): void {
44+
this.write('warn', message, ...optionalParams)
45+
}
46+
47+
error(message?: unknown, ...optionalParams: unknown[]): void {
48+
this.write('error', message, ...optionalParams)
49+
}
50+
51+
private write(level: LogLevel, message?: unknown, ...optionalParams: unknown[]): void {
52+
if (levelWeights[level] < levelWeights[this.minLevel]) return
53+
54+
const timestamp = new Date().toISOString()
55+
const upperLevel = level.toUpperCase().padEnd(5, ' ')
56+
57+
const formatted = this.formatMessage(message, optionalParams)
58+
const line = `[${timestamp}] [${upperLevel}] ${formatted}\n`
59+
60+
if (level === 'error') {
61+
process.stderr.write(line)
62+
} else {
63+
process.stdout.write(line)
64+
}
65+
}
66+
67+
private formatMessage(message: unknown, additional: unknown[]): string {
68+
const segments = [message, ...additional].filter((segment) => segment !== undefined)
69+
if (segments.length === 0) {
70+
return ''
71+
}
72+
73+
return segments
74+
.map((segment) => {
75+
if (segment instanceof Error) {
76+
return segment.stack ?? `${segment.name}: ${segment.message}`
77+
}
78+
if (typeof segment === 'string') {
79+
return segment
80+
}
81+
if (typeof segment === 'number' || typeof segment === 'boolean' || segment === null) {
82+
return String(segment)
83+
}
84+
try {
85+
return JSON.stringify(segment, null, 2)
86+
} catch {
87+
return String(segment)
88+
}
89+
})
90+
.join(' ')
91+
}
92+
}
93+
94+
export const logger = new Logger(process.env.LOG_LEVEL)

src/main.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { SkipRouteRequester } from './query/routing/skip/SkipRouteRequester.js'
1616
import { RouteRequester } from './query/routing/RouteRequesterInterface.js'
1717
import { ChainQuery } from './query/chainQuery.js'
1818
import { MetricsService } from './metrics.js'
19+
import { logger } from './logger'
1920

2021
const REDBANK = 'Redbank'
2122
const ROVER = 'Rover'
@@ -74,7 +75,7 @@ export const main = async () => {
7475
const metricsPort = process.env.METRICS_PORT ? parseInt(process.env.METRICS_PORT) : 9090
7576
const metrics = MetricsService.getInstance()
7677
metrics.startMetricsServer(metricsPort)
77-
console.log(`Metrics server started on port ${metricsPort}`)
78+
logger.info(`Metrics server started on port ${metricsPort}`)
7879

7980
switch (executorType) {
8081
case REDBANK:
@@ -129,6 +130,6 @@ const launchRedbank = async (
129130
}
130131

131132
main().catch((e) => {
132-
console.log(e)
133+
logger.error(e)
133134
process.exit(1)
134135
})

src/metrics.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import promClient from 'prom-client'
22
import http from 'http'
3+
import { logger } from './logger'
34

45
export class MetricsService {
56
private static instance: MetricsService
@@ -134,7 +135,7 @@ export class MetricsService {
134135
}
135136

136137
public startMetricsServer(port: number = 9090): void {
137-
const server = http.createServer(async (req, res) => {
138+
const server = http.createServer(async (req: http.IncomingMessage, res: http.ServerResponse) => {
138139
if (req.url === '/metrics') {
139140
res.setHeader('Content-Type', this.register.contentType)
140141
res.end(await this.register.metrics())
@@ -148,7 +149,7 @@ export class MetricsService {
148149
})
149150

150151
server.listen(port, () => {
151-
console.log(`Metrics server listening on port ${port}`)
152+
logger.info(`Metrics server listening on port ${port}`)
152153
})
153154
}
154155

src/query/routing/skip/SkipRouteRequester.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ export class SkipRouteRequester extends RouteRequester {
5050
pool: swapOp.pool,
5151
})),
5252
}))
53-
console.log('operations')
54-
console.log(JSON.stringify(operations))
5553
return {
5654
amountIn: skipRoute.amount_in,
5755
estimatedAmountOut: skipRoute.amount_out,

src/query/routing/skip/getSwapRoute.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { logger } from '../../../logger'
12
/**
23
* Skip API v2 Fungible Route Client
34
* Fetches swap routes from https://api.skip.build/v2/fungible/route
@@ -117,8 +118,8 @@ export async function getSwapRoute(
117118

118119
return data
119120
} catch (error) {
120-
console.error('Error fetching route:', error)
121-
console.error(
121+
logger.error('Error fetching route:', error)
122+
logger.error(
122123
'params:',
123124
JSON.stringify({
124125
denomIn,

0 commit comments

Comments
 (0)