@@ -23,76 +23,156 @@ import (
23
23
"crypto"
24
24
"fmt"
25
25
"github.com/nuts-foundation/nuts-node/core"
26
+ "github.com/prometheus/client_golang/prometheus"
26
27
"regexp"
28
+ "time"
27
29
)
28
30
29
31
// wrapper wraps a Storage backend and checks the validity of the kid on each of the relevant functions before
30
32
// forwarding the call to the wrapped backend.
31
- type wrapper struct {
33
+ type validationWrapper struct {
32
34
kidPattern * regexp.Regexp
33
35
wrappedBackend Storage
34
36
}
35
37
36
- func (w wrapper ) Name () string {
38
+ func (w validationWrapper ) Name () string {
37
39
return w .wrappedBackend .Name ()
38
40
}
39
41
40
- func (w wrapper ) CheckHealth () map [string ]core.Health {
42
+ func (w validationWrapper ) CheckHealth () map [string ]core.Health {
41
43
return w .wrappedBackend .CheckHealth ()
42
44
}
43
45
44
46
// NewValidatedKIDBackendWrapper creates a new wrapper for storage backends.
45
47
// Every call to the backend which takes a kid as param, gets the kid validated against the provided kidPattern.
46
48
func NewValidatedKIDBackendWrapper (backend Storage , kidPattern * regexp.Regexp ) Storage {
47
- return wrapper {
49
+ return validationWrapper {
48
50
kidPattern : kidPattern ,
49
51
wrappedBackend : backend ,
50
52
}
51
53
}
52
54
53
- func (w wrapper ) validateKID (kid string ) error {
55
+ func (w validationWrapper ) validateKID (kid string ) error {
54
56
if ! w .kidPattern .MatchString (kid ) {
55
57
return fmt .Errorf ("invalid key ID: %s" , kid )
56
58
}
57
59
return nil
58
60
}
59
61
60
- func (w wrapper ) GetPrivateKey (ctx context.Context , keyName string , version string ) (crypto.Signer , error ) {
62
+ func (w validationWrapper ) GetPrivateKey (ctx context.Context , keyName string , version string ) (crypto.Signer , error ) {
61
63
if err := w .validateKID (keyName ); err != nil {
62
64
return nil , err
63
65
}
64
66
return w .wrappedBackend .GetPrivateKey (ctx , keyName , version )
65
67
}
66
68
67
- func (w wrapper ) PrivateKeyExists (ctx context.Context , keyName string , version string ) (bool , error ) {
69
+ func (w validationWrapper ) PrivateKeyExists (ctx context.Context , keyName string , version string ) (bool , error ) {
68
70
if err := w .validateKID (keyName ); err != nil {
69
71
return false , err
70
72
}
71
73
return w .wrappedBackend .PrivateKeyExists (ctx , keyName , version )
72
74
}
73
75
74
- func (w wrapper ) SavePrivateKey (ctx context.Context , kid string , key crypto.PrivateKey ) error {
76
+ func (w validationWrapper ) SavePrivateKey (ctx context.Context , kid string , key crypto.PrivateKey ) error {
75
77
if err := w .validateKID (kid ); err != nil {
76
78
return err
77
79
}
78
80
return w .wrappedBackend .SavePrivateKey (ctx , kid , key )
79
81
}
80
82
81
- func (w wrapper ) DeletePrivateKey (ctx context.Context , keyName string ) error {
83
+ func (w validationWrapper ) DeletePrivateKey (ctx context.Context , keyName string ) error {
82
84
if err := w .validateKID (keyName ); err != nil {
83
85
return err
84
86
}
85
87
return w .wrappedBackend .DeletePrivateKey (ctx , keyName )
86
88
}
87
89
88
- func (w wrapper ) ListPrivateKeys (ctx context.Context ) []KeyNameVersion {
90
+ func (w validationWrapper ) ListPrivateKeys (ctx context.Context ) []KeyNameVersion {
89
91
return w .wrappedBackend .ListPrivateKeys (ctx )
90
92
}
91
93
92
- func (w wrapper ) NewPrivateKey (ctx context.Context , keyName string ) (crypto.PublicKey , string , error ) {
94
+ func (w validationWrapper ) NewPrivateKey (ctx context.Context , keyName string ) (crypto.PublicKey , string , error ) {
93
95
publicKey , version , err := w .wrappedBackend .NewPrivateKey (ctx , keyName )
94
96
if err != nil {
95
97
return nil , "" , err
96
98
}
97
99
return publicKey , version , err
98
100
}
101
+
102
+ func NewPrometheusWrapper (backend Storage ) * PrometheusWrapper {
103
+ return & PrometheusWrapper {
104
+ wrappedBackend : backend ,
105
+ opDurationMetric : prometheus .NewHistogramVec (prometheus.HistogramOpts {
106
+ Name : "crypto_storage_op_duration_seconds" ,
107
+ Help : "Duration of crypto storage operations in seconds (experimental, may be removed without notice)" ,
108
+ Buckets : []float64 {0.01 , 0.05 , 0.1 , .5 , 1 , 2 },
109
+ }, []string {"op" }),
110
+ }
111
+ }
112
+
113
+ var _ Storage = (* PrometheusWrapper )(nil )
114
+
115
+ type PrometheusWrapper struct {
116
+ wrappedBackend Storage
117
+ opDurationMetric * prometheus.HistogramVec
118
+ }
119
+
120
+ func (p PrometheusWrapper ) Collectors () []prometheus.Collector {
121
+ return []prometheus.Collector {p .opDurationMetric }
122
+ }
123
+
124
+ func (p PrometheusWrapper ) Name () string {
125
+ return p .wrappedBackend .Name ()
126
+ }
127
+
128
+ func (p PrometheusWrapper ) CheckHealth () map [string ]core.Health {
129
+ return p .wrappedBackend .CheckHealth ()
130
+ }
131
+
132
+ func (p PrometheusWrapper ) NewPrivateKey (ctx context.Context , keyName string ) (crypto.PublicKey , string , error ) {
133
+ start := time .Now ()
134
+ defer func () {
135
+ p .opDurationMetric .WithLabelValues ("new_private_key" ).Observe (time .Since (start ).Seconds ())
136
+ }()
137
+ return p .wrappedBackend .NewPrivateKey (ctx , keyName )
138
+ }
139
+
140
+ func (p PrometheusWrapper ) GetPrivateKey (ctx context.Context , keyName string , version string ) (crypto.Signer , error ) {
141
+ start := time .Now ()
142
+ defer func () {
143
+ p .opDurationMetric .WithLabelValues ("get_private_key" ).Observe (time .Since (start ).Seconds ())
144
+ }()
145
+ return p .wrappedBackend .GetPrivateKey (ctx , keyName , version )
146
+ }
147
+
148
+ func (p PrometheusWrapper ) PrivateKeyExists (ctx context.Context , keyName string , version string ) (bool , error ) {
149
+ start := time .Now ()
150
+ defer func () {
151
+ p .opDurationMetric .WithLabelValues ("private_key_exists" ).Observe (time .Since (start ).Seconds ())
152
+ }()
153
+ return p .wrappedBackend .PrivateKeyExists (ctx , keyName , version )
154
+ }
155
+
156
+ func (p PrometheusWrapper ) SavePrivateKey (ctx context.Context , keyname string , key crypto.PrivateKey ) error {
157
+ start := time .Now ()
158
+ defer func () {
159
+ p .opDurationMetric .WithLabelValues ("save_private_key" ).Observe (time .Since (start ).Seconds ())
160
+ }()
161
+ return p .wrappedBackend .SavePrivateKey (ctx , keyname , key )
162
+ }
163
+
164
+ func (p PrometheusWrapper ) ListPrivateKeys (ctx context.Context ) []KeyNameVersion {
165
+ start := time .Now ()
166
+ defer func () {
167
+ p .opDurationMetric .WithLabelValues ("list_private_keys" ).Observe (time .Since (start ).Seconds ())
168
+ }()
169
+ return p .wrappedBackend .ListPrivateKeys (ctx )
170
+ }
171
+
172
+ func (p PrometheusWrapper ) DeletePrivateKey (ctx context.Context , keyName string ) error {
173
+ start := time .Now ()
174
+ defer func () {
175
+ p .opDurationMetric .WithLabelValues ("delete_private_key" ).Observe (time .Since (start ).Seconds ())
176
+ }()
177
+ return p .wrappedBackend .DeletePrivateKey (ctx , keyName )
178
+ }
0 commit comments