some refinement
Build and Publish / Metadata (push) Has been cancelled
Build and Publish / BuildAndDeployAmd64 (push) Has been cancelled

This commit is contained in:
2026-04-07 12:44:55 +02:00
parent 89e1db8edf
commit 0ed1cb4355
14 changed files with 390 additions and 104 deletions
+2
View File
@@ -1,2 +1,4 @@
./server ./server
.DS_Store .DS_Store
otel-agent.log
./semgrep-results.json
+5
View File
@@ -0,0 +1,5 @@
otel-ui/node_modules/
otel-ui/dist/
vendor/
.gemini/
./server
+9 -1
View File
@@ -30,11 +30,19 @@ FROM alpine:latest
RUN apk --no-cache add ca-certificates RUN apk --no-cache add ca-certificates
WORKDIR /root/ # Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /home/appuser/
COPY --from=go-builder /go-otel . COPY --from=go-builder /go-otel .
COPY --from=go-builder /app/otel-ui/dist ./dist COPY --from=go-builder /app/otel-ui/dist ./dist
# Ensure the appuser owns the files
RUN chown -R appuser:appgroup /home/appuser/
USER appuser
EXPOSE 8080 EXPOSE 8080
CMD ["./go-otel"] CMD ["./go-otel"]
+10
View File
@@ -6,3 +6,13 @@ lint:
install-lint: install-lint:
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
fix:
golangci-lint run --fix ./...
semgrep:
@which semgrep > /dev/null || (echo "semgrep not found, please install it: brew install semgrep")
semgrep scan --config auto --config semgrep-rules.yml
semgrep-ci:
semgrep scan --config auto --config semgrep-rules.yml --error
+6 -1
View File
@@ -6,6 +6,7 @@ import (
"log" "log"
"net" "net"
"net/http" "net/http"
"os"
"strings" "strings"
"git.tornberg.me/go-otel/internal/collector" "git.tornberg.me/go-otel/internal/collector"
@@ -152,7 +153,11 @@ func main() {
// Configure history size (default 100, can be made configurable) // Configure history size (default 100, can be made configurable)
historySize := 100 historySize := 100
store := storage.NewFileStore("otel-agent.log") logPath := os.Getenv("OTELLOG_PATH")
if logPath == "" {
logPath = "otel-agent.log"
}
store := storage.NewFileStore(logPath)
coll := collector.New(nil, historySize, store) // Temporary nil for wsServer coll := collector.New(nil, historySize, store) // Temporary nil for wsServer
wsServer := websocket.New(coll) wsServer := websocket.New(coll)
// Update collector with wsServer // Update collector with wsServer
+20 -17
View File
@@ -1,30 +1,33 @@
module git.tornberg.me/go-otel module git.tornberg.me/go-otel
go 1.25.1 go 1.26
require ( require (
github.com/gorilla/websocket v1.5.3 github.com/gorilla/websocket v1.5.3
go.opentelemetry.io/collector/consumer v1.45.0 github.com/natefinch/lumberjack v2.0.0+incompatible
go.opentelemetry.io/collector/pdata v1.45.0 go.opentelemetry.io/collector/consumer v1.55.0
go.opentelemetry.io/proto/otlp v1.9.0 go.opentelemetry.io/collector/pdata v1.55.0
google.golang.org/grpc v1.76.0 go.opentelemetry.io/proto/otlp v1.10.0
google.golang.org/protobuf v1.36.10 google.golang.org/grpc v1.80.0
google.golang.org/protobuf v1.36.11
) )
require ( require (
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect github.com/BurntSushi/toml v1.6.0 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
github.com/hashicorp/go-version v1.9.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect go.opentelemetry.io/collector/featuregate v1.55.0 // indirect
go.opentelemetry.io/collector/featuregate v1.45.0 // indirect go.opentelemetry.io/otel v1.43.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/net v0.46.0 // indirect golang.org/x/net v0.52.0 // indirect
golang.org/x/sys v0.37.0 // indirect golang.org/x/sys v0.42.0 // indirect
golang.org/x/text v0.30.0 // indirect golang.org/x/text v0.35.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251103181224-f26f9409b101 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
) )
+57 -46
View File
@@ -1,3 +1,7 @@
github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk=
github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -14,10 +18,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA=
github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -34,51 +38,58 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/collector/consumer v1.45.0 h1:TtqXxgW+1GSCwdoohq0fzqnfqrZBKbfo++1XRj8mrEA= go.opentelemetry.io/collector/consumer v1.55.0 h1:7Per8P4J0nlBrFVSXb+nwZ+egiel1BRtggZngyykGsM=
go.opentelemetry.io/collector/consumer v1.45.0/go.mod h1:pJzqTWBubwLt8mVou+G4/Hs23b3m425rVmld3LqOYpY= go.opentelemetry.io/collector/consumer v1.55.0/go.mod h1:Qrn5fDp/HpDmUp+l2RGKsdKyOPlgGlaZPKvw/z9FfEc=
go.opentelemetry.io/collector/featuregate v1.45.0 h1:D06hpf1F2KzKC+qXLmVv5e8IZpgCyZVeVVC8iOQxVmw= go.opentelemetry.io/collector/featuregate v1.55.0 h1:s/bE8135+8GZpVlQ9qLXQjvprE9KNOGsLhNkqm+EDEU=
go.opentelemetry.io/collector/featuregate v1.45.0/go.mod h1:d0tiRzVYrytB6LkcYgz2ESFTv7OktRPQe0QEQcPt1L4= go.opentelemetry.io/collector/featuregate v1.55.0/go.mod h1:PS7zY/zaCb28EqciePVwRHVhc3oKortTFXsi3I6ee4g=
go.opentelemetry.io/collector/pdata v1.45.0 h1:q4XaISpeX640BcwXwb2mKOVw/gb67r22HjGWl8sbWsk= go.opentelemetry.io/collector/internal/testutil v0.149.0 h1:OWfUPO3NFKSaJtz/SBZph/2ENHbr/VbzzlBadKUhm8o=
go.opentelemetry.io/collector/pdata v1.45.0/go.mod h1:5q2f001YhwMQO8QvpFhCOa4Cq/vtwX9W4HRMsXkU/nE= go.opentelemetry.io/collector/internal/testutil v0.149.0/go.mod h1:Jkjs6rkqs973LqgZ0Fe3zrokQRKULYXPIf4HuqStiEE=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= go.opentelemetry.io/collector/pdata v1.55.0 h1:WBgye8bo8koUyV9Vmp/r2Q3lgDezdsgfKDQAaM1oT2I=
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= go.opentelemetry.io/collector/pdata v1.55.0/go.mod h1:6jPrbM4tuliCPACDznjFtxnnHisfKfzwrBVoeuESYuk=
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4= go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
go.opentelemetry.io/proto/slim/otlp v1.8.0 h1:afcLwp2XOeCbGrjufT1qWyruFt+6C9g5SOuymrSPUXQ= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
go.opentelemetry.io/proto/slim/otlp v1.8.0/go.mod h1:Yaa5fjYm1SMCq0hG0x/87wV1MP9H5xDuG/1+AhvBcsI= go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.1.0 h1:Uc+elixz922LHx5colXGi1ORbsW8DTIGM+gg+D9V7HE= go.opentelemetry.io/proto/slim/otlp v1.10.0 h1:iR97Vs/ZDR+y9TfuP9b1XBtdPWeC+OMslIBmhcLU7jM=
go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.1.0/go.mod h1:VyU6dTWBWv6h9w/+DYgSZAPMabWbPTFTuxp25sM8+s0= go.opentelemetry.io/proto/slim/otlp v1.10.0/go.mod h1:lV9250stpjYLPNA5viFabIgP2QlUGRT1GdTgAf8SIUk=
go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.1.0 h1:i8YpvWGm/Uq1koL//bnbJ/26eV3OrKWm09+rDYo7keU= go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.3.0 h1:RUF5rO0hAlgiJt1fzQVzcVs3vZVNHIcMLgOgG4rWNcQ=
go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.1.0/go.mod h1:pQ70xHY/ZVxNUBPn+qUWPl8nwai87eWdqL3M37lNi9A= go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.3.0/go.mod h1:I89cynRj8y+383o7tEQVg2SVA6SRgDVIouWPUVXjx0U=
go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.3.0 h1:CQvJSldHRUN6Z8jsUeYv8J0lXRvygALXIzsmAeCcZE0=
go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.3.0/go.mod h1:xSQ+mEfJe/GjK1LXEyVOoSI1N9JV9ZI923X5kup43W4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
google.golang.org/genproto/googleapis/api v0.0.0-20251103181224-f26f9409b101 h1:vk5TfqZHNn0obhPIYeS+cxIFKFQgser/M2jnI+9c6MM= google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
google.golang.org/genproto/googleapis/api v0.0.0-20251103181224-f26f9409b101/go.mod h1:E17fc4PDhkr22dE3RgnH2hEubUaky6ZwW4VhANxyspg= google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101 h1:tRPGkdGHuewF4UisLzzHHr1spKw92qLM98nIzxbC0wY= google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251103181224-f26f9409b101/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+12 -28
View File
@@ -47,7 +47,7 @@ func (c *Collector) SetBroadcaster(broadcaster websocket.Broadcaster) {
c.broadcaster = broadcaster c.broadcaster = broadcaster
} }
func (c *Collector) addToHistory(dataType websocket.DataType, data interface{}) { func (c *Collector) addToHistory(dataType websocket.DataType, data json.RawMessage) {
entry := websocket.HistoryEntry{ entry := websocket.HistoryEntry{
Type: string(dataType), Type: string(dataType),
Timestamp: time.Now().UnixNano(), Timestamp: time.Now().UnixNano(),
@@ -149,9 +149,8 @@ func (c *Collector) SearchHistory(ctx context.Context, query string, limit int)
if query == "" { if query == "" {
filtered = append(filtered, entry) filtered = append(filtered, entry)
} else { } else {
// Basic string filter for in-memory // Basic string filter for in-memory, no need to re-marshal RawMessage
data, _ := json.Marshal(entry.Data) if strings.Contains(strings.ToLower(string(entry.Data)), lowerQuery) {
if strings.Contains(strings.ToLower(string(data)), lowerQuery) {
filtered = append(filtered, entry) filtered = append(filtered, entry)
} }
} }
@@ -180,17 +179,12 @@ func (c *Collector) ConsumeTraces(ctx context.Context, td ptrace.Traces) error {
return err return err
} }
// Parse to interface{} for history storage // Store and broadcast raw bytes as json.RawMessage to avoid unsafe interface{} usage
var data interface{} c.addToHistory(websocket.DataTypeTraces, buf)
if err := json.Unmarshal(buf, &data); err != nil {
log.Printf("failed to unmarshal traces for history: %v", err)
} else {
c.addToHistory(websocket.DataTypeTraces, data)
}
entry := websocket.Entry{ entry := websocket.Entry{
Type: string(websocket.DataTypeTraces), Type: string(websocket.DataTypeTraces),
Data: data, Data: buf,
} }
c.broadcaster.Broadcast(&entry) c.broadcaster.Broadcast(&entry)
@@ -206,17 +200,12 @@ func (c *Collector) ConsumeMetrics(ctx context.Context, md pmetric.Metrics) erro
return err return err
} }
// Parse to interface{} for history storage // Store and broadcast raw bytes as json.RawMessage to avoid unsafe interface{} usage
var data interface{} c.addToHistory(websocket.DataTypeMetrics, buf)
if err := json.Unmarshal(buf, &data); err != nil {
log.Printf("failed to unmarshal metrics for history: %v", err)
} else {
c.addToHistory(websocket.DataTypeMetrics, data)
}
entry := websocket.Entry{ entry := websocket.Entry{
Type: string(websocket.DataTypeMetrics), Type: string(websocket.DataTypeMetrics),
Data: data, Data: buf,
} }
c.broadcaster.Broadcast(&entry) c.broadcaster.Broadcast(&entry)
@@ -232,17 +221,12 @@ func (c *Collector) ConsumeLogs(ctx context.Context, ld plog.Logs) error {
return err return err
} }
// Parse to interface{} for history storage // Store and broadcast raw bytes as json.RawMessage to avoid unsafe interface{} usage
var data interface{} c.addToHistory(websocket.DataTypeLogs, buf)
if err := json.Unmarshal(buf, &data); err != nil {
log.Printf("failed to unmarshal logs for history: %v", err)
} else {
c.addToHistory(websocket.DataTypeLogs, data)
}
entry := websocket.Entry{ entry := websocket.Entry{
Type: string(websocket.DataTypeLogs), Type: string(websocket.DataTypeLogs),
Data: data, Data: buf,
} }
c.broadcaster.Broadcast(&entry) c.broadcaster.Broadcast(&entry)
+3 -2
View File
@@ -2,6 +2,7 @@ package collector
import ( import (
"context" "context"
"encoding/json"
"testing" "testing"
"time" "time"
@@ -29,7 +30,7 @@ func TestCollectorWithStore(t *testing.T) {
store := &mockStore{} store := &mockStore{}
coll := New(nil, 10, store) coll := New(nil, 10, store)
coll.addToHistory(websocket.DataTypeLogs, map[string]interface{}{"msg": "test"}) coll.addToHistory(websocket.DataTypeLogs, json.RawMessage(`{"msg": "test"}`))
// Give it a moment since it's asynchronous // Give it a moment since it's asynchronous
timeout := time.After(100 * time.Millisecond) timeout := time.After(100 * time.Millisecond)
@@ -55,7 +56,7 @@ func TestCollectorHistoryLimit(t *testing.T) {
coll := New(nil, 10, nil) coll := New(nil, 10, nil)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
coll.addToHistory(websocket.DataTypeLogs, map[string]interface{}{"msg": i}) coll.addToHistory(websocket.DataTypeLogs, json.RawMessage(`{"msg": "test"}`))
} }
history := coll.GetHistory(10) history := coll.GetHistory(10)
+2 -2
View File
@@ -21,12 +21,12 @@ func TestFileStore(t *testing.T) {
entry1 := websocket.HistoryEntry{ entry1 := websocket.HistoryEntry{
Type: "logs", Type: "logs",
Timestamp: 100, Timestamp: 100,
Data: map[string]interface{}{"msg": "hello world"}, Data: json.RawMessage(`{"msg":"hello world"}`),
} }
entry2 := websocket.HistoryEntry{ entry2 := websocket.HistoryEntry{
Type: "traces", Type: "traces",
Timestamp: 200, Timestamp: 200,
Data: map[string]interface{}{"msg": "trace event"}, Data: json.RawMessage(`{"msg":"trace event"}`),
} }
if err := fs.Append(ctx, entry1); err != nil { if err := fs.Append(ctx, entry1); err != nil {
+2 -2
View File
@@ -29,13 +29,13 @@ type HistoryProvider interface {
type HistoryEntry struct { type HistoryEntry struct {
Type string `json:"type"` Type string `json:"type"`
Timestamp int64 `json:"timestamp"` Timestamp int64 `json:"timestamp"`
Data interface{} `json:"data"` Data json.RawMessage `json:"data"`
} }
// Entry represents a telemetry update sent to clients. // Entry represents a telemetry update sent to clients.
type Entry struct { type Entry struct {
Type string `json:"type"` Type string `json:"type"`
Data interface{} `json:"data"` Data json.RawMessage `json:"data"`
} }
// Broadcaster interface for sending telemetry updates to all connected clients. // Broadcaster interface for sending telemetry updates to all connected clients.
+21
View File
@@ -12,9 +12,22 @@ spec:
labels: labels:
app: otel-debug-receiver app: otel-debug-receiver
spec: spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers: containers:
- name: otel-debug - name: otel-debug
image: matst80/otel-debug:latest image: matst80/otel-debug:latest
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
ports: ports:
- containerPort: 8080 - containerPort: 8080
name: http name: http
@@ -25,6 +38,11 @@ spec:
env: env:
- name: GRPC_GO_LOG_SEVERITY_LEVEL - name: GRPC_GO_LOG_SEVERITY_LEVEL
value: "info" value: "info"
- name: OTELLOG_PATH
value: "/logs/otel-agent.log"
volumeMounts:
- name: log-dir
mountPath: /logs
livenessProbe: livenessProbe:
httpGet: httpGet:
path: /health path: /health
@@ -44,3 +62,6 @@ spec:
limits: limits:
memory: "256Mi" memory: "256Mi"
cpu: "500m" cpu: "500m"
volumes:
- name: log-dir
emptyDir: {}
+209
View File
@@ -0,0 +1,209 @@
{
"version": "1.157.0",
"results": [],
"errors": [
{
"code": 3,
"level": "warn",
"type": "Syntax error",
"message": "Syntax error at line semgrep-results.json:1:\n missing element",
"path": "semgrep-results.json"
},
{
"code": 3,
"level": "warn",
"type": [
"PartialParsing",
[
{
"path": ".gitea/workflows/build.yaml",
"start": {
"line": 36,
"col": 23,
"offset": 1047
},
"end": {
"line": 36,
"col": 26,
"offset": 1050
}
},
{
"path": ".gitea/workflows/build.yaml",
"start": {
"line": 37,
"col": 26,
"offset": 1047
},
"end": {
"line": 37,
"col": 29,
"offset": 1050
}
},
{
"path": ".gitea/workflows/build.yaml",
"start": {
"line": 38,
"col": 26,
"offset": 1047
},
"end": {
"line": 38,
"col": 29,
"offset": 1050
}
}
]
],
"message": "Syntax error at line .gitea/workflows/build.yaml:36:\n When parsing a snippet as Bash for metavariable-pattern in rule 'yaml.github-actions.security.curl-eval.curl-eval', `${{` was unexpected",
"path": ".gitea/workflows/build.yaml",
"spans": [
{
"file": ".gitea/workflows/build.yaml",
"start": {
"line": 36,
"col": 23,
"offset": 1047
},
"end": {
"line": 36,
"col": 26,
"offset": 1050
}
},
{
"file": ".gitea/workflows/build.yaml",
"start": {
"line": 37,
"col": 26,
"offset": 1047
},
"end": {
"line": 37,
"col": 29,
"offset": 1050
}
},
{
"file": ".gitea/workflows/build.yaml",
"start": {
"line": 38,
"col": 26,
"offset": 1047
},
"end": {
"line": 38,
"col": 29,
"offset": 1050
}
}
]
}
],
"paths": {
"scanned": [
".DS_Store",
".dockerignore",
".gitea/workflows/build.yaml",
".gitignore",
".golangci.yml",
".semgrepignore",
"Dockerfile",
"Makefile",
"README.md",
"agents_example.md",
"build.sh",
"go.mod",
"go.sum",
"index.html",
"internal/collector/collector.go",
"internal/collector/collector_test.go",
"internal/collector/handlers.go",
"internal/storage/file_store.go",
"internal/storage/file_store_test.go",
"internal/storage/store.go",
"internal/websocket/server.go",
"k8s/deployment.yaml",
"k8s/ingress.yaml",
"k8s/service.yaml",
"semgrep-results.json",
"semgrep-rules.yml",
"test.sh"
]
},
"time": {
"rules": [],
"rules_parse_time": 6.65862512588501,
"profiling_times": {
"config_time": 7.022655010223389,
"core_time": 7.331943988800049,
"ignores_time": 0.0019888877868652344,
"total_time": 14.365644931793213
},
"parsing_time": {
"total_time": 0.0,
"per_file_time": {
"mean": 0.0,
"std_dev": 0.0
},
"very_slow_stats": {
"time_ratio": 0.0,
"count_ratio": 0.0
},
"very_slow_files": []
},
"scanning_time": {
"total_time": 0.3914341926574707,
"per_file_time": {
"mean": 0.005436586009131538,
"std_dev": 0.0003555799509652799
},
"very_slow_stats": {
"time_ratio": 0.0,
"count_ratio": 0.0
},
"very_slow_files": []
},
"matching_time": {
"total_time": 0.0,
"per_file_and_rule_time": {
"mean": 0.0,
"std_dev": 0.0
},
"very_slow_stats": {
"time_ratio": 0.0,
"count_ratio": 0.0
},
"very_slow_rules_on_files": []
},
"tainting_time": {
"total_time": 0.0,
"per_def_and_rule_time": {
"mean": 0.0,
"std_dev": 0.0
},
"very_slow_stats": {
"time_ratio": 0.0,
"count_ratio": 0.0
},
"very_slow_rules_on_defs": []
},
"fixpoint_timeouts": [],
"prefiltering": {
"project_level_time": 0.0,
"file_level_time": 0.0,
"rules_with_project_prefilters_ratio": 0.0,
"rules_with_file_prefilters_ratio": 0.9292490118577075,
"rules_selected_ratio": 0.1324110671936759,
"rules_matched_ratio": 0.1324110671936759
},
"targets": [],
"total_bytes": 0,
"max_memory_bytes": 11722574784
},
"engine_requested": "OSS",
"interfile_languages_used": [],
"skipped_rules": [],
"profiling_results": []
}
+27
View File
@@ -0,0 +1,27 @@
rules:
- id: go-otel-span-end-defer
message: "Potential missing `defer span.End()`. Spans should be closed to avoid memory leaks."
languages: [go]
severity: WARNING
patterns:
- pattern: |
$SPAN, $ERR := $TRACER.Start(...)
...
- pattern-not: |
$SPAN, $ERR := $TRACER.Start(...)
defer $SPAN.End()
...
- pattern-not: |
$SPAN, $ERR := $TRACER.Start(...)
...
$SPAN.End()
- id: no-direct-log-fatal
message: "Avoid using `log.Fatal` in internal packages. Use errors to propagate up to main."
languages: [go]
severity: ERROR
pattern: log.Fatal(...)
paths:
exclude:
- "main.go"
- "cmd/**"