From d17525f79ef2d9d644c67aa061475c880c3a2991 Mon Sep 17 00:00:00 2001 From: Vlad Vitan <23100181+vlasebian@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:19:48 +0100 Subject: [PATCH 1/2] gs: Clone event data before registering evtGatewayConnectionStats --- pkg/gatewayserver/gatewayserver.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/gatewayserver/gatewayserver.go b/pkg/gatewayserver/gatewayserver.go index ccba5b181a..93fba9912a 100644 --- a/pkg/gatewayserver/gatewayserver.go +++ b/pkg/gatewayserver/gatewayserver.go @@ -1101,7 +1101,7 @@ func (gs *GatewayServer) updateConnStats(ctx context.Context, conn connectionEnt Protocol: conn.Connection.Frontend().Protocol(), GatewayRemoteAddress: conn.Connection.GatewayRemoteAddress(), } - registerGatewayConnectionStats(ctx, ids, stats) + registerGatewayConnectionStats(ctx, ids, ttnpb.Clone(stats)) if gs.statsRegistry != nil { if err := gs.statsRegistry.Set( decoupledCtx, @@ -1121,7 +1121,7 @@ func (gs *GatewayServer) updateConnStats(ctx context.Context, conn connectionEnt ConnectedAt: nil, DisconnectedAt: timestamppb.Now(), } - registerGatewayConnectionStats(decoupledCtx, ids, stats) + registerGatewayConnectionStats(decoupledCtx, ids, ttnpb.Clone(stats)) if gs.statsRegistry == nil { return } From 44dc81532343a93bc1ea0d89bafb4e3eba8ceba0 Mon Sep 17 00:00:00 2001 From: Vlad Vitan <23100181+vlasebian@users.noreply.github.com> Date: Thu, 5 Dec 2024 14:26:06 +0100 Subject: [PATCH 2/2] all: Recover from marshalling event data panic --- config/messages.json | 9 +++++++++ pkg/events/events.go | 22 ++++++++++++++++++++++ pkg/webui/locales/ja.json | 1 + 3 files changed, 32 insertions(+) diff --git a/config/messages.json b/config/messages.json index 5a0494a916..a474d02dbf 100644 --- a/config/messages.json +++ b/config/messages.json @@ -4832,6 +4832,15 @@ "file": "pattern.go" } }, + "error:pkg/events:marshal_data": { + "translations": { + "en": "marshal data" + }, + "description": { + "package": "pkg/events", + "file": "events.go" + } + }, "error:pkg/events:no_matching_events": { "translations": { "en": "no matching events for regexp `{regexp}`" diff --git a/pkg/events/events.go b/pkg/events/events.go index 45cc8be130..b1799bddaf 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -25,7 +25,9 @@ import ( "strings" "time" + "github.com/getsentry/sentry-go" "go.thethings.network/lorawan-stack/v3/pkg/errors" + sentryerrors "go.thethings.network/lorawan-stack/v3/pkg/errors/sentry" "go.thethings.network/lorawan-stack/v3/pkg/goproto" "go.thethings.network/lorawan-stack/v3/pkg/jsonpb" "go.thethings.network/lorawan-stack/v3/pkg/ttnpb" @@ -176,7 +178,27 @@ func New(ctx context.Context, name, description string, opts ...Option) Event { return (&definition{name: name, description: description}).New(ctx, opts...) } +var errMarshalData = errors.Define("marshal_data", "marshal data") + func marshalData(data any) (anyPB *anypb.Any, err error) { + // TODO: https://github.com/TheThingsIndustries/lorawan-stack-support/issues/1163. + // Remove this after the issue is fixed. + defer func() { + if p := recover(); p != nil { + if pErr, ok := p.(error); ok { + err = errMarshalData.WithCause(pErr) + } else { + err = errMarshalData.WithAttributes("panic", p) + } + event := sentryerrors.NewEvent(err) + sentry.CaptureEvent(event) + } + }() + + return mustMarshalData(data) +} + +func mustMarshalData(data any) (anyPB *anypb.Any, err error) { if protoMessage, ok := data.(proto.Message); ok { anyPB, err = anypb.New(protoMessage) if err != nil { diff --git a/pkg/webui/locales/ja.json b/pkg/webui/locales/ja.json index acae28092e..bd5b27812d 100644 --- a/pkg/webui/locales/ja.json +++ b/pkg/webui/locales/ja.json @@ -2362,6 +2362,7 @@ "error:pkg/events/redis:channel_closed": "チャネルが閉じています", "error:pkg/events/redis:unknown_encoding": "不明なエンコーディング", "error:pkg/events:invalid_regexp": "無効な正規表現", + "error:pkg/events:marshal_data": "", "error:pkg/events:no_matching_events": "正規表現`{regexp}`に一致するイベントがありません", "error:pkg/events:unknown_event_name": "不明なイベント`{name}`", "error:pkg/fetch:fetch_file": "ファイル `{filename}` を取得できません",