11package main
22
33import (
4+ "context"
45 "crypto/tls"
56 "crypto/x509"
67 "os"
78 "strconv"
89 "time"
910
11+ "github.com/pkg/errors"
1012 "github.com/sirupsen/logrus"
13+ "go.opentelemetry.io/otel"
14+ "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc"
15+ metricsdk "go.opentelemetry.io/otel/sdk/metric"
16+ "go.opentelemetry.io/otel/sdk/resource"
17+ semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
18+ "google.golang.org/grpc"
19+ "google.golang.org/grpc/credentials/insecure"
1120
1221 ocpp16 "github.com/lorenzodonini/ocpp-go/ocpp1.6"
1322 "github.com/lorenzodonini/ocpp-go/ocpp1.6/core"
@@ -28,6 +37,8 @@ const (
2837 envVarCaCertificate = "CA_CERTIFICATE_PATH"
2938 envVarServerCertificate = "SERVER_CERTIFICATE_PATH"
3039 envVarServerCertificateKey = "SERVER_CERTIFICATE_KEY_PATH"
40+ envVarMetricsEnabled = "METRICS_ENABLED"
41+ envVarMetricsAddress = "METRICS_ADDRESS"
3142)
3243
3344var log * logrus.Logger
@@ -188,6 +199,54 @@ func exampleRoutine(chargePointID string, handler *CentralSystemHandler) {
188199 }
189200}
190201
202+ // sets up OTLP metrics exporter
203+ func setupMetrics (address string ) error {
204+ grpcOpts := []grpc.DialOption {
205+ grpc .WithTransportCredentials (insecure .NewCredentials ()),
206+ }
207+
208+ client , err := grpc .NewClient (address , grpcOpts ... )
209+
210+ if err != nil {
211+ return errors .Wrap (err , "failed to create gRPC connection to collector" )
212+ }
213+
214+ ctx := context .Background ()
215+
216+ exporter , err := otlpmetricgrpc .New (ctx , otlpmetricgrpc .WithGRPCConn (client ))
217+ if err != nil {
218+ return errors .Wrap (err , "failed to create otlp metric exporter" )
219+ }
220+
221+ resource , err := resource .New (ctx ,
222+ resource .WithAttributes (
223+ semconv .ServiceNameKey .String ("centralSystem-demo" ),
224+ semconv .ServiceVersionKey .String ("example" ),
225+ ),
226+ resource .WithFromEnv (),
227+ resource .WithContainer (),
228+ resource .WithOS (),
229+ resource .WithOSType (),
230+ resource .WithHost (),
231+ )
232+ if err != nil {
233+ return errors .Wrap (err , "failed to create resource" )
234+ }
235+
236+ meterProvider := metricsdk .NewMeterProvider (
237+ metricsdk .WithReader (
238+ metricsdk .NewPeriodicReader (
239+ exporter ,
240+ metricsdk .WithInterval (10 * time .Second ),
241+ ),
242+ ),
243+ metricsdk .WithResource (resource ),
244+ )
245+
246+ otel .SetMeterProvider (meterProvider )
247+ return nil
248+ }
249+
191250// Start function
192251func main () {
193252 // Load config from ENV
@@ -198,6 +257,16 @@ func main() {
198257 } else {
199258 log .Printf ("no valid %v environment variable found, using default port" , envVarServerPort )
200259 }
260+
261+ // Setup metrics if enabled
262+ if t , _ := os .LookupEnv (envVarMetricsEnabled ); t == "true" {
263+ address , _ := os .LookupEnv (envVarMetricsAddress )
264+ if err := setupMetrics (address ); err != nil {
265+ log .Error (err )
266+ return
267+ }
268+ }
269+
201270 // Check if TLS enabled
202271 t , _ := os .LookupEnv (envVarTls )
203272 tlsEnabled , _ := strconv .ParseBool (t )
@@ -207,6 +276,7 @@ func main() {
207276 } else {
208277 centralSystem = setupCentralSystem ()
209278 }
279+
210280 // Support callbacks for all OCPP 1.6 profiles
211281 handler := & CentralSystemHandler {chargePoints : map [string ]* ChargePointState {}}
212282 centralSystem .SetCoreHandler (handler )
0 commit comments