Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
c68fb1e2
Unverified
Commit
c68fb1e2
authored
Dec 12, 2022
by
mergify[bot]
Committed by
GitHub
Dec 12, 2022
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4375 from ethereum-optimism/sc/cmn-clean-base-service
feat(cmn): clean up BaseServiceV2 options
parents
300d2fdf
9b289185
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
208 additions
and
133 deletions
+208
-133
perfect-years-rush.md
.changeset/perfect-years-rush.md
+9
-0
base-service-v2.ts
packages/common-ts/src/base-service/base-service-v2.ts
+30
-109
base-service.ts
packages/common-ts/src/base-service/base-service.ts
+3
-3
index.ts
packages/common-ts/src/base-service/index.ts
+2
-0
metrics.ts
packages/common-ts/src/base-service/metrics.ts
+51
-0
options.ts
packages/common-ts/src/base-service/options.ts
+77
-0
router.ts
packages/common-ts/src/base-service/router.ts
+6
-0
metrics.ts
packages/common-ts/src/common/metrics.ts
+1
-1
service.ts
...data-transport-layer/src/services/l1-ingestion/service.ts
+3
-3
service.ts
...data-transport-layer/src/services/l2-ingestion/service.ts
+2
-2
service.ts
packages/data-transport-layer/src/services/main/service.ts
+4
-4
service.ts
packages/data-transport-layer/src/services/server/service.ts
+2
-2
service.ts
packages/drippie-mon/src/service.ts
+6
-3
service.ts
packages/fault-detector/src/service.ts
+6
-3
service.ts
packages/replica-healthcheck/src/service.ts
+6
-3
No files found.
.changeset/perfect-years-rush.md
0 → 100644
View file @
c68fb1e2
---
'
@eth-optimism/common-ts'
:
minor
'
@eth-optimism/drippie-mon'
:
minor
'
@eth-optimism/fault-detector'
:
minor
'
@eth-optimism/replica-healthcheck'
:
minor
'
@eth-optimism/data-transport-layer'
:
patch
---
Refactors BaseServiceV2 slightly, merges standard options with regular options
packages/common-ts/src/base-service/base-service-v2.ts
View file @
c68fb1e2
...
...
@@ -3,61 +3,36 @@ import { Server } from 'net'
import
Config
from
'
bcfg
'
import
*
as
dotenv
from
'
dotenv
'
import
{
Command
,
Option
}
from
'
commander
'
import
{
ValidatorSpec
,
Spec
,
cleanEnv
}
from
'
envalid
'
import
{
cleanEnv
}
from
'
envalid
'
import
snakeCase
from
'
lodash/snakeCase
'
import
express
,
{
Router
}
from
'
express
'
import
express
from
'
express
'
import
prometheus
,
{
Registry
}
from
'
prom-client
'
import
promBundle
from
'
express-prom-bundle
'
import
bodyParser
from
'
body-parser
'
import
morgan
from
'
morgan
'
import
{
Logger
,
LogLevel
}
from
'
../common/logger
'
import
{
Metric
,
Gauge
,
Counter
}
from
'
./metrics
'
import
{
validators
}
from
'
./validators
'
export
type
Options
=
{
[
key
:
string
]:
any
}
export
type
StandardOptions
=
{
loopIntervalMs
?:
number
port
?:
number
hostname
?:
string
logLevel
?:
LogLevel
}
export
type
OptionsSpec
<
TOptions
extends
Options
>
=
{
[
P
in
keyof
Required
<
TOptions
>
]:
{
validator
:
(
spec
?:
Spec
<
TOptions
[
P
]
>
)
=>
ValidatorSpec
<
TOptions
[
P
]
>
desc
:
string
default
?:
TOptions
[
P
]
public
?:
boolean
}
}
export
type
MetricsV2
=
Record
<
any
,
Metric
>
export
type
StandardMetrics
=
{
metadata
:
Gauge
unhandledErrors
:
Counter
}
export
type
MetricsSpec
<
TMetrics
extends
MetricsV2
>
=
{
[
P
in
keyof
Required
<
TMetrics
>
]:
{
type
:
new
(
configuration
:
any
)
=>
TMetrics
[
P
]
desc
:
string
labels
?:
string
[]
}
}
export
type
ExpressRouter
=
Router
import
{
ExpressRouter
}
from
'
./router
'
import
{
Logger
}
from
'
../common/logger
'
import
{
Metrics
,
MetricsSpec
,
StandardMetrics
,
makeStdMetricsSpec
,
}
from
'
./metrics
'
import
{
Options
,
OptionsSpec
,
StandardOptions
,
stdOptionsSpec
,
getPublicOptions
,
}
from
'
./options
'
/**
* BaseServiceV2 is an advanced but simple base class for long-running TypeScript services.
*/
export
abstract
class
BaseServiceV2
<
TOptions
extends
Options
,
TMetrics
extends
Metrics
V2
,
TMetrics
extends
Metrics
,
TServiceState
>
{
/**
...
...
@@ -133,17 +108,13 @@ export abstract class BaseServiceV2<
/**
* @param params Options for the construction of the service.
* @param params.name Name for the service. This name will determine the prefix used for logging,
* metrics, and loading environment variables.
* @param params.optionsSpec Settings for input options. You must specify at least a
* description for each option.
* @param params.metricsSpec Settings that define which metrics are collected. All metrics that
* you plan to collect must be defined within this object.
* @param params.name Name for the service.
* @param params.optionsSpec Settings for input options.
* @param params.metricsSpec Settings that define which metrics are collected.
* @param params.options Options to pass to the service.
* @param params.loops Whether or not the service should loop. Defaults to true.
* @param params.loopIntervalMs Loop interval in milliseconds. Defaults to zero.
* @param params.port Port for the app server. Defaults to 7300.
* @param params.hostname Hostname for the app server. Defaults to 0.0.0.0.
* @param params.useEnv Whether or not to load options from the environment. Defaults to true.
* @param params.useArgv Whether or not to load options from the command line. Defaults to true.
*/
constructor
(
private
readonly
params
:
{
...
...
@@ -151,73 +122,23 @@ export abstract class BaseServiceV2<
version
:
string
optionsSpec
:
OptionsSpec
<
TOptions
>
metricsSpec
:
MetricsSpec
<
TMetrics
>
options
?:
Partial
<
TOptions
>
options
?:
Partial
<
TOptions
&
StandardOptions
>
loop
?:
boolean
loopIntervalMs
?:
number
port
?:
number
hostname
?:
string
logLevel
?:
LogLevel
}
)
{
this
.
loop
=
params
.
loop
!==
undefined
?
params
.
loop
:
true
this
.
state
=
{}
as
TServiceState
const
stdOptionsSpec
:
OptionsSpec
<
StandardOptions
>
=
{
loopIntervalMs
:
{
validator
:
validators
.
num
,
desc
:
'
Loop interval in milliseconds
'
,
default
:
params
.
loopIntervalMs
||
0
,
public
:
true
,
},
port
:
{
validator
:
validators
.
num
,
desc
:
'
Port for the app server
'
,
default
:
params
.
port
||
7300
,
public
:
true
,
},
hostname
:
{
validator
:
validators
.
str
,
desc
:
'
Hostname for the app server
'
,
default
:
params
.
hostname
||
'
0.0.0.0
'
,
public
:
true
,
},
logLevel
:
{
validator
:
validators
.
logLevel
,
desc
:
'
Log level
'
,
default
:
params
.
logLevel
||
'
debug
'
,
public
:
true
,
},
}
// Add default options to options spec.
// Add standard options spec to user options spec.
;(
params
.
optionsSpec
as
any
)
=
{
...
(
params
.
optionsSpec
||
{})
,
...
params
.
optionsSpec
,
...
stdOptionsSpec
,
}
// List of options that can safely be logged.
const
publicOptionNames
=
Object
.
entries
(
params
.
optionsSpec
)
.
filter
(([,
spec
])
=>
{
return
spec
.
public
})
.
map
(([
key
])
=>
{
return
key
})
// Add default metrics to metrics spec.
;(
params
.
metricsSpec
as
any
)
=
{
...(
params
.
metricsSpec
||
{}),
// Users cannot set these options.
metadata
:
{
type
:
Gauge
,
desc
:
'
Service metadata
'
,
labels
:
[
'
name
'
,
'
version
'
].
concat
(
publicOptionNames
),
},
unhandledErrors
:
{
type
:
Counter
,
desc
:
'
Unhandled errors
'
,
},
...
params
.
metricsSpec
,
...
makeStdMetricsSpec
(
params
.
optionsSpec
),
}
/**
...
...
@@ -328,12 +249,12 @@ export abstract class BaseServiceV2<
this
.
hostname
=
this
.
options
.
hostname
// Set up everything else.
this
.
healthy
=
true
this
.
loopIntervalMs
=
this
.
options
.
loopIntervalMs
this
.
logger
=
new
Logger
({
name
:
params
.
name
,
level
:
this
.
options
.
logLevel
,
})
this
.
healthy
=
true
// Gracefully handle stop signals.
const
maxSignalCount
=
3
...
...
@@ -364,7 +285,7 @@ export abstract class BaseServiceV2<
{
name
:
params
.
name
,
version
:
params
.
version
,
...
publicOptionNames
.
reduce
((
acc
,
key
)
=>
{
...
getPublicOptions
(
params
.
optionsSpec
)
.
reduce
((
acc
,
key
)
=>
{
if
(
key
in
stdOptionsSpec
)
{
acc
[
key
]
=
this
.
options
[
key
].
toString
()
}
else
{
...
...
packages/common-ts/src/base-service/base-service.ts
View file @
c68fb1e2
/* Imports: Internal */
import
{
Logger
}
from
'
../common/logger
'
import
{
Metrics
}
from
'
../common/metrics
'
import
{
Legacy
Metrics
}
from
'
../common/metrics
'
type
OptionSettings
<
TOptions
>
=
{
[
P
in
keyof
TOptions
]?:
{
...
...
@@ -11,7 +11,7 @@ type OptionSettings<TOptions> = {
type
BaseServiceOptions
<
T
>
=
T
&
{
logger
?:
Logger
metrics
?:
Metrics
metrics
?:
Legacy
Metrics
}
/**
...
...
@@ -22,7 +22,7 @@ export class BaseService<T> {
protected
name
:
string
protected
options
:
T
protected
logger
:
Logger
protected
metrics
:
Metrics
protected
metrics
:
Legacy
Metrics
protected
initialized
=
false
protected
running
=
false
...
...
packages/common-ts/src/base-service/index.ts
View file @
c68fb1e2
...
...
@@ -2,3 +2,5 @@ export * from './base-service'
export
*
from
'
./base-service-v2
'
export
*
from
'
./validators
'
export
*
from
'
./metrics
'
export
*
from
'
./options
'
export
*
from
'
./router
'
packages/common-ts/src/base-service/metrics.ts
View file @
c68fb1e2
...
...
@@ -5,8 +5,59 @@ import {
Summary
as
PSummary
,
}
from
'
prom-client
'
import
{
OptionsSpec
,
getPublicOptions
}
from
'
./options
'
// Prometheus metrics re-exported.
export
class
Gauge
extends
PGauge
<
string
>
{}
export
class
Counter
extends
PCounter
<
string
>
{}
export
class
Histogram
extends
PHistogram
<
string
>
{}
export
class
Summary
extends
PSummary
<
string
>
{}
export
type
Metric
=
Gauge
|
Counter
|
Histogram
|
Summary
/**
* Metrics that are available for a given service.
*/
export
type
Metrics
=
Record
<
any
,
Metric
>
/**
* Specification for metrics.
*/
export
type
MetricsSpec
<
TMetrics
extends
Metrics
>
=
{
[
P
in
keyof
Required
<
TMetrics
>
]:
{
type
:
new
(
configuration
:
any
)
=>
TMetrics
[
P
]
desc
:
string
labels
?:
string
[]
}
}
/**
* Standard metrics that are always available.
*/
export
type
StandardMetrics
=
{
metadata
:
Gauge
unhandledErrors
:
Counter
}
/**
* Generates a standard metrics specification. Needs to be a function because the labels for
* service metadata are dynamic dependent on the list of given options.
*
* @param options Options to include in the service metadata.
* @returns Metrics specification.
*/
export
const
makeStdMetricsSpec
=
(
optionsSpec
:
OptionsSpec
<
any
>
):
MetricsSpec
<
StandardMetrics
>
=>
{
return
{
// Users cannot set these options.
metadata
:
{
type
:
Gauge
,
desc
:
'
Service metadata
'
,
labels
:
[
'
name
'
,
'
version
'
].
concat
(
getPublicOptions
(
optionsSpec
)),
},
unhandledErrors
:
{
type
:
Counter
,
desc
:
'
Unhandled errors
'
,
},
}
}
packages/common-ts/src/base-service/options.ts
0 → 100644
View file @
c68fb1e2
import
{
ValidatorSpec
,
Spec
}
from
'
envalid
'
import
{
LogLevel
}
from
'
../common/logger
'
import
{
validators
}
from
'
./validators
'
/**
* Options for a service.
*/
export
type
Options
=
{
[
key
:
string
]:
any
}
/**
* Specification for options.
*/
export
type
OptionsSpec
<
TOptions
extends
Options
>
=
{
[
P
in
keyof
Required
<
TOptions
>
]:
{
validator
:
(
spec
?:
Spec
<
TOptions
[
P
]
>
)
=>
ValidatorSpec
<
TOptions
[
P
]
>
desc
:
string
default
?:
TOptions
[
P
]
public
?:
boolean
}
}
/**
* Standard options shared by all services.
*/
export
type
StandardOptions
=
{
loopIntervalMs
?:
number
port
?:
number
hostname
?:
string
logLevel
?:
LogLevel
}
/**
* Specification for standard options.
*/
export
const
stdOptionsSpec
:
OptionsSpec
<
StandardOptions
>
=
{
loopIntervalMs
:
{
validator
:
validators
.
num
,
desc
:
'
Loop interval in milliseconds, only applies if service is set to loop
'
,
default
:
0
,
public
:
true
,
},
port
:
{
validator
:
validators
.
num
,
desc
:
'
Port for the app server
'
,
default
:
7300
,
public
:
true
,
},
hostname
:
{
validator
:
validators
.
str
,
desc
:
'
Hostname for the app server
'
,
default
:
'
0.0.0.0
'
,
public
:
true
,
},
logLevel
:
{
validator
:
validators
.
logLevel
,
desc
:
'
Log level
'
,
default
:
'
debug
'
,
public
:
true
,
},
}
/**
* Gets the list of public option names from an options specification.
*
* @param optionsSpec Options specification.
* @returns List of public option names.
*/
export
const
getPublicOptions
=
(
optionsSpec
:
OptionsSpec
<
Options
>
):
string
[]
=>
{
return
Object
.
keys
(
optionsSpec
).
filter
((
key
)
=>
{
return
optionsSpec
[
key
].
public
})
}
packages/common-ts/src/base-service/router.ts
0 → 100644
View file @
c68fb1e2
import
{
Router
}
from
'
express
'
/**
* Express router re-exported.
*/
export
type
ExpressRouter
=
Router
packages/common-ts/src/common/metrics.ts
View file @
c68fb1e2
...
...
@@ -14,7 +14,7 @@ export interface MetricsOptions {
labels
?:
Object
}
export
class
Metrics
{
export
class
Legacy
Metrics
{
options
:
MetricsOptions
client
:
typeof
prometheus
registry
:
Registry
...
...
packages/data-transport-layer/src/services/l1-ingestion/service.ts
View file @
c68fb1e2
/* Imports: External */
import
{
fromHexString
,
getChainId
,
sleep
}
from
'
@eth-optimism/core-utils
'
import
{
BaseService
,
Metrics
}
from
'
@eth-optimism/common-ts
'
import
{
BaseService
,
Legacy
Metrics
}
from
'
@eth-optimism/common-ts
'
import
{
TypedEvent
}
from
'
@eth-optimism/contracts/dist/types/common
'
import
{
BaseProvider
,
StaticJsonRpcProvider
}
from
'
@ethersproject/providers
'
import
{
LevelUp
}
from
'
levelup
'
...
...
@@ -31,7 +31,7 @@ interface L1IngestionMetrics {
const
registerMetrics
=
({
client
,
registry
,
}:
Metrics
):
L1IngestionMetrics
=>
({
}:
Legacy
Metrics
):
L1IngestionMetrics
=>
({
highestSyncedL1Block
:
new
client
.
Gauge
({
name
:
'
data_transport_layer_highest_synced_l1_block
'
,
help
:
'
Highest Synced L1 Block Number
'
,
...
...
@@ -52,7 +52,7 @@ const registerMetrics = ({
export
interface
L1IngestionServiceOptions
extends
L1DataTransportServiceOptions
{
db
:
LevelUp
metrics
:
Metrics
metrics
:
Legacy
Metrics
}
const
optionSettings
=
{
...
...
packages/data-transport-layer/src/services/l2-ingestion/service.ts
View file @
c68fb1e2
/* Imports: External */
import
{
BaseService
,
Metrics
}
from
'
@eth-optimism/common-ts
'
import
{
BaseService
,
Legacy
Metrics
}
from
'
@eth-optimism/common-ts
'
import
{
StaticJsonRpcProvider
}
from
'
@ethersproject/providers
'
import
{
getChainId
,
sleep
,
toRpcHexString
}
from
'
@eth-optimism/core-utils
'
import
{
BigNumber
}
from
'
ethers
'
...
...
@@ -22,7 +22,7 @@ interface L2IngestionMetrics {
const
registerMetrics
=
({
client
,
registry
,
}:
Metrics
):
L2IngestionMetrics
=>
({
}:
Legacy
Metrics
):
L2IngestionMetrics
=>
({
highestSyncedL2Block
:
new
client
.
Gauge
({
name
:
'
data_transport_layer_highest_synced_l2_block
'
,
help
:
'
Highest Synced L2 Block Number
'
,
...
...
packages/data-transport-layer/src/services/main/service.ts
View file @
c68fb1e2
/* Imports: External */
import
{
BaseService
,
Metrics
}
from
'
@eth-optimism/common-ts
'
import
{
BaseService
,
Legacy
Metrics
}
from
'
@eth-optimism/common-ts
'
import
{
LevelUp
}
from
'
levelup
'
import
level
from
'
level
'
import
{
Counter
}
from
'
prom-client
'
...
...
@@ -27,7 +27,7 @@ export interface L1DataTransportServiceOptions {
l2RpcProviderUser
?:
string
l2RpcProviderPassword
?:
string
l1SyncShutoffBlock
?:
number
metrics
?:
Metrics
metrics
?:
Legacy
Metrics
dbPath
:
string
logsPerPollingInterval
:
number
pollingInterval
:
number
...
...
@@ -66,7 +66,7 @@ export class L1DataTransportService extends BaseService<L1DataTransportServiceOp
l1IngestionService
?:
L1IngestionService
l2IngestionService
?:
L2IngestionService
l1TransportServer
:
L1TransportServer
metrics
:
Metrics
metrics
:
Legacy
Metrics
failureCounter
:
Counter
<
string
>
}
=
{}
as
any
...
...
@@ -81,7 +81,7 @@ export class L1DataTransportService extends BaseService<L1DataTransportServiceOp
this
.
logger
.
info
(
`L2 chain ID is:
${
this
.
options
.
l2ChainId
}
`
)
this
.
logger
.
info
(
`BSS HF1 will activate at:
${
bssHf1Index
}
`
)
this
.
state
.
metrics
=
new
Metrics
({
this
.
state
.
metrics
=
new
Legacy
Metrics
({
labels
:
{
environment
:
this
.
options
.
nodeEnv
,
network
:
this
.
options
.
ethNetworkName
,
...
...
packages/data-transport-layer/src/services/server/service.ts
View file @
c68fb1e2
/* Imports: External */
import
{
BaseService
,
Logger
,
Metrics
}
from
'
@eth-optimism/common-ts
'
import
{
BaseService
,
Logger
,
Legacy
Metrics
}
from
'
@eth-optimism/common-ts
'
import
express
,
{
Request
,
Response
}
from
'
express
'
import
promBundle
from
'
express-prom-bundle
'
import
cors
from
'
cors
'
...
...
@@ -27,7 +27,7 @@ import { L1DataTransportServiceOptions } from '../main/service'
export
interface
L1TransportServerOptions
extends
L1DataTransportServiceOptions
{
db
:
LevelUp
metrics
:
Metrics
metrics
:
Legacy
Metrics
}
const
optionSettings
=
{
...
...
packages/drippie-mon/src/service.ts
View file @
c68fb1e2
import
{
BaseServiceV2
,
StandardOptions
,
Gauge
,
Counter
,
validators
,
...
...
@@ -30,13 +31,15 @@ export class DrippieMonService extends BaseServiceV2<
DrippieMonMetrics
,
DrippieMonState
>
{
constructor
(
options
?:
Partial
<
DrippieMonOptions
>
)
{
constructor
(
options
?:
Partial
<
DrippieMonOptions
&
StandardOptions
>
)
{
super
({
version
,
name
:
'
drippie-mon
'
,
loop
:
true
,
options
:
{
loopIntervalMs
:
60
_000
,
options
,
...
options
,
},
optionsSpec
:
{
rpc
:
{
validator
:
validators
.
provider
,
...
...
packages/fault-detector/src/service.ts
View file @
c68fb1e2
import
{
BaseServiceV2
,
StandardOptions
,
ExpressRouter
,
Gauge
,
validators
,
...
...
@@ -39,13 +40,15 @@ type State = {
}
export
class
FaultDetector
extends
BaseServiceV2
<
Options
,
Metrics
,
State
>
{
constructor
(
options
?:
Partial
<
Options
>
)
{
constructor
(
options
?:
Partial
<
Options
&
StandardOptions
>
)
{
super
({
version
,
name
:
'
fault-detector
'
,
loop
:
true
,
options
:
{
loopIntervalMs
:
1000
,
options
,
...
options
,
},
optionsSpec
:
{
l1RpcProvider
:
{
validator
:
validators
.
provider
,
...
...
packages/replica-healthcheck/src/service.ts
View file @
c68fb1e2
import
{
Provider
,
Block
}
from
'
@ethersproject/abstract-provider
'
import
{
BaseServiceV2
,
StandardOptions
,
Counter
,
Gauge
,
validators
,
...
...
@@ -32,12 +33,14 @@ export class HealthcheckService extends BaseServiceV2<
HealthcheckMetrics
,
HealthcheckState
>
{
constructor
(
options
?:
Partial
<
HealthcheckOptions
>
)
{
constructor
(
options
?:
Partial
<
HealthcheckOptions
&
StandardOptions
>
)
{
super
({
version
,
name
:
'
healthcheck
'
,
options
:
{
loopIntervalMs
:
5000
,
options
,
...
options
,
},
optionsSpec
:
{
referenceRpcProvider
:
{
validator
:
validators
.
provider
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment