diff --git a/.config/supervisord/supervisord.conf b/.config/supervisord/supervisord.conf index 17ea959..cf0229c 100644 --- a/.config/supervisord/supervisord.conf +++ b/.config/supervisord/supervisord.conf @@ -13,16 +13,27 @@ killasgroup=true stopasgroup=true autostart=true +[program:plugin-watcher] +user=root +# restart delve if the PID for gpx_factry changes +command=/bin/bash -c 'while true; do pid=$(pgrep gpx_factry); if [ "$pid" != "$last_pid" ]; then echo "PID changed, restarting delve..."; supervisorctl restart delve; last_pid=$pid; fi; sleep 1; done' +stdout_logfile=/dev/fd/1 +stdout_logfile_maxbytes=0 +redirect_stderr=true +killasgroup=true +stopasgroup=true +autostart=true + [program:delve] user=root -command=/bin/bash -c 'pid=""; while [ -z "$pid" ]; do pid=$(pgrep -f gpx_factry); done; /root/go/bin/dlv attach --api-version=2 --headless --continue --accept-multiclient --listen=:2345 $pid' +command=/bin/bash -c 'pid=""; while [ -z "$pid" ]; do pid=$(pgrep gpx_factry); done; /root/go/bin/dlv attach --api-version=2 --headless --continue --accept-multiclient --listen=:2345 $pid' stdout_logfile=/dev/fd/1 stdout_logfile_maxbytes=0 redirect_stderr=true killasgroup=false stopasgroup=false autostart=true -autosrestart=true +autorestart=true startretries=999 [program:build-watcher] diff --git a/go.mod b/go.mod index 14cc2c6..89283af 100644 --- a/go.mod +++ b/go.mod @@ -6,11 +6,11 @@ require ( github.com/go-playground/form v3.1.4+incompatible github.com/go-resty/resty/v2 v2.7.0 github.com/google/uuid v1.6.0 - github.com/grafana/grafana-plugin-sdk-go v0.256.0 + github.com/grafana/grafana-plugin-sdk-go v0.260.1 github.com/pkg/errors v0.9.1 github.com/spf13/cast v1.5.0 - golang.org/x/sync v0.8.0 - google.golang.org/protobuf v1.35.1 + golang.org/x/sync v0.10.0 + google.golang.org/protobuf v1.35.2 ) require ( @@ -20,9 +20,9 @@ require ( github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cheekybits/genny v1.0.0 // indirect - github.com/chromedp/cdproto v0.0.0-20241022234722-4d5d5faf59fb // indirect + github.com/chromedp/cdproto v0.0.0-20241208230723-d1c7de7e5dd2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect - github.com/elazarl/goproxy v0.0.0-20240909085733-6741dbfc16a1 // indirect + github.com/elazarl/goproxy v0.0.0-20241209145312-60626aee8fb5 // indirect github.com/fatih/color v1.15.0 // indirect github.com/getkin/kin-openapi v0.128.0 // indirect github.com/go-logr/logr v1.4.2 // indirect @@ -39,9 +39,9 @@ require ( github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect - github.com/hashicorp/go-plugin v1.6.1 // indirect + github.com/hashicorp/go-plugin v1.6.2 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/invopop/yaml v0.3.1 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -65,7 +65,7 @@ require ( github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.60.0 // indirect + github.com/prometheus/common v0.60.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8 // indirect @@ -73,26 +73,26 @@ require ( github.com/unknwon/log v0.0.0-20200308114134-929b1006e34a // indirect github.com/urfave/cli v1.22.16 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.53.0 // indirect - go.opentelemetry.io/contrib/propagators/jaeger v1.29.0 // indirect - go.opentelemetry.io/contrib/samplers/jaegerremote v0.25.0 // indirect - go.opentelemetry.io/otel v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 // indirect - go.opentelemetry.io/otel/metric v1.31.0 // indirect - go.opentelemetry.io/otel/sdk v1.31.0 // indirect - go.opentelemetry.io/otel/trace v1.31.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.57.0 // indirect + go.opentelemetry.io/contrib/propagators/jaeger v1.32.0 // indirect + go.opentelemetry.io/contrib/samplers/jaegerremote v0.26.0 // indirect + go.opentelemetry.io/otel v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 // indirect + go.opentelemetry.io/otel/metric v1.32.0 // indirect + go.opentelemetry.io/otel/sdk v1.32.0 // indirect + go.opentelemetry.io/otel/trace v1.32.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.30.0 // indirect - golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.19.0 // indirect + golang.org/x/net v0.32.0 // indirect + golang.org/x/sys v0.28.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 // indirect google.golang.org/grpc v1.67.1 // indirect gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect diff --git a/go.sum b/go.sum index da9e823..008fcb4 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,8 @@ github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitf github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/chromedp/cdproto v0.0.0-20241022234722-4d5d5faf59fb h1:noKVm2SsG4v0Yd0lHNtFYc9EUxIVvrr4kJ6hM8wvIYU= github.com/chromedp/cdproto v0.0.0-20241022234722-4d5d5faf59fb/go.mod h1:4XqMl3iIW08jtieURWL6Tt5924w21pxirC6th662XUM= +github.com/chromedp/cdproto v0.0.0-20241208230723-d1c7de7e5dd2 h1:fJob5N/Eprtd427U84kFpQhAHIEqJYuDzveaL6T4Xsk= +github.com/chromedp/cdproto v0.0.0-20241208230723-d1c7de7e5dd2/go.mod h1:4XqMl3iIW08jtieURWL6Tt5924w21pxirC6th662XUM= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -23,6 +25,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/elazarl/goproxy v0.0.0-20240909085733-6741dbfc16a1 h1:g7YUigN4dW2+zpdusdTTghZ+5Py3BaUMAStvL8Nk+FY= github.com/elazarl/goproxy v0.0.0-20240909085733-6741dbfc16a1/go.mod h1:thX175TtLTzLj3p7N/Q9IiKZ7NF+p72cvL91emV0hzo= +github.com/elazarl/goproxy v0.0.0-20241209145312-60626aee8fb5 h1:8uwZ3G6BWD7I0lMflO1m/fUztvFbPKAaY+xZlqQpfVU= +github.com/elazarl/goproxy v0.0.0-20241209145312-60626aee8fb5/go.mod h1:thX175TtLTzLj3p7N/Q9IiKZ7NF+p72cvL91emV0hzo= github.com/elazarl/goproxy/ext v0.0.0-20220115173737-adb46da277ac h1:9yrT5tmn9Zc0ytWPASlaPwQfQMQYnRf0RSDe1XvHw0Q= github.com/elazarl/goproxy/ext v0.0.0-20220115173737-adb46da277ac/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= @@ -71,6 +75,8 @@ github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/grafana/grafana-plugin-sdk-go v0.256.0 h1:Vh7A+QaaenNx2gwKQekwHuGEGz8XNvc6Q2ZU+H4/Y/A= github.com/grafana/grafana-plugin-sdk-go v0.256.0/go.mod h1:ACAKXTUgobDFdroItuDxXzdOxa2aCsG1GfZ5+j+/i8M= +github.com/grafana/grafana-plugin-sdk-go v0.260.1 h1:KzbooQP9mv/9CPsn+SoUwGuomA8oUxO0iuIq6Rg/ekE= +github.com/grafana/grafana-plugin-sdk-go v0.260.1/go.mod h1:JriieK5Oc5v120QKhMs/LO55N0P3YI2ttEiVT1wfYsw= github.com/grafana/otel-profiling-go v0.5.1 h1:stVPKAFZSa7eGiqbYuG25VcqYksR6iWvF3YH66t4qL8= github.com/grafana/otel-profiling-go v0.5.1/go.mod h1:ftN/t5A/4gQI19/8MoWurBEtC6gFw8Dns1sJZ9W4Tls= github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= @@ -81,10 +87,14 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwn github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-plugin v1.6.1 h1:P7MR2UP6gNKGPp+y7EZw2kOiq4IR9WiqLvp0XOsVdwI= github.com/hashicorp/go-plugin v1.6.1/go.mod h1:XPHFku2tFo3o3QKFgSYo+cghcUhw1NA1hZyMK0PWAw0= +github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog= +github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso= @@ -157,6 +167,8 @@ github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJNllA= github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= +github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc= +github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= @@ -182,6 +194,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/unknwon/bra v0.0.0-20200517080246-1e3013ecaff8 h1:aVGB3YnaS/JNfOW3tiHIlmNmTDg618va+eT0mVomgyI= @@ -202,30 +215,51 @@ github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 h1:yMkBS9yViCc7U7yeLzJPM2XizlfdVvBRSmsQDWu6qc0= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0/go.mod h1:n8MR6/liuGB5EmTETUBeU5ZgqMOlqKRxUaqPQBOANZ8= go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.53.0 h1:IVtyPth4Rs5P8wIf0mP2KVKFNTJ4paX9qQ4Hkh5gFdc= go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.53.0/go.mod h1:ImRBLMJv177/pwiLZ7tU7HDGNdBv7rS0HQ99eN/zBl8= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.57.0 h1:7F3XCD6WYzDkwbi8I8N+oYJWquPVScnRosKGgqjsR8c= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.57.0/go.mod h1:Dk3C0BfIlZDZ5c6eVS7TYiH2vssuyUU3vUsgbrR+5V4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 h1:DheMAlT6POBP+gh8RUH19EOTnQIor5QE0uSRPtzCpSw= go.opentelemetry.io/contrib/propagators/jaeger v1.29.0 h1:+YPiqF5rR6PqHBlmEFLPumbSP0gY0WmCGFayXRcCLvs= go.opentelemetry.io/contrib/propagators/jaeger v1.29.0/go.mod h1:6PD7q7qquWSp3Z4HeM3e/2ipRubaY1rXZO8NIHVDZjs= +go.opentelemetry.io/contrib/propagators/jaeger v1.32.0 h1:K/fOyTMD6GELKTIJBaJ9k3ppF2Njt8MeUGBOwfaWXXA= +go.opentelemetry.io/contrib/propagators/jaeger v1.32.0/go.mod h1:ISE6hda//MTWvtngG7p4et3OCngsrTVfl7c6DjN17f8= go.opentelemetry.io/contrib/samplers/jaegerremote v0.25.0 h1:nwxen/H3auImb5D4Neo8TDhDseskdRYmlHvi7j1sExc= go.opentelemetry.io/contrib/samplers/jaegerremote v0.25.0/go.mod h1:KjcLnhrgBMLiPPAqyoGhuNmF6jm38LCPV6hdbBeFOTU= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.26.0 h1:/SKXyZLAnuj981HVc8G5ZylYK3qD2W6AYR6cJx5kIHw= +go.opentelemetry.io/contrib/samplers/jaegerremote v0.26.0/go.mod h1:cOEzME0M2OKeHB45lJiOKfvUCdg/r75mf7YS5w0tbmE= go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY= go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE= +go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U= +go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0 h1:K0XaT3DwHAcV4nKLzcQvwAgSyisUghWoY20I7huthMk= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.31.0/go.mod h1:B5Ki776z/MBnVha1Nzwp5arlzBbE3+1jk+pGmaP5HME= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 h1:IJFEoHiytixx8cMiVAO+GmHR6Frwu+u5Ur8njpFO6Ac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0/go.mod h1:3rHrKNtLIoS0oZwkY2vxi+oJcwFRWdtUyRII+so45p8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0 h1:FFeLy03iVTXP6ffeN2iXrxfGsZGCjVx0/4KlizjyBwU= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.31.0/go.mod h1:TMu73/k1CP8nBUpDLc71Wj/Kf7ZS9FK5b53VapRsP9o= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0 h1:9kV11HXBHZAvuPUZxmMWrH8hZn/6UnHX4K0mu36vNsU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.32.0/go.mod h1:JyA0FHXe22E1NeNiHmVp7kFHglnexDQ7uRWDiiJ1hKQ= go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE= go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY= +go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M= +go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk= go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0= +go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys= go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A= +go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM= +go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -246,11 +280,15 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI= +golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191020152052-9984515f0562/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -268,12 +306,16 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -290,12 +332,18 @@ gonum.org/v1/gonum v0.12.0 h1:xKuo6hzt+gMav00meVPUlXwSdoEJP46BR+wdxQEFK2o= gonum.org/v1/gonum v0.12.0/go.mod h1:73TDxJfAAHeA8Mk9mf8NlIppyhQNo5GLTcYeqgo2lvY= google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg= google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9 h1:QCqS/PdaHTSWGvupk2F/ehwHtGc0/GYkT+3GAcR1CCc= google.golang.org/genproto/googleapis/rpc v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28 h1:XVhgTWWV3kGQlwJHR3upFWZeTsei6Oks1apkZSeonIE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/pkg/datasource/event_query_handler.go b/pkg/datasource/event_query_handler.go index 1e9e24d..5c8296d 100644 --- a/pkg/datasource/event_query_handler.go +++ b/pkg/datasource/event_query_handler.go @@ -122,7 +122,9 @@ func (ds *HistorianDataSource) handleEventQuery(ctx context.Context, eventQuery assetPropertyFieldTypes := getAssetPropertyFieldTypes(eventAssetPropertyFrames) return EventQueryResultToDataFrame(eventQuery.IncludeParentInfo, slices.Collect(maps.Values(assets)), events, allEventTypes, eventTypeProperties, selectedPropertiesSet, assetPropertyFieldTypes, eventAssetPropertyFrames) case string(schemas.EventTypePropertyTypePeriodic): - return EventQueryResultToTrendDataFrame(eventQuery.IncludeParentInfo, slices.Collect(maps.Values(assets)), events, util.ByUUID(allEventTypes), eventTypePropertiesByEventType, selectedPropertiesSet, eventAssetPropertyFrames) + return EventQueryResultToTrendDataFrame(eventQuery.IncludeParentInfo, slices.Collect(maps.Values(assets)), events, util.ByUUID(allEventTypes), eventTypePropertiesByEventType, selectedPropertiesSet, eventAssetPropertyFrames, false) + case string(schemas.EventTypePropertyTypePeriodicWithDimension): + return EventQueryResultToTrendDataFrame(eventQuery.IncludeParentInfo, slices.Collect(maps.Values(assets)), events, util.ByUUID(allEventTypes), eventTypePropertiesByEventType, selectedPropertiesSet, eventAssetPropertyFrames, true) default: return nil, fmt.Errorf("unsupported event query type %s", eventQuery.Type) } diff --git a/pkg/datasource/events.go b/pkg/datasource/events.go index 471662e..ff660c9 100644 --- a/pkg/datasource/events.go +++ b/pkg/datasource/events.go @@ -66,7 +66,7 @@ type eventFrameColumn struct { } // EventQueryResultToTrendDataFrame converts a event query result to data frames -func EventQueryResultToTrendDataFrame(includeParentInfo bool, assets []schemas.Asset, events []schemas.Event, eventTypes map[uuid.UUID]schemas.EventType, eventTypePropertiesForEventType map[uuid.UUID][]schemas.EventTypeProperty, selectedProperties map[string]struct{}, eventAssetPropertyFrames map[uuid.UUID]data.Frames) (data.Frames, error) { +func EventQueryResultToTrendDataFrame(includeParentInfo bool, assets []schemas.Asset, events []schemas.Event, eventTypes map[uuid.UUID]schemas.EventType, eventTypePropertiesForEventType map[uuid.UUID][]schemas.EventTypeProperty, selectedProperties map[string]struct{}, eventAssetPropertyFrames map[uuid.UUID]data.Frames, byDimension bool) (data.Frames, error) { uuidToAssetMap := make(map[uuid.UUID]schemas.Asset) for _, asset := range assets { uuidToAssetMap[asset.UUID] = asset @@ -78,26 +78,30 @@ func EventQueryResultToTrendDataFrame(includeParentInfo bool, assets []schemas.A for _, eventType := range eventTypes { eventTypeProperties := eventTypePropertiesForEventType[eventType.UUID] for _, eventTypeProperty := range eventTypeProperties { - if eventTypeProperty.Type == schemas.EventTypePropertyTypePeriodic { + if (!byDimension && eventTypeProperty.Type == schemas.EventTypePropertyTypePeriodic) || eventTypeProperty.Type == schemas.EventTypePropertyTypePeriodicWithDimension { if _, ok := selectedProperties[eventTypeProperty.Name]; len(selectedProperties) == 0 || ok { periodicEventTypeProperties = append(periodicEventTypeProperties, eventTypeProperty) } else if _, ok := selectedProperties[eventTypeProperty.UUID.String()]; len(selectedProperties) == 0 || ok { periodicEventTypeProperties = append(periodicEventTypeProperties, eventTypeProperty) } - } else { + } + if eventTypeProperty.Type == schemas.EventTypePropertyTypeSimple { simpleEventTypeProperties = append(simpleEventTypeProperties, eventTypeProperty) } } } periodicPropertyData := map[float64]map[eventFrameColumn]interface{}{} - columns := []eventFrameColumn{} for i := range events { eventLabels := data.Labels{} for j := range simpleEventTypeProperties { name := simpleEventTypeProperties[j].Name + if events[i].Properties == nil { + break + } + if value, ok := events[i].Properties.Properties[name]; ok { eventLabels[name] = fmt.Sprintf("%v", value) } @@ -122,6 +126,10 @@ func EventQueryResultToTrendDataFrame(includeParentInfo bool, assets []schemas.A labels := data.Labels{} maps.Copy(labels, eventLabels) periodicPropertyValues := util.PeriodicPropertyValues{} + if events[i].Properties == nil { + continue + } + if err := events[i].Properties.Properties.Get(periodicEventTypeProperties[j].Name, &periodicPropertyValues); err != nil { continue } @@ -188,13 +196,19 @@ func EventQueryResultToTrendDataFrame(includeParentInfo bool, assets []schemas.A setUOMFieldConfig(identifier.Field, periodicEventTypeProperties[j]) columns = append(columns, identifier) - for k := range periodicPropertyValues.Offsets { - offset := periodicPropertyValues.Offsets[k] + for offset, value := range periodicPropertyValues.ValuesByOffset { + if byDimension { + if dimensionValue, ok := periodicPropertyValues.DimensionValuesByOffset[offset].(float64); ok { + offset = dimensionValue + } + } + if _, ok := periodicPropertyData[offset]; !ok { periodicPropertyData[offset] = map[eventFrameColumn]interface{}{} } - periodicPropertyData[offset][identifier] = periodicPropertyValues.Values[k] + periodicPropertyData[offset][identifier] = value } + } assetPropertyFrames := eventAssetPropertyFrames[events[i].UUID] @@ -249,8 +263,10 @@ func EventQueryResultToTrendDataFrame(includeParentInfo bool, assets []schemas.A data.NewField("Offset", nil, []float64{}), } - fields[0].Config = &data.FieldConfig{ - Unit: "dtdhms", + if !byDimension { + fields[0].Config = &data.FieldConfig{ + Unit: "dtdhms", + } } offsets := slices.Sorted(maps.Keys(periodicPropertyData)) diff --git a/pkg/schemas/database.go b/pkg/schemas/database.go index 32e8a62..66029ca 100644 --- a/pkg/schemas/database.go +++ b/pkg/schemas/database.go @@ -86,8 +86,9 @@ const ( // The order determines how EventTypePropertyType gets sorted const ( - EventTypePropertyTypeSimple PropertyType = "simple" - EventTypePropertyTypePeriodic PropertyType = "periodic" + EventTypePropertyTypeSimple PropertyType = "simple" + EventTypePropertyTypePeriodic PropertyType = "periodic" + EventTypePropertyTypePeriodicWithDimension PropertyType = "periodic_with_dimension" ) // EventTypeProperty has the fields of an event type property that are used by the data source diff --git a/pkg/util/periodic_property_values.go b/pkg/util/periodic_property_values.go index d79ce62..118fa9c 100644 --- a/pkg/util/periodic_property_values.go +++ b/pkg/util/periodic_property_values.go @@ -1,66 +1,178 @@ package util -import "slices" +import ( + "encoding/json" + + "maps" + "slices" +) // PeriodicPropertyValues is a map of offsets and values type PeriodicPropertyValues struct { - // Offsets is a list of offsets - Offsets []float64 `json:"t"` - // Values is a list of values - Values []interface{} `json:"v"` + ValuesByOffset map[float64]interface{} `json:"-"` + DimensionValuesByOffset map[float64]interface{} `json:"-"` +} + +// NewPeriodicPropertyValues creates a new PeriodicPropertyValues +func NewPeriodicPropertyValues() *PeriodicPropertyValues { + return &PeriodicPropertyValues{ + ValuesByOffset: map[float64]interface{}{}, + } +} + +// NewPeriodicPropertyValuesWithDimension creates a new PeriodicPropertyValues with dimension values +func NewPeriodicPropertyValuesWithDimension() *PeriodicPropertyValues { + return &PeriodicPropertyValues{ + ValuesByOffset: map[float64]interface{}{}, + DimensionValuesByOffset: map[float64]interface{}{}, + } +} + +// HasDimensionValues returns true if the values have dimension values +func (p *PeriodicPropertyValues) HasDimensionValues() bool { + return p.DimensionValuesByOffset != nil } // GetValueAt returns the value at the given offset func (p *PeriodicPropertyValues) GetValueAt(offset float64) interface{} { - index := slices.Index(p.Offsets, offset) - if index == -1 { + return p.ValuesByOffset[offset] +} + +// GetDimensionValueAt returns the dimension value at the given offset +func (p *PeriodicPropertyValues) GetDimensionValueAt(offset float64) interface{} { + if p.DimensionValuesByOffset == nil { return nil } - return p.Values[index] + return p.DimensionValuesByOffset[offset] } // SetValueAt sets the value at the given offset func (p *PeriodicPropertyValues) SetValueAt(offset float64, value interface{}) { - index := slices.Index(p.Offsets, offset) - if index == -1 { - p.Offsets = append(p.Offsets, offset) - p.Values = append(p.Values, value) + p.ValuesByOffset[offset] = value + if p.DimensionValuesByOffset != nil { + p.DimensionValuesByOffset[offset] = nil + } +} + +// SetDimensionValueAt sets the dimension value at the given offset +func (p *PeriodicPropertyValues) SetDimensionValueAt(offset float64, values interface{}) { + if p.DimensionValuesByOffset == nil { return } - p.Values[index] = value + p.DimensionValuesByOffset[offset] = values + p.ValuesByOffset[offset] = nil } // AppendValue appends a value to the end of the values func (p *PeriodicPropertyValues) AppendValue(offset float64, value interface{}) { - p.Offsets = append(p.Offsets, offset) - p.Values = append(p.Values, value) + if p.DimensionValuesByOffset != nil { + p.DimensionValuesByOffset[offset] = nil + } + + p.ValuesByOffset[offset] = value } // RemoveValueAt removes a value at the given offset func (p *PeriodicPropertyValues) RemoveValueAt(offset float64) { - index := slices.Index(p.Offsets, offset) - if index == -1 { + delete(p.ValuesByOffset, offset) + if p.DimensionValuesByOffset != nil { + delete(p.DimensionValuesByOffset, offset) + } +} + +// SetValueAtWithDimension sets the value at the given offset with a unit value +func (p *PeriodicPropertyValues) SetValueAtWithDimension(offset float64, value interface{}, unitValue interface{}) { + if p.DimensionValuesByOffset == nil { return } - p.Offsets = append(p.Offsets[:index], p.Offsets[index+1:]...) - p.Values = append(p.Values[:index], p.Values[index+1:]...) + p.ValuesByOffset[offset] = value + p.DimensionValuesByOffset[offset] = unitValue +} + +// AppendValueWithDimension appends a value to the end of the values with a unit value +func (p *PeriodicPropertyValues) AppendValueWithDimension(offset float64, value interface{}, unitValue interface{}) { + p.SetValueAtWithDimension(offset, value, unitValue) +} + +type periodicPropertyValuesJSON struct { + Offsets []float64 `json:"t"` + Values []interface{} `json:"v"` + DimensionValues []interface{} `json:"d,omitempty"` } -// Sort sorts the values by offset -func (p *PeriodicPropertyValues) Sort() { - mapped := make(map[float64]interface{}) - for i, offset := range p.Offsets { - mapped[offset] = p.Values[i] +// MarshalJSON marshals the PeriodicPropertyValues to JSON +func (p *PeriodicPropertyValues) MarshalJSON() ([]byte, error) { + t := make([]float64, 0, len(p.ValuesByOffset)) + v := make([]interface{}, 0, len(p.ValuesByOffset)) + var d []interface{} + if p.DimensionValuesByOffset != nil { + d = make([]interface{}, 0, len(p.ValuesByOffset)) + } + + // Sort the offsets + offsets := slices.Sorted(maps.Keys(p.ValuesByOffset)) + + for _, offset := range offsets { + t = append(t, offset) + v = append(v, p.ValuesByOffset[offset]) + if p.DimensionValuesByOffset != nil { + d = append(d, p.DimensionValuesByOffset[offset]) + } + } + + result := periodicPropertyValuesJSON{ + Offsets: t, + Values: v, + } + + if p.DimensionValuesByOffset != nil { + result.DimensionValues = d + } + + return json.Marshal(result) +} + +// ParseValues parses the values in the PeriodicPropertyValues +func (p *PeriodicPropertyValues) ParseValues(parser func(interface{}) (interface{}, error)) error { + values := make(map[float64]interface{}) + + for offset, value := range p.ValuesByOffset { + parsedValue, err := parser(value) + if err != nil { + return err + } + + values[offset] = parsedValue + } + + p.ValuesByOffset = values + + return nil +} + +// UnmarshalJSON unmarshals the PeriodicPropertyValues from JSON +func (p *PeriodicPropertyValues) UnmarshalJSON(data []byte) error { + v := periodicPropertyValuesJSON{} + + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + p.ValuesByOffset = map[float64]interface{}{} + + if v.DimensionValues != nil { + p.DimensionValuesByOffset = map[float64]interface{}{} } - sortedValues := make([]interface{}, len(p.Offsets)) - slices.Sort(p.Offsets) - for i, offset := range p.Offsets { - sortedValues[i] = mapped[offset] + for i := range v.Offsets { + p.ValuesByOffset[v.Offsets[i]] = v.Values[i] + if len(v.DimensionValues) > i { + p.DimensionValuesByOffset[v.Offsets[i]] = v.DimensionValues[i] + } } - p.Values = sortedValues + return nil } diff --git a/pkg/util/semver.go b/pkg/util/semver.go index 4ffafa9..c0a7fe1 100644 --- a/pkg/util/semver.go +++ b/pkg/util/semver.go @@ -16,6 +16,19 @@ func min(a, b int) int { // SemverCompare compares two semver strings, returns true if a is less than b func SemverCompare(a string, b string) bool { + if a == b { + return false + } + + // debug is always more than any other version + if b == "debug" { + return true + } + + if a == "debug" { + return false + } + aParts := strings.Split(a, ".") bParts := strings.Split(b, ".") length := min(len(aParts), len(bParts)) diff --git a/src/CustomVariableEditor/EventTypePropertyFilter.tsx b/src/CustomVariableEditor/EventTypePropertyFilter.tsx index ad7e5f5..83bfa0a 100644 --- a/src/CustomVariableEditor/EventTypePropertyFilter.tsx +++ b/src/CustomVariableEditor/EventTypePropertyFilter.tsx @@ -1,15 +1,17 @@ import React, { useState } from 'react' import { SelectableValue } from '@grafana/data' -import { AsyncMultiSelect, InlineField, InlineFieldRow, Select } from '@grafana/ui' +import { AsyncMultiSelect, InlineField, InlineFieldRow, MultiSelect } from '@grafana/ui' import { DataSource } from 'datasource' -import { EventTypeFilter, EventTypePropertiesFilter, EventTypePropertyType, labelWidth } from 'types' +import { EventTypeFilter, EventTypePropertiesFilter, HistorianInfo, PropertyType, labelWidth } from 'types' +import { isSupportedPrototypeType } from 'QueryEditor/util' export function EventTypePropertyFilterRow(props: { datasource: DataSource onChange: (val: EventTypePropertiesFilter) => void initialValue?: EventTypePropertiesFilter templateVariables: SelectableValue + historianInfo?: HistorianInfo | undefined }) { const [selectedEventTypes, setEventTypes] = useState>>() @@ -40,10 +42,13 @@ export function EventTypePropertyFilterRow(props: { return selectableValues } - const onTypeChange = (value: SelectableValue | undefined) => { + const onTypeChange = (items: Array> | undefined) => { + const types = items?.map((e) => { + return e.value || '' + }) props.onChange({ ...props.initialValue, - Types: value?.value ? [value.value] : [], + Types: types, }) } @@ -63,19 +68,17 @@ export function EventTypePropertyFilterRow(props: { - isSupportedPrototypeType(value, props.historianInfo?.Version ?? '')) .filter(([_, value]) => !props.isAnnotationQuery || value === PropertyType.Simple) .map(([key, value]) => ({ label: key, value }))} value={props.query.Type} diff --git a/src/QueryEditor/util.ts b/src/QueryEditor/util.ts index aed333b..f3668e4 100644 --- a/src/QueryEditor/util.ts +++ b/src/QueryEditor/util.ts @@ -12,6 +12,7 @@ import { Measurement, MeasurementQuery, MeasurementQueryOptions, + PropertyType, ValueFilter, } from 'types' @@ -331,6 +332,18 @@ export function migrateMeasurementQuery(query: MeasurementQuery): MeasurementQue // semverCompare compares two semver strings and returns greater than 0 if a > b, 0 if a == b, and less than 0 if a < b export function semverCompare(a: string, b: string): number { + if (a === b) { + return 0 + } + + if (a === 'debug') { + return 1 + } + + if (b === 'debug') { + return -1 + } + // remove leading v if (a.startsWith('v')) { a = a.substring(1) @@ -366,3 +379,10 @@ export function semverCompare(a: string, b: string): number { return 0 } + +export function isSupportedPrototypeType(type: PropertyType, version: string): boolean { + if (type === PropertyType.PeriodicWithDimension && semverCompare(version, 'v7.2.0') < 0) { + return false + } + return true +} diff --git a/src/types.ts b/src/types.ts index 062d2a0..fdb3621 100644 --- a/src/types.ts +++ b/src/types.ts @@ -131,11 +131,6 @@ export interface EventQuery { IncludeParentInfo?: boolean } -export enum EventTypePropertyType { - Simple = 'simple', - Periodic = 'periodic', -} - export interface ResourceFilter { ScopedVars?: ScopedVars } @@ -262,6 +257,7 @@ export enum PropertyDatatype { export enum PropertyType { Simple = 'simple', Periodic = 'periodic', + PeriodicWithDimension = 'periodic_with_dimension', } export interface EventTypeProperty {