Skip to content

Commit 8bd95d9

Browse files
authored
Merge pull request #121 from kaleido-io/add-monitoring-support
2 parents 1c064fd + 89cf5c2 commit 8bd95d9

File tree

12 files changed

+173
-66
lines changed

12 files changed

+173
-66
lines changed

.github/workflows/go.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
run: docker save --output firefly.tar.gz hyperledger/firefly
6161

6262
- name: Upload Docker image
63-
uses: actions/upload-artifact@v3
63+
uses: actions/upload-artifact@v4
6464
with:
6565
name: firefly-docker
6666
path: firefly.tar.gz
@@ -146,7 +146,7 @@ jobs:
146146
go-version: 1.22
147147

148148
- name: Download Docker image
149-
uses: actions/download-artifact@v3
149+
uses: actions/download-artifact@v4
150150
with:
151151
name: firefly-docker
152152

@@ -165,7 +165,7 @@ jobs:
165165
run: ./test/e2e/run.sh
166166

167167
- name: Archive container logs
168-
uses: actions/upload-artifact@v3
168+
uses: actions/upload-artifact@v4
169169
if: always()
170170
with:
171171
name: container-logs-${{ matrix.test-suite }}-${{ matrix.blockchain-provider }}-${{ matrix.blockchain-connector }}-${{ matrix.database-type }}-${{ matrix.token-provider }}

.github/workflows/integration.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575
run: ./test/e2e/run.sh
7676

7777
- name: Archive container logs
78-
uses: actions/upload-artifact@v3
78+
uses: actions/upload-artifact@v4
7979
if: always()
8080
with:
8181
name: container-logs-${{ matrix.test-suite }}-${{ matrix.blockchain-node }}-${{ matrix.database-type }}
@@ -111,7 +111,7 @@ jobs:
111111
run: ./test/e2e/run.sh
112112

113113
- name: Archive container logs
114-
uses: actions/upload-artifact@v3
114+
uses: actions/upload-artifact@v4
115115
if: always()
116116
with:
117117
name: container-logs-TestEthereumV1MigrationE2ESuite-geth-postgres

doc-site/.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- uses: actions/setup-python@v4
2424
with:
2525
python-version: 3.x
26-
- uses: actions/cache@v2
26+
- uses: actions/cache@v4
2727
with:
2828
key: ${{ github.ref }}
2929
path: .cache

doc-site/docs/reference/config.md

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -406,30 +406,70 @@ title: Configuration Reference
406406

407407
## metrics
408408

409+
|Key|Description|Type|Default Value|
410+
|---|-----------|----|-------------|
411+
|address|Deprecated - use monitoring.address instead|`int`|`127.0.0.1`
412+
|enabled|Deprecated - use monitoring.enabled instead|`boolean`|`true`
413+
|path|Deprecated - use monitoring.metricsPath instead|`string`|`/metrics`
414+
|port|Deprecated - use monitoring.port instead|`int`|`6000`
415+
|publicURL|Deprecated - use monitoring.publicURL instead|URL `string`|`<nil>`
416+
|readTimeout|Deprecated - use monitoring.readTimeout instead|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s`
417+
|shutdownTimeout|The maximum amount of time to wait for any open HTTP requests to finish before shutting down the HTTP server|[`time.Duration`](https://pkg.go.dev/time#Duration)|`10s`
418+
|writeTimeout|Deprecated - use monitoring.writeTimeout instead|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s`
419+
420+
## metrics.auth
421+
422+
|Key|Description|Type|Default Value|
423+
|---|-----------|----|-------------|
424+
|type|The auth plugin to use for server side authentication of requests|`string`|`<nil>`
425+
426+
## metrics.auth.basic
427+
428+
|Key|Description|Type|Default Value|
429+
|---|-----------|----|-------------|
430+
|passwordfile|The path to a .htpasswd file to use for authenticating requests. Passwords should be hashed with bcrypt.|`string`|`<nil>`
431+
432+
## metrics.tls
433+
434+
|Key|Description|Type|Default Value|
435+
|---|-----------|----|-------------|
436+
|ca|The TLS certificate authority in PEM format (this option is ignored if caFile is also set)|`string`|`<nil>`
437+
|caFile|The path to the CA file for TLS on this API|`string`|`<nil>`
438+
|cert|The TLS certificate in PEM format (this option is ignored if certFile is also set)|`string`|`<nil>`
439+
|certFile|The path to the certificate file for TLS on this API|`string`|`<nil>`
440+
|clientAuth|Enables or disables client auth for TLS on this API|`string`|`<nil>`
441+
|enabled|Enables or disables TLS on this API|`boolean`|`false`
442+
|insecureSkipHostVerify|When to true in unit test development environments to disable TLS verification. Use with extreme caution|`boolean`|`<nil>`
443+
|key|The TLS certificate key in PEM format (this option is ignored if keyFile is also set)|`string`|`<nil>`
444+
|keyFile|The path to the private key file for TLS on this API|`string`|`<nil>`
445+
|requiredDNAttributes|A set of required subject DN attributes. Each entry is a regular expression, and the subject certificate must have a matching attribute of the specified type (CN, C, O, OU, ST, L, STREET, POSTALCODE, SERIALNUMBER are valid attributes)|`map[string]string`|`<nil>`
446+
447+
## monitoring
448+
409449
|Key|Description|Type|Default Value|
410450
|---|-----------|----|-------------|
411451
|address|The IP address on which the metrics HTTP API should listen|`int`|`127.0.0.1`
412452
|enabled|Enables the metrics API|`boolean`|`true`
413-
|path|The path from which to serve the Prometheus metrics|`string`|`/metrics`
453+
|metricsPath|The path from which to serve the Prometheus metrics|`string`|`/metrics`
414454
|port|The port on which the metrics HTTP API should listen|`int`|`6000`
415455
|publicURL|The fully qualified public URL for the metrics API. This is used for building URLs in HTTP responses and in OpenAPI Spec generation|URL `string`|`<nil>`
416456
|readTimeout|The maximum time to wait when reading from an HTTP connection|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s`
417457
|shutdownTimeout|The maximum amount of time to wait for any open HTTP requests to finish before shutting down the HTTP server|[`time.Duration`](https://pkg.go.dev/time#Duration)|`10s`
418458
|writeTimeout|The maximum time to wait when writing to an HTTP connection|[`time.Duration`](https://pkg.go.dev/time#Duration)|`15s`
419459

420-
## metrics.auth
460+
## monitoring.auth
421461

422462
|Key|Description|Type|Default Value|
423463
|---|-----------|----|-------------|
424464
|type|The auth plugin to use for server side authentication of requests|`string`|`<nil>`
425465

426-
## metrics.auth.basic
466+
## monitoring.auth.basic
427467

428468
|Key|Description|Type|Default Value|
429469
|---|-----------|----|-------------|
430470
|passwordfile|The path to a .htpasswd file to use for authenticating requests. Passwords should be hashed with bcrypt.|`string`|`<nil>`
431471

432-
## metrics.tls
472+
## monitoring.tls
433473

434474
|Key|Description|Type|Default Value|
435475
|---|-----------|----|-------------|

internal/apiserver/metrics_server.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright © 2022 Kaleido, Inc.
1+
// Copyright © 2025 Kaleido, Inc.
22
//
33
// SPDX-License-Identifier: Apache-2.0
44
//
@@ -21,11 +21,17 @@ import (
2121
)
2222

2323
const (
24-
MetricsEnabled = "enabled"
25-
MetricsPath = "path"
24+
Enabled = "enabled"
25+
DeprecatedMetricsPath = "path"
26+
MetricsPath = "metricsPath"
2627
)
2728

28-
func initMetricsConfig(config config.Section) {
29-
config.AddKnownKey(MetricsEnabled, true)
29+
func initDeprecatedMetricsConfig(config config.Section) {
30+
config.AddKnownKey(Enabled, true)
31+
config.AddKnownKey(DeprecatedMetricsPath, "/metrics")
32+
}
33+
34+
func initMonitoringConfig(config config.Section) {
35+
config.AddKnownKey(Enabled, true)
3036
config.AddKnownKey(MetricsPath, "/metrics")
3137
}

internal/apiserver/server.go

Lines changed: 48 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright © 2024 Kaleido, Inc.
1+
// Copyright © 2025 Kaleido, Inc.
22
//
33
// SPDX-License-Identifier: Apache-2.0
44
//
@@ -42,10 +42,11 @@ import (
4242
)
4343

4444
var (
45-
spiConfig = config.RootSection("spi")
46-
apiConfig = config.RootSection("http")
47-
metricsConfig = config.RootSection("metrics")
48-
corsConfig = config.RootSection("cors")
45+
spiConfig = config.RootSection("spi")
46+
apiConfig = config.RootSection("http")
47+
deprecatedMetricsConfig = config.RootSection("metrics")
48+
monitoringConfig = config.RootSection("monitoring")
49+
corsConfig = config.RootSection("cors")
4950
)
5051

5152
// Server is the external interface for the API Server
@@ -55,31 +56,35 @@ type Server interface {
5556

5657
type apiServer struct {
5758
// Defaults set with config
58-
apiTimeout time.Duration
59-
apiMaxTimeout time.Duration
60-
metricsEnabled bool
61-
ffiSwaggerGen FFISwaggerGen
62-
apiPublicURL string
63-
dynamicPublicURLHeader string
64-
defaultNamespace string
59+
apiTimeout time.Duration
60+
apiMaxTimeout time.Duration
61+
deprecatedMetricsEnabled bool
62+
monitoringEnabled bool
63+
ffiSwaggerGen FFISwaggerGen
64+
apiPublicURL string
65+
dynamicPublicURLHeader string
66+
defaultNamespace string
6567
}
6668

6769
func InitConfig() {
6870
httpserver.InitHTTPConfig(apiConfig, 5000)
6971
httpserver.InitHTTPConfig(spiConfig, 5001)
70-
httpserver.InitHTTPConfig(metricsConfig, 6000)
72+
httpserver.InitHTTPConfig(deprecatedMetricsConfig, 6000)
73+
httpserver.InitHTTPConfig(monitoringConfig, 6000)
7174
httpserver.InitCORSConfig(corsConfig)
72-
initMetricsConfig(metricsConfig)
75+
initDeprecatedMetricsConfig(deprecatedMetricsConfig)
76+
initMonitoringConfig(monitoringConfig)
7377
}
7478

7579
func NewAPIServer() Server {
7680
as := &apiServer{
77-
apiTimeout: config.GetDuration(coreconfig.APIRequestTimeout),
78-
apiMaxTimeout: config.GetDuration(coreconfig.APIRequestMaxTimeout),
79-
dynamicPublicURLHeader: config.GetString(coreconfig.APIDynamicPublicURLHeader),
80-
defaultNamespace: config.GetString(coreconfig.NamespacesDefault),
81-
metricsEnabled: config.GetBool(coreconfig.MetricsEnabled),
82-
ffiSwaggerGen: &ffiSwaggerGen{},
81+
apiTimeout: config.GetDuration(coreconfig.APIRequestTimeout),
82+
apiMaxTimeout: config.GetDuration(coreconfig.APIRequestMaxTimeout),
83+
dynamicPublicURLHeader: config.GetString(coreconfig.APIDynamicPublicURLHeader),
84+
defaultNamespace: config.GetString(coreconfig.NamespacesDefault),
85+
deprecatedMetricsEnabled: config.GetBool(coreconfig.DeprecatedMetricsEnabled),
86+
monitoringEnabled: config.GetBool(coreconfig.MonitoringEnabled),
87+
ffiSwaggerGen: &ffiSwaggerGen{},
8388
}
8489
as.apiPublicURL = as.getPublicURL(apiConfig, "")
8590
return as
@@ -110,15 +115,21 @@ func (as *apiServer) Serve(ctx context.Context, mgr namespace.Manager) (err erro
110115
} else if config.GetBool(coreconfig.LegacyAdminEnabled) {
111116
log.L(ctx).Warnf("Your config includes an 'admin' section, which should be renamed to 'spi' - SPI server will not be enabled until this is corrected")
112117
}
118+
serverName := "metrics"
119+
mConfig := deprecatedMetricsConfig
120+
if as.monitoringEnabled {
121+
serverName = "monitoring"
122+
mConfig = monitoringConfig
123+
}
113124

114-
if as.metricsEnabled {
115-
metricsHTTPServer, err := httpserver.NewHTTPServer(ctx, "metrics", as.createMetricsMuxRouter(), metricsErrChan, metricsConfig, corsConfig, &httpserver.ServerOptions{
125+
if as.deprecatedMetricsEnabled || as.monitoringEnabled {
126+
monitoringServer, err := httpserver.NewHTTPServer(ctx, serverName, as.createMonitoringMuxRouter(), metricsErrChan, mConfig, corsConfig, &httpserver.ServerOptions{
116127
MaximumRequestTimeout: as.apiMaxTimeout,
117128
})
118129
if err != nil {
119130
return err
120131
}
121-
go metricsHTTPServer.ServeHTTP(ctx)
132+
go monitoringServer.ServeHTTP(ctx)
122133
}
123134

124135
return as.waitForServerStop(httpErrChan, spiErrChan, metricsErrChan)
@@ -345,7 +356,7 @@ func (as *apiServer) createMuxRouter(ctx context.Context, mgr namespace.Manager)
345356
r := mux.NewRouter()
346357
hf := as.handlerFactory()
347358

348-
if as.metricsEnabled {
359+
if as.deprecatedMetricsEnabled || as.monitoringEnabled {
349360
r.Use(metrics.GetRestServerInstrumentation().Middleware)
350361
}
351362

@@ -433,7 +444,7 @@ func (as *apiServer) spiWSHandler(mgr namespace.Manager) http.HandlerFunc {
433444

434445
func (as *apiServer) createAdminMuxRouter(mgr namespace.Manager) *mux.Router {
435446
r := mux.NewRouter()
436-
if as.metricsEnabled {
447+
if as.deprecatedMetricsEnabled || as.monitoringEnabled {
437448
r.Use(metrics.GetAdminServerInstrumentation().Middleware)
438449
}
439450
hf := as.handlerFactory()
@@ -468,12 +479,20 @@ func (as *apiServer) createAdminMuxRouter(mgr namespace.Manager) *mux.Router {
468479
return r
469480
}
470481

471-
func (as *apiServer) createMetricsMuxRouter() *mux.Router {
482+
func (as *apiServer) createMonitoringMuxRouter() *mux.Router {
472483
r := mux.NewRouter()
473-
474-
r.Path(config.GetString(coreconfig.MetricsPath)).Handler(promhttp.InstrumentMetricHandler(metrics.Registry(),
484+
metricsPath := config.GetString(coreconfig.DeprecatedMetricsPath)
485+
if as.monitoringEnabled {
486+
metricsPath = config.GetString(coreconfig.MonitoringMetricsPath)
487+
}
488+
r.Path(metricsPath).Handler(promhttp.InstrumentMetricHandler(metrics.Registry(),
475489
promhttp.HandlerFor(metrics.Registry(), promhttp.HandlerOpts{})))
476-
490+
hf := ffapi.HandlerFactory{}
491+
r.HandleFunc("/livez", hf.APIWrapper(func(res http.ResponseWriter, req *http.Request) (status int, err error) {
492+
// a simple liveness check
493+
return http.StatusOK, nil
494+
}))
495+
r.NotFoundHandler = hf.APIWrapper(as.notFoundHandler)
477496
return r
478497
}
479498

internal/apiserver/server_test.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright © 2021 Kaleido, Inc.
1+
// Copyright © 2025 Kaleido, Inc.
22
//
33
// SPDX-License-Identifier: Apache-2.0
44
//
@@ -86,7 +86,7 @@ func TestStartStopServer(t *testing.T) {
8686
InitConfig()
8787
apiConfig.Set(httpserver.HTTPConfPort, 0)
8888
spiConfig.Set(httpserver.HTTPConfPort, 0)
89-
metricsConfig.Set(httpserver.HTTPConfPort, 0)
89+
monitoringConfig.Set(httpserver.HTTPConfPort, 0)
9090
config.Set(coreconfig.UIPath, "test")
9191
config.Set(coreconfig.SPIEnabled, true)
9292
ctx, cancel := context.WithCancel(context.Background())
@@ -105,7 +105,7 @@ func TestStartLegacyAdminConfig(t *testing.T) {
105105
InitConfig()
106106
apiConfig.Set(httpserver.HTTPConfPort, 0)
107107
spiConfig.Set(httpserver.HTTPConfPort, 0)
108-
metricsConfig.Set(httpserver.HTTPConfPort, 0)
108+
monitoringConfig.Set(httpserver.HTTPConfPort, 0)
109109
config.Set(coreconfig.UIPath, "test")
110110
config.Set(coreconfig.LegacyAdminEnabled, true)
111111
ctx, cancel := context.WithCancel(context.Background())
@@ -170,8 +170,8 @@ func TestStartMetricsFail(t *testing.T) {
170170
coreconfig.Reset()
171171
metrics.Clear()
172172
InitConfig()
173-
metricsConfig.Set(httpserver.HTTPConfAddress, "...://")
174-
config.Set(coreconfig.MetricsEnabled, true)
173+
monitoringConfig.Set(httpserver.HTTPConfAddress, "...://")
174+
config.Set(coreconfig.MonitoringEnabled, true)
175175
ctx, cancel := context.WithCancel(context.Background())
176176
cancel() // server will immediately shut down
177177
as := NewAPIServer()
@@ -575,3 +575,17 @@ func TestContractAPIDefaultNS(t *testing.T) {
575575
assert.NoError(t, err)
576576
assert.Equal(t, 200, res.StatusCode())
577577
}
578+
579+
func TestMonitoringServerRoutes(t *testing.T) {
580+
_, _, as := newTestServer()
581+
s := httptest.NewServer(as.createMonitoringMuxRouter())
582+
defer s.Close()
583+
584+
res, err := http.Get(fmt.Sprintf("http://%s/livez", s.Listener.Addr()))
585+
assert.NoError(t, err)
586+
assert.Equal(t, 200, res.StatusCode)
587+
588+
res, err = http.Get(fmt.Sprintf("http://%s/metrics", s.Listener.Addr()))
589+
assert.NoError(t, err)
590+
assert.Equal(t, 200, res.StatusCode)
591+
}

internal/coreconfig/coreconfig.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright © 2024 Kaleido, Inc.
1+
// Copyright © 2025 Kaleido, Inc.
22
//
33
// SPDX-License-Identifier: Apache-2.0
44
//
@@ -287,10 +287,14 @@ var (
287287
MessageWriterBatchTimeout = ffc("message.writer.batchTimeout")
288288
// MessageWriterBatchMaxInserts
289289
MessageWriterBatchMaxInserts = ffc("message.writer.batchMaxInserts")
290-
// MetricsEnabled determines whether metrics will be instrumented and if the metrics server will be enabled or not
291-
MetricsEnabled = ffc("metrics.enabled")
290+
// MetricsEnabled - deprecated, use monitoring.enabled
291+
DeprecatedMetricsEnabled = ffc("metrics.enabled")
292+
// MetricsPath - deprecated, use monitoring.metricsPath
293+
DeprecatedMetricsPath = ffc("metrics.path")
294+
// Monitoring determines whether monitoring routes will be enabled, which contains metrics instruments
295+
MonitoringEnabled = ffc("monitoring.enabled")
292296
// MetricsPath determines what path to serve the Prometheus metrics from
293-
MetricsPath = ffc("metrics.path")
297+
MonitoringMetricsPath = ffc("monitoring.metricsPath")
294298
// NamespacesDefault is the default namespace - must be in the predefines list
295299
NamespacesDefault = ffc("namespaces.default")
296300
// NamespacesPredefined is a list of namespaces to ensure exists, without requiring a broadcast from the network

0 commit comments

Comments
 (0)