mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-22 02:06:39 +00:00
Compare commits
5 Commits
sync-clien
...
refactor/g
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06da6dce38 | ||
|
|
7484c777e9 | ||
|
|
537151e0f3 | ||
|
|
a9c28ef723 | ||
|
|
c29bb1a289 |
@@ -56,6 +56,7 @@ block.prof: Block profiling information.
|
|||||||
heap.prof: Heap profiling information (snapshot of memory allocations).
|
heap.prof: Heap profiling information (snapshot of memory allocations).
|
||||||
allocs.prof: Allocations profiling information.
|
allocs.prof: Allocations profiling information.
|
||||||
threadcreate.prof: Thread creation profiling information.
|
threadcreate.prof: Thread creation profiling information.
|
||||||
|
stack_trace.txt: Complete stack traces of all goroutines at the time of bundle creation.
|
||||||
|
|
||||||
|
|
||||||
Anonymization Process
|
Anonymization Process
|
||||||
@@ -109,6 +110,9 @@ go tool pprof -http=:8088 heap.prof
|
|||||||
|
|
||||||
This will open a web browser tab with the profiling information.
|
This will open a web browser tab with the profiling information.
|
||||||
|
|
||||||
|
Stack Trace
|
||||||
|
The stack_trace.txt file contains a complete snapshot of all goroutine stack traces at the time the debug bundle was created.
|
||||||
|
|
||||||
Routes
|
Routes
|
||||||
The routes.txt file contains detailed routing table information in a tabular format:
|
The routes.txt file contains detailed routing table information in a tabular format:
|
||||||
|
|
||||||
@@ -327,6 +331,10 @@ func (g *BundleGenerator) createArchive() error {
|
|||||||
log.Errorf("failed to add profiles to debug bundle: %v", err)
|
log.Errorf("failed to add profiles to debug bundle: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := g.addStackTrace(); err != nil {
|
||||||
|
log.Errorf("failed to add stack trace to debug bundle: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := g.addSyncResponse(); err != nil {
|
if err := g.addSyncResponse(); err != nil {
|
||||||
return fmt.Errorf("add sync response: %w", err)
|
return fmt.Errorf("add sync response: %w", err)
|
||||||
}
|
}
|
||||||
@@ -522,6 +530,18 @@ func (g *BundleGenerator) addProf() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g *BundleGenerator) addStackTrace() error {
|
||||||
|
buf := make([]byte, 5242880) // 5 MB buffer
|
||||||
|
n := runtime.Stack(buf, true)
|
||||||
|
|
||||||
|
stackTrace := bytes.NewReader(buf[:n])
|
||||||
|
if err := g.addFileToZip(stackTrace, "stack_trace.txt"); err != nil {
|
||||||
|
return fmt.Errorf("add stack trace file to zip: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (g *BundleGenerator) addInterfaces() error {
|
func (g *BundleGenerator) addInterfaces() error {
|
||||||
interfaces, err := net.Interfaces()
|
interfaces, err := net.Interfaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ type EndpointUpdater struct {
|
|||||||
wgConfig WgConfig
|
wgConfig WgConfig
|
||||||
initiator bool
|
initiator bool
|
||||||
|
|
||||||
// mu protects updateWireGuardPeer and cancelFunc
|
// mu protects cancelFunc
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
cancelFunc func()
|
cancelFunc func()
|
||||||
updateWg sync.WaitGroup
|
updateWg sync.WaitGroup
|
||||||
@@ -86,11 +86,9 @@ func (e *EndpointUpdater) scheduleDelayedUpdate(ctx context.Context, addr *net.U
|
|||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
case <-t.C:
|
case <-t.C:
|
||||||
e.mu.Lock()
|
|
||||||
if err := e.updateWireGuardPeer(addr, presharedKey); err != nil {
|
if err := e.updateWireGuardPeer(addr, presharedKey); err != nil {
|
||||||
e.log.Errorf("failed to update WireGuard peer, address: %s, error: %v", addr, err)
|
e.log.Errorf("failed to update WireGuard peer, address: %s, error: %v", addr, err)
|
||||||
}
|
}
|
||||||
e.mu.Unlock()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,14 +60,7 @@ func (hook ContextHook) Fire(entry *logrus.Entry) error {
|
|||||||
|
|
||||||
entry.Data["context"] = source
|
entry.Data["context"] = source
|
||||||
|
|
||||||
switch source {
|
addFields(entry)
|
||||||
case HTTPSource:
|
|
||||||
addHTTPFields(entry)
|
|
||||||
case GRPCSource:
|
|
||||||
addGRPCFields(entry)
|
|
||||||
case SystemSource:
|
|
||||||
addSystemFields(entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -99,7 +92,7 @@ func (hook ContextHook) parseSrc(filePath string) string {
|
|||||||
return fmt.Sprintf("%s/%s", pkg, file)
|
return fmt.Sprintf("%s/%s", pkg, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addHTTPFields(entry *logrus.Entry) {
|
func addFields(entry *logrus.Entry) {
|
||||||
if ctxReqID, ok := entry.Context.Value(context.RequestIDKey).(string); ok {
|
if ctxReqID, ok := entry.Context.Value(context.RequestIDKey).(string); ok {
|
||||||
entry.Data[context.RequestIDKey] = ctxReqID
|
entry.Data[context.RequestIDKey] = ctxReqID
|
||||||
}
|
}
|
||||||
@@ -109,30 +102,6 @@ func addHTTPFields(entry *logrus.Entry) {
|
|||||||
if ctxInitiatorID, ok := entry.Context.Value(context.UserIDKey).(string); ok {
|
if ctxInitiatorID, ok := entry.Context.Value(context.UserIDKey).(string); ok {
|
||||||
entry.Data[context.UserIDKey] = ctxInitiatorID
|
entry.Data[context.UserIDKey] = ctxInitiatorID
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func addGRPCFields(entry *logrus.Entry) {
|
|
||||||
if ctxReqID, ok := entry.Context.Value(context.RequestIDKey).(string); ok {
|
|
||||||
entry.Data[context.RequestIDKey] = ctxReqID
|
|
||||||
}
|
|
||||||
if ctxAccountID, ok := entry.Context.Value(context.AccountIDKey).(string); ok {
|
|
||||||
entry.Data[context.AccountIDKey] = ctxAccountID
|
|
||||||
}
|
|
||||||
if ctxDeviceID, ok := entry.Context.Value(context.PeerIDKey).(string); ok {
|
|
||||||
entry.Data[context.PeerIDKey] = ctxDeviceID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func addSystemFields(entry *logrus.Entry) {
|
|
||||||
if ctxReqID, ok := entry.Context.Value(context.RequestIDKey).(string); ok {
|
|
||||||
entry.Data[context.RequestIDKey] = ctxReqID
|
|
||||||
}
|
|
||||||
if ctxInitiatorID, ok := entry.Context.Value(context.UserIDKey).(string); ok {
|
|
||||||
entry.Data[context.UserIDKey] = ctxInitiatorID
|
|
||||||
}
|
|
||||||
if ctxAccountID, ok := entry.Context.Value(context.AccountIDKey).(string); ok {
|
|
||||||
entry.Data[context.AccountIDKey] = ctxAccountID
|
|
||||||
}
|
|
||||||
if ctxDeviceID, ok := entry.Context.Value(context.PeerIDKey).(string); ok {
|
if ctxDeviceID, ok := entry.Context.Value(context.PeerIDKey).(string); ok {
|
||||||
entry.Data[context.PeerIDKey] = ctxDeviceID
|
entry.Data[context.PeerIDKey] = ctxDeviceID
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ func (c *Controller) sendUpdateAccountPeers(ctx context.Context, accountID strin
|
|||||||
if c.experimentalNetworkMap(accountID) {
|
if c.experimentalNetworkMap(accountID) {
|
||||||
account = c.getAccountFromHolderOrInit(accountID)
|
account = c.getAccountFromHolderOrInit(accountID)
|
||||||
} else {
|
} else {
|
||||||
account, err = c.requestBuffer.GetAccountWithBackpressure(ctx, accountID)
|
account, err = c.requestBuffer.GetAccountLightWithBackpressure(ctx, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to get account: %v", err)
|
return fmt.Errorf("failed to get account: %v", err)
|
||||||
}
|
}
|
||||||
@@ -300,7 +300,7 @@ func (c *Controller) UpdateAccountPeer(ctx context.Context, accountId string, pe
|
|||||||
return fmt.Errorf("peer %s doesn't have a channel, skipping network map update", peerId)
|
return fmt.Errorf("peer %s doesn't have a channel, skipping network map update", peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
account, err := c.requestBuffer.GetAccountWithBackpressure(ctx, accountId)
|
account, err := c.requestBuffer.GetAccountLightWithBackpressure(ctx, accountId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to send out updates to peer %s: %v", peerId, err)
|
return fmt.Errorf("failed to send out updates to peer %s: %v", peerId, err)
|
||||||
}
|
}
|
||||||
@@ -414,7 +414,7 @@ func (c *Controller) GetValidatedPeerWithMap(ctx context.Context, isRequiresAppr
|
|||||||
if c.experimentalNetworkMap(accountID) {
|
if c.experimentalNetworkMap(accountID) {
|
||||||
account = c.getAccountFromHolderOrInit(accountID)
|
account = c.getAccountFromHolderOrInit(accountID)
|
||||||
} else {
|
} else {
|
||||||
account, err = c.requestBuffer.GetAccountWithBackpressure(ctx, accountID)
|
account, err = c.requestBuffer.GetAccountLightWithBackpressure(ctx, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, 0, err
|
return nil, nil, nil, 0, err
|
||||||
}
|
}
|
||||||
@@ -506,7 +506,7 @@ func (c *Controller) recalculateNetworkMapCache(account *types.Account, validate
|
|||||||
|
|
||||||
func (c *Controller) RecalculateNetworkMapCache(ctx context.Context, accountId string) error {
|
func (c *Controller) RecalculateNetworkMapCache(ctx context.Context, accountId string) error {
|
||||||
if c.experimentalNetworkMap(accountId) {
|
if c.experimentalNetworkMap(accountId) {
|
||||||
account, err := c.requestBuffer.GetAccountWithBackpressure(ctx, accountId)
|
account, err := c.requestBuffer.GetAccountLightWithBackpressure(ctx, accountId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -548,7 +548,7 @@ func (c *Controller) getAccountFromHolderOrInit(accountID string) *types.Account
|
|||||||
if a != nil {
|
if a != nil {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
account, err := c.holder.LoadOrStoreFunc(accountID, c.requestBuffer.GetAccountWithBackpressure)
|
account, err := c.holder.LoadOrStoreFunc(accountID, c.requestBuffer.GetAccountLightWithBackpressure)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -715,7 +715,7 @@ func (c *Controller) OnPeersUpdated(ctx context.Context, accountID string, peerI
|
|||||||
func (c *Controller) OnPeersAdded(ctx context.Context, accountID string, peerIDs []string) error {
|
func (c *Controller) OnPeersAdded(ctx context.Context, accountID string, peerIDs []string) error {
|
||||||
for _, peerID := range peerIDs {
|
for _, peerID := range peerIDs {
|
||||||
if c.experimentalNetworkMap(accountID) {
|
if c.experimentalNetworkMap(accountID) {
|
||||||
account, err := c.requestBuffer.GetAccountWithBackpressure(ctx, accountID)
|
account, err := c.requestBuffer.GetAccountLightWithBackpressure(ctx, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -761,7 +761,7 @@ func (c *Controller) OnPeersDeleted(ctx context.Context, accountID string, peerI
|
|||||||
c.peersUpdateManager.CloseChannel(ctx, peerID)
|
c.peersUpdateManager.CloseChannel(ctx, peerID)
|
||||||
|
|
||||||
if c.experimentalNetworkMap(accountID) {
|
if c.experimentalNetworkMap(accountID) {
|
||||||
account, err := c.requestBuffer.GetAccountWithBackpressure(ctx, accountID)
|
account, err := c.requestBuffer.GetAccountLightWithBackpressure(ctx, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithContext(ctx).Errorf("failed to get account %s: %v", accountID, err)
|
log.WithContext(ctx).Errorf("failed to get account %s: %v", accountID, err)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
grpcMiddleware "github.com/grpc-ecosystem/go-grpc-middleware/v2"
|
grpcMiddleware "github.com/grpc-ecosystem/go-grpc-middleware/v2"
|
||||||
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip"
|
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/realip"
|
||||||
|
"github.com/rs/xid"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
@@ -180,7 +180,7 @@ func unaryInterceptor(
|
|||||||
info *grpc.UnaryServerInfo,
|
info *grpc.UnaryServerInfo,
|
||||||
handler grpc.UnaryHandler,
|
handler grpc.UnaryHandler,
|
||||||
) (interface{}, error) {
|
) (interface{}, error) {
|
||||||
reqID := uuid.New().String()
|
reqID := xid.New().String()
|
||||||
//nolint
|
//nolint
|
||||||
ctx = context.WithValue(ctx, hook.ExecutionContextKey, hook.GRPCSource)
|
ctx = context.WithValue(ctx, hook.ExecutionContextKey, hook.GRPCSource)
|
||||||
//nolint
|
//nolint
|
||||||
@@ -194,7 +194,7 @@ func streamInterceptor(
|
|||||||
info *grpc.StreamServerInfo,
|
info *grpc.StreamServerInfo,
|
||||||
handler grpc.StreamHandler,
|
handler grpc.StreamHandler,
|
||||||
) error {
|
) error {
|
||||||
reqID := uuid.New().String()
|
reqID := xid.New().String()
|
||||||
wrapped := grpcMiddleware.WrapServerStream(ss)
|
wrapped := grpcMiddleware.WrapServerStream(ss)
|
||||||
//nolint
|
//nolint
|
||||||
ctx := context.WithValue(ss.Context(), hook.ExecutionContextKey, hook.GRPCSource)
|
ctx := context.WithValue(ss.Context(), hook.ExecutionContextKey, hook.GRPCSource)
|
||||||
|
|||||||
@@ -7,5 +7,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type RequestBuffer interface {
|
type RequestBuffer interface {
|
||||||
GetAccountWithBackpressure(ctx context.Context, accountID string) (*types.Account, error)
|
// GetAccountLightWithBackpressure returns account without users, setup keys, and onboarding data with request buffering
|
||||||
|
GetAccountLightWithBackpressure(ctx context.Context, accountID string) (*types.Account, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,11 +25,13 @@ type AccountResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AccountRequestBuffer struct {
|
type AccountRequestBuffer struct {
|
||||||
store store.Store
|
store store.Store
|
||||||
getAccountRequests map[string][]*AccountRequest
|
getAccountRequests map[string][]*AccountRequest
|
||||||
mu sync.Mutex
|
getAccountLightRequests map[string][]*AccountRequest
|
||||||
getAccountRequestCh chan *AccountRequest
|
mu sync.Mutex
|
||||||
bufferInterval time.Duration
|
getAccountRequestCh chan *AccountRequest
|
||||||
|
getAccountLightRequestCh chan *AccountRequest
|
||||||
|
bufferInterval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAccountRequestBuffer(ctx context.Context, store store.Store) *AccountRequestBuffer {
|
func NewAccountRequestBuffer(ctx context.Context, store store.Store) *AccountRequestBuffer {
|
||||||
@@ -45,13 +47,16 @@ func NewAccountRequestBuffer(ctx context.Context, store store.Store) *AccountReq
|
|||||||
log.WithContext(ctx).Infof("set account request buffer interval to %s", bufferInterval)
|
log.WithContext(ctx).Infof("set account request buffer interval to %s", bufferInterval)
|
||||||
|
|
||||||
ac := AccountRequestBuffer{
|
ac := AccountRequestBuffer{
|
||||||
store: store,
|
store: store,
|
||||||
getAccountRequests: make(map[string][]*AccountRequest),
|
getAccountRequests: make(map[string][]*AccountRequest),
|
||||||
getAccountRequestCh: make(chan *AccountRequest),
|
getAccountLightRequests: make(map[string][]*AccountRequest),
|
||||||
bufferInterval: bufferInterval,
|
getAccountRequestCh: make(chan *AccountRequest),
|
||||||
|
getAccountLightRequestCh: make(chan *AccountRequest),
|
||||||
|
bufferInterval: bufferInterval,
|
||||||
}
|
}
|
||||||
|
|
||||||
go ac.processGetAccountRequests(ctx)
|
go ac.processGetAccountRequests(ctx)
|
||||||
|
go ac.processGetAccountLightRequests(ctx)
|
||||||
|
|
||||||
return &ac
|
return &ac
|
||||||
}
|
}
|
||||||
@@ -70,6 +75,22 @@ func (ac *AccountRequestBuffer) GetAccountWithBackpressure(ctx context.Context,
|
|||||||
return result.Account, result.Err
|
return result.Account, result.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAccountLightWithBackpressure returns account without users, setup keys, and onboarding data with request buffering
|
||||||
|
func (ac *AccountRequestBuffer) GetAccountLightWithBackpressure(ctx context.Context, accountID string) (*types.Account, error) {
|
||||||
|
req := &AccountRequest{
|
||||||
|
AccountID: accountID,
|
||||||
|
ResultChan: make(chan *AccountResult, 1),
|
||||||
|
}
|
||||||
|
|
||||||
|
log.WithContext(ctx).Tracef("requesting account light %s with backpressure", accountID)
|
||||||
|
startTime := time.Now()
|
||||||
|
ac.getAccountLightRequestCh <- req
|
||||||
|
|
||||||
|
result := <-req.ResultChan
|
||||||
|
log.WithContext(ctx).Tracef("got account light with backpressure after %s", time.Since(startTime))
|
||||||
|
return result.Account, result.Err
|
||||||
|
}
|
||||||
|
|
||||||
func (ac *AccountRequestBuffer) processGetAccountBatch(ctx context.Context, accountID string) {
|
func (ac *AccountRequestBuffer) processGetAccountBatch(ctx context.Context, accountID string) {
|
||||||
ac.mu.Lock()
|
ac.mu.Lock()
|
||||||
requests := ac.getAccountRequests[accountID]
|
requests := ac.getAccountRequests[accountID]
|
||||||
@@ -109,3 +130,43 @@ func (ac *AccountRequestBuffer) processGetAccountRequests(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ac *AccountRequestBuffer) processGetAccountLightBatch(ctx context.Context, accountID string) {
|
||||||
|
ac.mu.Lock()
|
||||||
|
requests := ac.getAccountLightRequests[accountID]
|
||||||
|
delete(ac.getAccountLightRequests, accountID)
|
||||||
|
ac.mu.Unlock()
|
||||||
|
|
||||||
|
if len(requests) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
startTime := time.Now()
|
||||||
|
account, err := ac.store.GetAccountLight(ctx, accountID)
|
||||||
|
log.WithContext(ctx).Tracef("getting account light %s in batch took %s", accountID, time.Since(startTime))
|
||||||
|
result := &AccountResult{Account: account, Err: err}
|
||||||
|
|
||||||
|
for _, req := range requests {
|
||||||
|
req.ResultChan <- result
|
||||||
|
close(req.ResultChan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ac *AccountRequestBuffer) processGetAccountLightRequests(ctx context.Context) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case req := <-ac.getAccountLightRequestCh:
|
||||||
|
ac.mu.Lock()
|
||||||
|
ac.getAccountLightRequests[req.AccountID] = append(ac.getAccountLightRequests[req.AccountID], req)
|
||||||
|
if len(ac.getAccountLightRequests[req.AccountID]) == 1 {
|
||||||
|
go func(ctx context.Context, accountID string) {
|
||||||
|
time.Sleep(ac.bufferInterval)
|
||||||
|
ac.processGetAccountLightBatch(ctx, accountID)
|
||||||
|
}(ctx, req.AccountID)
|
||||||
|
}
|
||||||
|
ac.mu.Unlock()
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -796,6 +796,14 @@ func (s *SqlStore) GetAccount(ctx context.Context, accountID string) (*types.Acc
|
|||||||
return s.getAccountGorm(ctx, accountID)
|
return s.getAccountGorm(ctx, accountID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAccountLight returns account without users, setup keys, and onboarding data
|
||||||
|
func (s *SqlStore) GetAccountLight(ctx context.Context, accountID string) (*types.Account, error) {
|
||||||
|
if s.pool != nil {
|
||||||
|
return s.getAccountLightPgx(ctx, accountID)
|
||||||
|
}
|
||||||
|
return s.getAccountLightGorm(ctx, accountID)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SqlStore) getAccountGorm(ctx context.Context, accountID string) (*types.Account, error) {
|
func (s *SqlStore) getAccountGorm(ctx context.Context, accountID string) (*types.Account, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
defer func() {
|
defer func() {
|
||||||
@@ -897,6 +905,82 @@ func (s *SqlStore) getAccountGorm(ctx context.Context, accountID string) (*types
|
|||||||
return &account, nil
|
return &account, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SqlStore) getAccountLightGorm(ctx context.Context, accountID string) (*types.Account, error) {
|
||||||
|
start := time.Now()
|
||||||
|
defer func() {
|
||||||
|
elapsed := time.Since(start)
|
||||||
|
if elapsed > 1*time.Second {
|
||||||
|
log.WithContext(ctx).Tracef("GetAccountLight for account %s exceeded 1s, took: %v", accountID, elapsed)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var account types.Account
|
||||||
|
result := s.db.Model(&account).
|
||||||
|
Preload("Policies.Rules").
|
||||||
|
Preload("PeersG").
|
||||||
|
Preload("GroupsG.GroupPeers").
|
||||||
|
Preload("RoutesG").
|
||||||
|
Preload("NameServerGroupsG").
|
||||||
|
Preload("PostureChecks").
|
||||||
|
Preload("Networks").
|
||||||
|
Preload("NetworkRouters").
|
||||||
|
Preload("NetworkResources").
|
||||||
|
Take(&account, idQueryCondition, accountID)
|
||||||
|
if result.Error != nil {
|
||||||
|
log.WithContext(ctx).Errorf("error when getting account %s from the store: %s", accountID, result.Error)
|
||||||
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, status.NewAccountNotFoundError(accountID)
|
||||||
|
}
|
||||||
|
return nil, status.NewGetAccountFromStoreError(result.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
account.SetupKeys = make(map[string]*types.SetupKey)
|
||||||
|
|
||||||
|
account.Peers = make(map[string]*nbpeer.Peer, len(account.PeersG))
|
||||||
|
for _, peer := range account.PeersG {
|
||||||
|
account.Peers[peer.ID] = &peer
|
||||||
|
}
|
||||||
|
account.PeersG = nil
|
||||||
|
|
||||||
|
account.Users = make(map[string]*types.User)
|
||||||
|
|
||||||
|
account.Groups = make(map[string]*types.Group, len(account.GroupsG))
|
||||||
|
for _, group := range account.GroupsG {
|
||||||
|
group.Peers = make([]string, len(group.GroupPeers))
|
||||||
|
for i, gp := range group.GroupPeers {
|
||||||
|
group.Peers[i] = gp.PeerID
|
||||||
|
}
|
||||||
|
if group.Resources == nil {
|
||||||
|
group.Resources = []types.Resource{}
|
||||||
|
}
|
||||||
|
account.Groups[group.ID] = group
|
||||||
|
}
|
||||||
|
account.GroupsG = nil
|
||||||
|
|
||||||
|
account.Routes = make(map[route.ID]*route.Route, len(account.RoutesG))
|
||||||
|
for _, route := range account.RoutesG {
|
||||||
|
account.Routes[route.ID] = &route
|
||||||
|
}
|
||||||
|
account.RoutesG = nil
|
||||||
|
account.NameServerGroups = make(map[string]*nbdns.NameServerGroup, len(account.NameServerGroupsG))
|
||||||
|
for _, ns := range account.NameServerGroupsG {
|
||||||
|
ns.AccountID = ""
|
||||||
|
if ns.NameServers == nil {
|
||||||
|
ns.NameServers = []nbdns.NameServer{}
|
||||||
|
}
|
||||||
|
if ns.Groups == nil {
|
||||||
|
ns.Groups = []string{}
|
||||||
|
}
|
||||||
|
if ns.Domains == nil {
|
||||||
|
ns.Domains = []string{}
|
||||||
|
}
|
||||||
|
account.NameServerGroups[ns.ID] = &ns
|
||||||
|
}
|
||||||
|
account.NameServerGroupsG = nil
|
||||||
|
account.InitOnce()
|
||||||
|
return &account, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SqlStore) getAccountPgx(ctx context.Context, accountID string) (*types.Account, error) {
|
func (s *SqlStore) getAccountPgx(ctx context.Context, accountID string) (*types.Account, error) {
|
||||||
account, err := s.getAccount(ctx, accountID)
|
account, err := s.getAccount(ctx, accountID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1180,6 +1264,221 @@ func (s *SqlStore) getAccountPgx(ctx context.Context, accountID string) (*types.
|
|||||||
return account, nil
|
return account, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SqlStore) getAccountLightPgx(ctx context.Context, accountID string) (*types.Account, error) {
|
||||||
|
account, err := s.getAccount(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
errChan := make(chan error, 9)
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
peers, err := s.getPeers(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
account.PeersG = peers
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
groups, err := s.getGroups(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
account.GroupsG = groups
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
policies, err := s.getPolicies(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
account.Policies = policies
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
routes, err := s.getRoutes(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
account.RoutesG = routes
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
nsgs, err := s.getNameServerGroups(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
account.NameServerGroupsG = nsgs
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
checks, err := s.getPostureChecks(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
account.PostureChecks = checks
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
networks, err := s.getNetworks(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
account.Networks = networks
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
routers, err := s.getNetworkRouters(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
account.NetworkRouters = routers
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
resources, err := s.getNetworkResources(ctx, accountID)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
account.NetworkResources = resources
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
close(errChan)
|
||||||
|
for e := range errChan {
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var policyIDs []string
|
||||||
|
for _, p := range account.Policies {
|
||||||
|
policyIDs = append(policyIDs, p.ID)
|
||||||
|
}
|
||||||
|
var groupIDs []string
|
||||||
|
for _, g := range account.GroupsG {
|
||||||
|
groupIDs = append(groupIDs, g.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Add(2)
|
||||||
|
errChan = make(chan error, 2)
|
||||||
|
|
||||||
|
var rules []*types.PolicyRule
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
var err error
|
||||||
|
rules, err = s.getPolicyRules(ctx, policyIDs)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var groupPeers []types.GroupPeer
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
var err error
|
||||||
|
groupPeers, err = s.getGroupPeers(ctx, groupIDs)
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
close(errChan)
|
||||||
|
for e := range errChan {
|
||||||
|
if e != nil {
|
||||||
|
return nil, e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rulesByPolicyID := make(map[string][]*types.PolicyRule)
|
||||||
|
for _, rule := range rules {
|
||||||
|
rulesByPolicyID[rule.PolicyID] = append(rulesByPolicyID[rule.PolicyID], rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
peersByGroupID := make(map[string][]string)
|
||||||
|
for _, gp := range groupPeers {
|
||||||
|
peersByGroupID[gp.GroupID] = append(peersByGroupID[gp.GroupID], gp.PeerID)
|
||||||
|
}
|
||||||
|
|
||||||
|
account.SetupKeys = make(map[string]*types.SetupKey)
|
||||||
|
|
||||||
|
account.Peers = make(map[string]*nbpeer.Peer, len(account.PeersG))
|
||||||
|
for i := range account.PeersG {
|
||||||
|
peer := &account.PeersG[i]
|
||||||
|
account.Peers[peer.ID] = peer
|
||||||
|
}
|
||||||
|
|
||||||
|
account.Users = make(map[string]*types.User)
|
||||||
|
|
||||||
|
for i := range account.Policies {
|
||||||
|
policy := account.Policies[i]
|
||||||
|
if policyRules, ok := rulesByPolicyID[policy.ID]; ok {
|
||||||
|
policy.Rules = policyRules
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
account.Groups = make(map[string]*types.Group, len(account.GroupsG))
|
||||||
|
for i := range account.GroupsG {
|
||||||
|
group := account.GroupsG[i]
|
||||||
|
if peerIDs, ok := peersByGroupID[group.ID]; ok {
|
||||||
|
group.Peers = peerIDs
|
||||||
|
}
|
||||||
|
account.Groups[group.ID] = group
|
||||||
|
}
|
||||||
|
|
||||||
|
account.Routes = make(map[route.ID]*route.Route, len(account.RoutesG))
|
||||||
|
for i := range account.RoutesG {
|
||||||
|
route := &account.RoutesG[i]
|
||||||
|
account.Routes[route.ID] = route
|
||||||
|
}
|
||||||
|
|
||||||
|
account.NameServerGroups = make(map[string]*nbdns.NameServerGroup, len(account.NameServerGroupsG))
|
||||||
|
for i := range account.NameServerGroupsG {
|
||||||
|
nsg := &account.NameServerGroupsG[i]
|
||||||
|
nsg.AccountID = ""
|
||||||
|
account.NameServerGroups[nsg.ID] = nsg
|
||||||
|
}
|
||||||
|
|
||||||
|
account.SetupKeysG = nil
|
||||||
|
account.PeersG = nil
|
||||||
|
account.UsersG = nil
|
||||||
|
account.GroupsG = nil
|
||||||
|
account.RoutesG = nil
|
||||||
|
account.NameServerGroupsG = nil
|
||||||
|
|
||||||
|
return account, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SqlStore) getAccount(ctx context.Context, accountID string) (*types.Account, error) {
|
func (s *SqlStore) getAccount(ctx context.Context, accountID string) (*types.Account, error) {
|
||||||
var account types.Account
|
var account types.Account
|
||||||
account.Network = &types.Network{}
|
account.Network = &types.Network{}
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ type Store interface {
|
|||||||
GetAccountsCounter(ctx context.Context) (int64, error)
|
GetAccountsCounter(ctx context.Context) (int64, error)
|
||||||
GetAllAccounts(ctx context.Context) []*types.Account
|
GetAllAccounts(ctx context.Context) []*types.Account
|
||||||
GetAccount(ctx context.Context, accountID string) (*types.Account, error)
|
GetAccount(ctx context.Context, accountID string) (*types.Account, error)
|
||||||
|
// GetAccountLight returns account without users, setup keys, and onboarding data
|
||||||
|
GetAccountLight(ctx context.Context, accountID string) (*types.Account, error)
|
||||||
GetAccountMeta(ctx context.Context, lockStrength LockingStrength, accountID string) (*types.AccountMeta, error)
|
GetAccountMeta(ctx context.Context, lockStrength LockingStrength, accountID string) (*types.AccountMeta, error)
|
||||||
GetAccountOnboarding(ctx context.Context, accountID string) (*types.AccountOnboarding, error)
|
GetAccountOnboarding(ctx context.Context, accountID string) (*types.AccountOnboarding, error)
|
||||||
AccountExists(ctx context.Context, lockStrength LockingStrength, id string) (bool, error)
|
AccountExists(ctx context.Context, lockStrength LockingStrength, id string) (bool, error)
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/rs/xid"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"go.opentelemetry.io/otel/attribute"
|
"go.opentelemetry.io/otel/attribute"
|
||||||
"go.opentelemetry.io/otel/metric"
|
"go.opentelemetry.io/otel/metric"
|
||||||
@@ -169,7 +169,7 @@ func (m *HTTPMiddleware) Handler(h http.Handler) http.Handler {
|
|||||||
//nolint
|
//nolint
|
||||||
ctx := context.WithValue(r.Context(), hook.ExecutionContextKey, hook.HTTPSource)
|
ctx := context.WithValue(r.Context(), hook.ExecutionContextKey, hook.HTTPSource)
|
||||||
|
|
||||||
reqID := uuid.New().String()
|
reqID := xid.New().String()
|
||||||
//nolint
|
//nolint
|
||||||
ctx = context.WithValue(ctx, nbContext.RequestIDKey, reqID)
|
ctx = context.WithValue(ctx, nbContext.RequestIDKey, reqID)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user