diff --git a/.github/ISSUE_TEMPLATE/bug-issue-report.md b/.github/ISSUE_TEMPLATE/bug-issue-report.md index 87f757f42..3633cca4f 100644 --- a/.github/ISSUE_TEMPLATE/bug-issue-report.md +++ b/.github/ISSUE_TEMPLATE/bug-issue-report.md @@ -31,14 +31,22 @@ Please specify whether you use NetBird Cloud or self-host NetBird's control plan `netbird version` -**NetBird status -dA output:** +**Is any other VPN software installed?** -If applicable, add the `netbird status -dA' command output. +If yes, which one? -**Do you face any (non-mobile) client issues?** +**Debug output** -Please provide the file created by `netbird debug for 1m -AS`. -We advise reviewing the anonymized files for any remaining PII. +To help us resolve the problem, please attach the following debug output + + netbird status -dA + +As well as the file created by + + netbird debug for 1m -AS + + +We advise reviewing the anonymized output for any remaining personal information. **Screenshots** @@ -47,3 +55,10 @@ If applicable, add screenshots to help explain your problem. **Additional context** Add any other context about the problem here. + +**Have you tried these troubleshooting steps?** +- [ ] Checked for newer NetBird versions +- [ ] Searched for similar issues on GitHub (including closed ones) +- [ ] Restarted the NetBird client +- [ ] Disabled other VPN software +- [ ] Checked firewall settings diff --git a/.github/workflows/golang-test-linux.yml b/.github/workflows/golang-test-linux.yml index 3be8bcff3..cf061f876 100644 --- a/.github/workflows/golang-test-linux.yml +++ b/.github/workflows/golang-test-linux.yml @@ -258,7 +258,7 @@ jobs: strategy: fail-fast: false matrix: - arch: [ '386','amd64' ] + arch: [ 'amd64' ] store: [ 'sqlite', 'postgres', 'mysql' ] runs-on: ubuntu-22.04 steps: @@ -325,8 +325,8 @@ jobs: strategy: fail-fast: false matrix: - arch: [ '386','amd64' ] - store: [ 'sqlite', 'postgres', 'mysql' ] + arch: [ 'amd64' ] + store: [ 'sqlite', 'postgres' ] runs-on: ubuntu-22.04 steps: - name: Install Go @@ -392,7 +392,7 @@ jobs: strategy: fail-fast: false matrix: - arch: [ '386','amd64' ] + arch: [ 'amd64' ] store: [ 'sqlite', 'postgres' ] runs-on: ubuntu-22.04 steps: @@ -461,7 +461,7 @@ jobs: strategy: fail-fast: false matrix: - arch: [ '386','amd64' ] + arch: [ 'amd64' ] store: [ 'sqlite', 'postgres'] runs-on: ubuntu-22.04 steps: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 04874bdf4..919351f18 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,7 +71,7 @@ jobs: - name: Install goversioninfo run: go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@233067e - name: Generate windows syso amd64 - run: goversioninfo -icon client/ui/netbird.ico -manifest client/manifest.xml -product-name ${{ env.PRODUCT_NAME }} -copyright "${{ env.COPYRIGHT }}" -ver-major ${{ steps.semver_parser.outputs.major }} -ver-minor ${{ steps.semver_parser.outputs.minor }} -ver-patch ${{ steps.semver_parser.outputs.patch }} -ver-build 0 -file-version ${{ steps.semver_parser.outputs.fullversion }}.0 -product-version ${{ steps.semver_parser.outputs.fullversion }}.0 -o client/resources_windows_amd64.syso + run: goversioninfo -icon client/ui/assets/netbird.ico -manifest client/manifest.xml -product-name ${{ env.PRODUCT_NAME }} -copyright "${{ env.COPYRIGHT }}" -ver-major ${{ steps.semver_parser.outputs.major }} -ver-minor ${{ steps.semver_parser.outputs.minor }} -ver-patch ${{ steps.semver_parser.outputs.patch }} -ver-build 0 -file-version ${{ steps.semver_parser.outputs.fullversion }}.0 -product-version ${{ steps.semver_parser.outputs.fullversion }}.0 -o client/resources_windows_amd64.syso - name: Run GoReleaser uses: goreleaser/goreleaser-action@v4 with: @@ -150,7 +150,7 @@ jobs: - name: Install goversioninfo run: go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@233067e - name: Generate windows syso amd64 - run: goversioninfo -64 -icon client/ui/netbird.ico -manifest client/ui/manifest.xml -product-name ${{ env.PRODUCT_NAME }}-"UI" -copyright "${{ env.COPYRIGHT }}" -ver-major ${{ steps.semver_parser.outputs.major }} -ver-minor ${{ steps.semver_parser.outputs.minor }} -ver-patch ${{ steps.semver_parser.outputs.patch }} -ver-build 0 -file-version ${{ steps.semver_parser.outputs.fullversion }}.0 -product-version ${{ steps.semver_parser.outputs.fullversion }}.0 -o client/ui/resources_windows_amd64.syso + run: goversioninfo -64 -icon client/ui/assets/netbird.ico -manifest client/ui/manifest.xml -product-name ${{ env.PRODUCT_NAME }}-"UI" -copyright "${{ env.COPYRIGHT }}" -ver-major ${{ steps.semver_parser.outputs.major }} -ver-minor ${{ steps.semver_parser.outputs.minor }} -ver-patch ${{ steps.semver_parser.outputs.patch }} -ver-build 0 -file-version ${{ steps.semver_parser.outputs.fullversion }}.0 -product-version ${{ steps.semver_parser.outputs.fullversion }}.0 -o client/ui/resources_windows_amd64.syso - name: Run GoReleaser uses: goreleaser/goreleaser-action@v4 diff --git a/.goreleaser_ui.yaml b/.goreleaser_ui.yaml index 1dd649d1b..459f204d3 100644 --- a/.goreleaser_ui.yaml +++ b/.goreleaser_ui.yaml @@ -53,9 +53,9 @@ nfpms: scripts: postinstall: "release_files/ui-post-install.sh" contents: - - src: client/ui/netbird.desktop + - src: client/ui/build/netbird.desktop dst: /usr/share/applications/netbird.desktop - - src: client/ui/netbird.png + - src: client/ui/assets/netbird.png dst: /usr/share/pixmaps/netbird.png dependencies: - netbird @@ -72,9 +72,9 @@ nfpms: scripts: postinstall: "release_files/ui-post-install.sh" contents: - - src: client/ui/netbird.desktop + - src: client/ui/build/netbird.desktop dst: /usr/share/applications/netbird.desktop - - src: client/ui/netbird.png + - src: client/ui/assets/netbird.png dst: /usr/share/pixmaps/netbird.png dependencies: - netbird diff --git a/client/firewall/iptables/manager_linux.go b/client/firewall/iptables/manager_linux.go index f8c8945e6..542a13c1f 100644 --- a/client/firewall/iptables/manager_linux.go +++ b/client/firewall/iptables/manager_linux.go @@ -167,7 +167,7 @@ func (m *Manager) SetLegacyManagement(isLegacy bool) error { } // Reset firewall to the default state -func (m *Manager) Reset(stateManager *statemanager.Manager) error { +func (m *Manager) Close(stateManager *statemanager.Manager) error { m.mutex.Lock() defer m.mutex.Unlock() diff --git a/client/firewall/iptables/manager_linux_test.go b/client/firewall/iptables/manager_linux_test.go index 0dcbc8f5d..23926d059 100644 --- a/client/firewall/iptables/manager_linux_test.go +++ b/client/firewall/iptables/manager_linux_test.go @@ -62,7 +62,7 @@ func TestIptablesManager(t *testing.T) { time.Sleep(time.Second) defer func() { - err := manager.Reset(nil) + err := manager.Close(nil) require.NoError(t, err, "clear the manager state") time.Sleep(time.Second) @@ -100,14 +100,14 @@ func TestIptablesManager(t *testing.T) { _, err = manager.AddPeerFiltering(nil, ip, "udp", nil, port, fw.ActionAccept, "") require.NoError(t, err, "failed to add rule") - err = manager.Reset(nil) + err = manager.Close(nil) require.NoError(t, err, "failed to reset") ok, err := ipv4Client.ChainExists("filter", chainNameInputRules) require.NoError(t, err, "failed check chain exists") if ok { - require.NoErrorf(t, err, "chain '%v' still exists after Reset", chainNameInputRules) + require.NoErrorf(t, err, "chain '%v' still exists after Close", chainNameInputRules) } }) } @@ -136,7 +136,7 @@ func TestIptablesManagerIPSet(t *testing.T) { time.Sleep(time.Second) defer func() { - err := manager.Reset(nil) + err := manager.Close(nil) require.NoError(t, err, "clear the manager state") time.Sleep(time.Second) @@ -166,7 +166,7 @@ func TestIptablesManagerIPSet(t *testing.T) { }) t.Run("reset check", func(t *testing.T) { - err = manager.Reset(nil) + err = manager.Close(nil) require.NoError(t, err, "failed to reset") }) } @@ -204,7 +204,7 @@ func TestIptablesCreatePerformance(t *testing.T) { time.Sleep(time.Second) defer func() { - err := manager.Reset(nil) + err := manager.Close(nil) require.NoError(t, err, "clear the manager state") time.Sleep(time.Second) diff --git a/client/firewall/iptables/state_linux.go b/client/firewall/iptables/state_linux.go index 44b8340ba..2a7120bbf 100644 --- a/client/firewall/iptables/state_linux.go +++ b/client/firewall/iptables/state_linux.go @@ -62,7 +62,7 @@ func (s *ShutdownState) Cleanup() error { ipt.aclMgr.ipsetStore = s.ACLIPsetStore } - if err := ipt.Reset(nil); err != nil { + if err := ipt.Close(nil); err != nil { return fmt.Errorf("reset iptables manager: %w", err) } diff --git a/client/firewall/manager/firewall.go b/client/firewall/manager/firewall.go index 6d369f649..1d71051ef 100644 --- a/client/firewall/manager/firewall.go +++ b/client/firewall/manager/firewall.go @@ -102,8 +102,8 @@ type Manager interface { // SetLegacyManagement sets the legacy management mode SetLegacyManagement(legacy bool) error - // Reset firewall to the default state - Reset(stateManager *statemanager.Manager) error + // Close closes the firewall manager + Close(stateManager *statemanager.Manager) error // Flush the changes to firewall controller Flush() error diff --git a/client/firewall/nftables/manager_linux.go b/client/firewall/nftables/manager_linux.go index 878ede2da..475601d17 100644 --- a/client/firewall/nftables/manager_linux.go +++ b/client/firewall/nftables/manager_linux.go @@ -87,7 +87,7 @@ func (m *Manager) Init(stateManager *statemanager.Manager) error { // We only need to record minimal interface state for potential recreation. // Unlike iptables, which requires tracking individual rules, nftables maintains // a known state (our netbird table plus a few static rules). This allows for easy - // cleanup using Reset() without needing to store specific rules. + // cleanup using Close() without needing to store specific rules. if err := stateManager.UpdateState(&ShutdownState{ InterfaceState: &InterfaceState{ NameStr: m.wgIface.Name(), @@ -243,7 +243,7 @@ func (m *Manager) SetLegacyManagement(isLegacy bool) error { } // Reset firewall to the default state -func (m *Manager) Reset(stateManager *statemanager.Manager) error { +func (m *Manager) Close(stateManager *statemanager.Manager) error { m.mutex.Lock() defer m.mutex.Unlock() diff --git a/client/firewall/nftables/manager_linux_test.go b/client/firewall/nftables/manager_linux_test.go index bfdffd9e3..3f1a6e4b3 100644 --- a/client/firewall/nftables/manager_linux_test.go +++ b/client/firewall/nftables/manager_linux_test.go @@ -65,7 +65,7 @@ func TestNftablesManager(t *testing.T) { time.Sleep(time.Second * 3) defer func() { - err = manager.Reset(nil) + err = manager.Close(nil) require.NoError(t, err, "failed to reset") time.Sleep(time.Second) }() @@ -162,7 +162,7 @@ func TestNftablesManager(t *testing.T) { // established rule remains require.Len(t, rules, 1, "expected 1 rules after deletion") - err = manager.Reset(nil) + err = manager.Close(nil) require.NoError(t, err, "failed to reset") } @@ -191,7 +191,7 @@ func TestNFtablesCreatePerformance(t *testing.T) { time.Sleep(time.Second * 3) defer func() { - if err := manager.Reset(nil); err != nil { + if err := manager.Close(nil); err != nil { t.Errorf("clear the manager state: %v", err) } time.Sleep(time.Second) @@ -274,7 +274,7 @@ func TestNftablesManagerCompatibilityWithIptables(t *testing.T) { require.NoError(t, manager.Init(nil)) t.Cleanup(func() { - err := manager.Reset(nil) + err := manager.Close(nil) require.NoError(t, err, "failed to reset manager state") // Verify iptables output after reset diff --git a/client/firewall/nftables/router_linux_test.go b/client/firewall/nftables/router_linux_test.go index 87a219a70..498fdf882 100644 --- a/client/firewall/nftables/router_linux_test.go +++ b/client/firewall/nftables/router_linux_test.go @@ -38,7 +38,7 @@ func TestNftablesManager_AddNatRule(t *testing.T) { // need fw manager to init both acl mgr and router for all chains to be present manager, err := Create(ifaceMock) t.Cleanup(func() { - require.NoError(t, manager.Reset(nil)) + require.NoError(t, manager.Close(nil)) }) require.NoError(t, err) require.NoError(t, manager.Init(nil)) @@ -127,7 +127,7 @@ func TestNftablesManager_RemoveNatRule(t *testing.T) { t.Run(testCase.Name, func(t *testing.T) { manager, err := Create(ifaceMock) t.Cleanup(func() { - require.NoError(t, manager.Reset(nil)) + require.NoError(t, manager.Close(nil)) }) require.NoError(t, err) require.NoError(t, manager.Init(nil)) diff --git a/client/firewall/nftables/state_linux.go b/client/firewall/nftables/state_linux.go index a68c8b8b8..facca1cec 100644 --- a/client/firewall/nftables/state_linux.go +++ b/client/firewall/nftables/state_linux.go @@ -39,7 +39,7 @@ func (s *ShutdownState) Cleanup() error { return fmt.Errorf("create nftables manager: %w", err) } - if err := nft.Reset(nil); err != nil { + if err := nft.Close(nil); err != nil { return fmt.Errorf("reset nftables manager: %w", err) } diff --git a/client/firewall/uspfilter/uspfilter_bench_test.go b/client/firewall/uspfilter/uspfilter_bench_test.go index b43ac2b16..beb5b9336 100644 --- a/client/firewall/uspfilter/uspfilter_bench_test.go +++ b/client/firewall/uspfilter/uspfilter_bench_test.go @@ -171,7 +171,7 @@ func BenchmarkCoreFiltering(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false, flowLogger) defer b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.wgNetwork = &net.IPNet{ @@ -216,7 +216,7 @@ func BenchmarkStateScaling(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false, flowLogger) b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.wgNetwork = &net.IPNet{ @@ -264,7 +264,7 @@ func BenchmarkEstablishmentOverhead(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false, flowLogger) b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.wgNetwork = &net.IPNet{ @@ -463,7 +463,7 @@ func BenchmarkRoutedNetworkReturn(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false, flowLogger) b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) // Setup scenario @@ -590,7 +590,7 @@ func BenchmarkLongLivedConnections(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false, flowLogger) defer b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.SetNetwork(&net.IPNet{ @@ -678,7 +678,7 @@ func BenchmarkShortLivedConnections(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false, flowLogger) defer b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.SetNetwork(&net.IPNet{ @@ -794,7 +794,7 @@ func BenchmarkParallelLongLivedConnections(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false, flowLogger) defer b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.SetNetwork(&net.IPNet{ @@ -879,7 +879,7 @@ func BenchmarkParallelShortLivedConnections(b *testing.B) { SetFilterFunc: func(device.PacketFilter) error { return nil }, }, false, flowLogger) defer b.Cleanup(func() { - require.NoError(b, manager.Reset(nil)) + require.NoError(b, manager.Close(nil)) }) manager.SetNetwork(&net.IPNet{ diff --git a/client/firewall/uspfilter/uspfilter_filter_test.go b/client/firewall/uspfilter/uspfilter_filter_test.go index 3a97506f1..c6902dfea 100644 --- a/client/firewall/uspfilter/uspfilter_filter_test.go +++ b/client/firewall/uspfilter/uspfilter_filter_test.go @@ -39,7 +39,7 @@ func TestPeerACLFiltering(t *testing.T) { require.NotNil(t, manager) t.Cleanup(func() { - require.NoError(t, manager.Reset(nil)) + require.NoError(t, manager.Close(nil)) }) manager.wgNetwork = wgNet @@ -310,7 +310,7 @@ func setupRoutedManager(tb testing.TB, network string) *Manager { require.False(tb, manager.nativeRouter.Load()) tb.Cleanup(func() { - require.NoError(tb, manager.Reset(nil)) + require.NoError(tb, manager.Close(nil)) }) return manager diff --git a/client/iface/bind/ice_bind.go b/client/iface/bind/ice_bind.go index 41f415af7..6897f04a1 100644 --- a/client/iface/bind/ice_bind.go +++ b/client/iface/bind/ice_bind.go @@ -5,7 +5,6 @@ import ( "net" "net/netip" "runtime" - "strings" "sync" "github.com/pion/stun/v2" @@ -108,35 +107,17 @@ func (s *ICEBind) GetICEMux() (*UniversalUDPMuxDefault, error) { return s.udpMux, nil } -func (b *ICEBind) SetEndpoint(peerAddress *net.UDPAddr, conn net.Conn) (*net.UDPAddr, error) { - fakeUDPAddr, err := fakeAddress(peerAddress) - if err != nil { - return nil, err - } - - // force IPv4 - fakeAddr, ok := netip.AddrFromSlice(fakeUDPAddr.IP.To4()) - if !ok { - return nil, fmt.Errorf("failed to convert IP to netip.Addr") - } - +func (b *ICEBind) SetEndpoint(fakeIP netip.Addr, conn net.Conn) { b.endpointsMu.Lock() - b.endpoints[fakeAddr] = conn + b.endpoints[fakeIP] = conn b.endpointsMu.Unlock() - - return fakeUDPAddr, nil } -func (b *ICEBind) RemoveEndpoint(fakeUDPAddr *net.UDPAddr) { - fakeAddr, ok := netip.AddrFromSlice(fakeUDPAddr.IP.To4()) - if !ok { - log.Warnf("failed to convert IP to netip.Addr") - return - } - +func (b *ICEBind) RemoveEndpoint(fakeIP netip.Addr) { b.endpointsMu.Lock() defer b.endpointsMu.Unlock() - delete(b.endpoints, fakeAddr) + + delete(b.endpoints, fakeIP) } func (b *ICEBind) Send(bufs [][]byte, ep wgConn.Endpoint) error { @@ -275,21 +256,6 @@ func (c *ICEBind) receiveRelayed(buffs [][]byte, sizes []int, eps []wgConn.Endpo } } -// fakeAddress returns a fake address that is used to as an identifier for the peer. -// The fake address is in the format of 127.1.x.x where x.x is the last two octets of the peer address. -func fakeAddress(peerAddress *net.UDPAddr) (*net.UDPAddr, error) { - octets := strings.Split(peerAddress.IP.String(), ".") - if len(octets) != 4 { - return nil, fmt.Errorf("invalid IP format") - } - - newAddr := &net.UDPAddr{ - IP: net.ParseIP(fmt.Sprintf("127.1.%s.%s", octets[2], octets[3])), - Port: peerAddress.Port, - } - return newAddr, nil -} - func getMessages(msgsPool *sync.Pool) *[]ipv6.Message { return msgsPool.Get().(*[]ipv6.Message) } diff --git a/client/iface/netstack/tun.go b/client/iface/netstack/tun.go index 01f19875e..a271a1954 100644 --- a/client/iface/netstack/tun.go +++ b/client/iface/netstack/tun.go @@ -55,7 +55,7 @@ func (t *NetStackTun) Create() (tun.Device, *netstack.Net, error) { skipProxy, err := strconv.ParseBool(os.Getenv(EnvSkipProxy)) if err != nil { - log.Errorf("failed to parse NB_ETSTACK_SKIP_PROXY: %s", err) + log.Errorf("failed to parse %s: %s", EnvSkipProxy, err) } if skipProxy { return nsTunDev, tunNet, nil diff --git a/client/iface/wgproxy/bind/proxy.go b/client/iface/wgproxy/bind/proxy.go index 8a2e65382..614787e17 100644 --- a/client/iface/wgproxy/bind/proxy.go +++ b/client/iface/wgproxy/bind/proxy.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "net/netip" + "strings" "sync" log "github.com/sirupsen/logrus" @@ -16,13 +17,13 @@ import ( type ProxyBind struct { Bind *bind.ICEBind - wgAddr *net.UDPAddr - wgEndpoint *bind.Endpoint - remoteConn net.Conn - ctx context.Context - cancel context.CancelFunc - closeMu sync.Mutex - closed bool + fakeNetIP *netip.AddrPort + wgBindEndpoint *bind.Endpoint + remoteConn net.Conn + ctx context.Context + cancel context.CancelFunc + closeMu sync.Mutex + closed bool pausedMu sync.Mutex paused bool @@ -33,20 +34,24 @@ type ProxyBind struct { // endpoint is the NetBird address of the remote peer. The SetEndpoint return with the address what will be used in the // WireGuard configuration. func (p *ProxyBind) AddTurnConn(ctx context.Context, nbAddr *net.UDPAddr, remoteConn net.Conn) error { - addr, err := p.Bind.SetEndpoint(nbAddr, remoteConn) + fakeNetIP, err := fakeAddress(nbAddr) if err != nil { return err } - p.wgAddr = addr - p.wgEndpoint = addrToEndpoint(addr) + p.fakeNetIP = fakeNetIP + p.wgBindEndpoint = &bind.Endpoint{AddrPort: *fakeNetIP} p.remoteConn = remoteConn p.ctx, p.cancel = context.WithCancel(ctx) - return err + return nil } func (p *ProxyBind) EndpointAddr() *net.UDPAddr { - return p.wgAddr + return &net.UDPAddr{ + IP: p.fakeNetIP.Addr().AsSlice(), + Port: int(p.fakeNetIP.Port()), + Zone: p.fakeNetIP.Addr().Zone(), + } } func (p *ProxyBind) Work() { @@ -54,6 +59,8 @@ func (p *ProxyBind) Work() { return } + p.Bind.SetEndpoint(p.fakeNetIP.Addr(), p.remoteConn) + p.pausedMu.Lock() p.paused = false p.pausedMu.Unlock() @@ -93,7 +100,7 @@ func (p *ProxyBind) close() error { p.cancel() - p.Bind.RemoveEndpoint(p.wgAddr) + p.Bind.RemoveEndpoint(p.fakeNetIP.Addr()) if rErr := p.remoteConn.Close(); rErr != nil && !errors.Is(rErr, net.ErrClosed) { return rErr @@ -126,7 +133,7 @@ func (p *ProxyBind) proxyToLocal(ctx context.Context) { } msg := bind.RecvMessage{ - Endpoint: p.wgEndpoint, + Endpoint: p.wgBindEndpoint, Buffer: buf[:n], } p.Bind.RecvChan <- msg @@ -134,8 +141,19 @@ func (p *ProxyBind) proxyToLocal(ctx context.Context) { } } -func addrToEndpoint(addr *net.UDPAddr) *bind.Endpoint { - ip, _ := netip.AddrFromSlice(addr.IP.To4()) - addrPort := netip.AddrPortFrom(ip, uint16(addr.Port)) - return &bind.Endpoint{AddrPort: addrPort} +// fakeAddress returns a fake address that is used to as an identifier for the peer. +// The fake address is in the format of 127.1.x.x where x.x is the last two octets of the peer address. +func fakeAddress(peerAddress *net.UDPAddr) (*netip.AddrPort, error) { + octets := strings.Split(peerAddress.IP.String(), ".") + if len(octets) != 4 { + return nil, fmt.Errorf("invalid IP format") + } + + fakeIP, err := netip.ParseAddr(fmt.Sprintf("127.1.%s.%s", octets[2], octets[3])) + if err != nil { + return nil, fmt.Errorf("failed to parse new IP: %w", err) + } + + netipAddr := netip.AddrPortFrom(fakeIP, uint16(peerAddress.Port)) + return &netipAddr, nil } diff --git a/client/installer.nsis b/client/installer.nsis index af942a868..743c81a6d 100644 --- a/client/installer.nsis +++ b/client/installer.nsis @@ -6,8 +6,8 @@ !define DESCRIPTION "A WireGuard®-based mesh network that connects your devices into a single private network" !define INSTALLER_NAME "netbird-installer.exe" !define MAIN_APP_EXE "Netbird" -!define ICON "ui\\netbird.ico" -!define BANNER "ui\\banner.bmp" +!define ICON "ui\\assets\\netbird.ico" +!define BANNER "ui\\build\\banner.bmp" !define LICENSE_DATA "..\\LICENSE" !define INSTALL_DIR "$PROGRAMFILES64\${APP_NAME}" diff --git a/client/internal/acl/manager_test.go b/client/internal/acl/manager_test.go index 82a136e9c..9e1659455 100644 --- a/client/internal/acl/manager_test.go +++ b/client/internal/acl/manager_test.go @@ -62,7 +62,7 @@ func TestDefaultManager(t *testing.T) { return } defer func(fw manager.Manager) { - _ = fw.Reset(nil) + _ = fw.Close(nil) }(fw) acl := NewDefaultManager(fw) @@ -356,7 +356,7 @@ func TestDefaultManagerEnableSSHRules(t *testing.T) { return } defer func(fw manager.Manager) { - _ = fw.Reset(nil) + _ = fw.Close(nil) }(fw) acl := NewDefaultManager(fw) diff --git a/client/internal/dns/server_test.go b/client/internal/dns/server_test.go index 80db2561b..d60edfa55 100644 --- a/client/internal/dns/server_test.go +++ b/client/internal/dns/server_test.go @@ -1018,7 +1018,7 @@ func TestHandlerChain_DomainPriorities(t *testing.T) { mh.AssertExpectations(t) } - // Reset mocks + // Close mocks if mh, ok := tc.expectedHandler.(*MockHandler); ok { mh.ExpectedCalls = nil mh.Calls = nil diff --git a/client/internal/peer/conn.go b/client/internal/peer/conn.go index 9b4d1a554..b91cfe33c 100644 --- a/client/internal/peer/conn.go +++ b/client/internal/peer/conn.go @@ -442,8 +442,8 @@ func (conn *Conn) onRelayConnectionIsReady(rci RelayConnInfo) { conn.log.Infof("created new wgProxy for relay connection: %s", wgProxy.EndpointAddr().String()) - if conn.iceP2PIsActive() { - conn.log.Debugf("do not switch to relay because current priority is: %s", conn.currentConnPriority.String()) + if conn.isICEActive() { + conn.log.Infof("do not switch to relay because current priority is: %s", conn.currentConnPriority.String()) conn.setRelayedProxy(wgProxy) conn.statusRelay.Set(StatusConnected) conn.updateRelayStatus(rci.relayedConn.RemoteAddr().String(), rci.rosenpassPubKey) @@ -711,8 +711,8 @@ func (conn *Conn) isReadyToUpgrade() bool { return conn.wgProxyRelay != nil && conn.currentConnPriority != connPriorityRelay } -func (conn *Conn) iceP2PIsActive() bool { - return conn.currentConnPriority == connPriorityICEP2P && conn.statusICE.Get() == StatusConnected +func (conn *Conn) isICEActive() bool { + return (conn.currentConnPriority == connPriorityICEP2P || conn.currentConnPriority == connPriorityICETurn) && conn.statusICE.Get() == StatusConnected } func (conn *Conn) removeWgPeer() error { diff --git a/client/internal/routemanager/dnsinterceptor/handler.go b/client/internal/routemanager/dnsinterceptor/handler.go index f36285cc4..da1056e2d 100644 --- a/client/internal/routemanager/dnsinterceptor/handler.go +++ b/client/internal/routemanager/dnsinterceptor/handler.go @@ -160,6 +160,12 @@ func (d *DnsInterceptor) ServeDNS(w dns.ResponseWriter, r *dns.Msg) { return } + // set the AuthenticatedData flag and the EDNS0 buffer size to 4096 bytes to support larger dns records + if r.Extra == nil { + r.SetEdns0(4096, false) + r.MsgHdr.AuthenticatedData = true + } + client := &dns.Client{ Timeout: 5 * time.Second, Net: "udp", diff --git a/client/netbird.wxs b/client/netbird.wxs index ee9ab667f..5e03a014d 100644 --- a/client/netbird.wxs +++ b/client/netbird.wxs @@ -71,7 +71,7 @@ - + diff --git a/client/resources.rc b/client/resources.rc index ac411245e..696fd0dfa 100644 --- a/client/resources.rc +++ b/client/resources.rc @@ -5,5 +5,5 @@ #define STRINGIZE(x) #x #define EXPAND(x) STRINGIZE(x) CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST manifest.xml -7 ICON ui/netbird.ico +7 ICON ui/assets/netbird.ico wintun.dll RCDATA wintun.dll diff --git a/client/ui/netbird-systemtray-connected-dark.ico b/client/ui/assets/netbird-systemtray-connected-dark.ico similarity index 100% rename from client/ui/netbird-systemtray-connected-dark.ico rename to client/ui/assets/netbird-systemtray-connected-dark.ico diff --git a/client/ui/netbird-systemtray-connected-dark.png b/client/ui/assets/netbird-systemtray-connected-dark.png similarity index 100% rename from client/ui/netbird-systemtray-connected-dark.png rename to client/ui/assets/netbird-systemtray-connected-dark.png diff --git a/client/ui/netbird-systemtray-connected-macos.png b/client/ui/assets/netbird-systemtray-connected-macos.png similarity index 100% rename from client/ui/netbird-systemtray-connected-macos.png rename to client/ui/assets/netbird-systemtray-connected-macos.png diff --git a/client/ui/netbird-systemtray-connected.ico b/client/ui/assets/netbird-systemtray-connected.ico similarity index 100% rename from client/ui/netbird-systemtray-connected.ico rename to client/ui/assets/netbird-systemtray-connected.ico diff --git a/client/ui/netbird-systemtray-connected.png b/client/ui/assets/netbird-systemtray-connected.png similarity index 100% rename from client/ui/netbird-systemtray-connected.png rename to client/ui/assets/netbird-systemtray-connected.png diff --git a/client/ui/netbird-systemtray-connecting-dark.ico b/client/ui/assets/netbird-systemtray-connecting-dark.ico similarity index 100% rename from client/ui/netbird-systemtray-connecting-dark.ico rename to client/ui/assets/netbird-systemtray-connecting-dark.ico diff --git a/client/ui/netbird-systemtray-connecting-dark.png b/client/ui/assets/netbird-systemtray-connecting-dark.png similarity index 100% rename from client/ui/netbird-systemtray-connecting-dark.png rename to client/ui/assets/netbird-systemtray-connecting-dark.png diff --git a/client/ui/netbird-systemtray-connecting-macos.png b/client/ui/assets/netbird-systemtray-connecting-macos.png similarity index 100% rename from client/ui/netbird-systemtray-connecting-macos.png rename to client/ui/assets/netbird-systemtray-connecting-macos.png diff --git a/client/ui/netbird-systemtray-connecting.ico b/client/ui/assets/netbird-systemtray-connecting.ico similarity index 100% rename from client/ui/netbird-systemtray-connecting.ico rename to client/ui/assets/netbird-systemtray-connecting.ico diff --git a/client/ui/netbird-systemtray-connecting.png b/client/ui/assets/netbird-systemtray-connecting.png similarity index 100% rename from client/ui/netbird-systemtray-connecting.png rename to client/ui/assets/netbird-systemtray-connecting.png diff --git a/client/ui/netbird-systemtray-disconnected-macos.png b/client/ui/assets/netbird-systemtray-disconnected-macos.png similarity index 100% rename from client/ui/netbird-systemtray-disconnected-macos.png rename to client/ui/assets/netbird-systemtray-disconnected-macos.png diff --git a/client/ui/netbird-systemtray-disconnected.ico b/client/ui/assets/netbird-systemtray-disconnected.ico similarity index 100% rename from client/ui/netbird-systemtray-disconnected.ico rename to client/ui/assets/netbird-systemtray-disconnected.ico diff --git a/client/ui/netbird-systemtray-disconnected.png b/client/ui/assets/netbird-systemtray-disconnected.png similarity index 100% rename from client/ui/netbird-systemtray-disconnected.png rename to client/ui/assets/netbird-systemtray-disconnected.png diff --git a/client/ui/netbird-systemtray-error-dark.ico b/client/ui/assets/netbird-systemtray-error-dark.ico similarity index 100% rename from client/ui/netbird-systemtray-error-dark.ico rename to client/ui/assets/netbird-systemtray-error-dark.ico diff --git a/client/ui/netbird-systemtray-error-dark.png b/client/ui/assets/netbird-systemtray-error-dark.png similarity index 100% rename from client/ui/netbird-systemtray-error-dark.png rename to client/ui/assets/netbird-systemtray-error-dark.png diff --git a/client/ui/netbird-systemtray-error-macos.png b/client/ui/assets/netbird-systemtray-error-macos.png similarity index 100% rename from client/ui/netbird-systemtray-error-macos.png rename to client/ui/assets/netbird-systemtray-error-macos.png diff --git a/client/ui/netbird-systemtray-error.ico b/client/ui/assets/netbird-systemtray-error.ico similarity index 100% rename from client/ui/netbird-systemtray-error.ico rename to client/ui/assets/netbird-systemtray-error.ico diff --git a/client/ui/netbird-systemtray-error.png b/client/ui/assets/netbird-systemtray-error.png similarity index 100% rename from client/ui/netbird-systemtray-error.png rename to client/ui/assets/netbird-systemtray-error.png diff --git a/client/ui/netbird-systemtray-update-connected-dark.ico b/client/ui/assets/netbird-systemtray-update-connected-dark.ico similarity index 100% rename from client/ui/netbird-systemtray-update-connected-dark.ico rename to client/ui/assets/netbird-systemtray-update-connected-dark.ico diff --git a/client/ui/netbird-systemtray-update-connected-dark.png b/client/ui/assets/netbird-systemtray-update-connected-dark.png similarity index 100% rename from client/ui/netbird-systemtray-update-connected-dark.png rename to client/ui/assets/netbird-systemtray-update-connected-dark.png diff --git a/client/ui/netbird-systemtray-update-connected-macos.png b/client/ui/assets/netbird-systemtray-update-connected-macos.png similarity index 100% rename from client/ui/netbird-systemtray-update-connected-macos.png rename to client/ui/assets/netbird-systemtray-update-connected-macos.png diff --git a/client/ui/netbird-systemtray-update-connected.ico b/client/ui/assets/netbird-systemtray-update-connected.ico similarity index 100% rename from client/ui/netbird-systemtray-update-connected.ico rename to client/ui/assets/netbird-systemtray-update-connected.ico diff --git a/client/ui/netbird-systemtray-update-connected.png b/client/ui/assets/netbird-systemtray-update-connected.png similarity index 100% rename from client/ui/netbird-systemtray-update-connected.png rename to client/ui/assets/netbird-systemtray-update-connected.png diff --git a/client/ui/netbird-systemtray-update-disconnected-dark.ico b/client/ui/assets/netbird-systemtray-update-disconnected-dark.ico similarity index 100% rename from client/ui/netbird-systemtray-update-disconnected-dark.ico rename to client/ui/assets/netbird-systemtray-update-disconnected-dark.ico diff --git a/client/ui/netbird-systemtray-update-disconnected-dark.png b/client/ui/assets/netbird-systemtray-update-disconnected-dark.png similarity index 100% rename from client/ui/netbird-systemtray-update-disconnected-dark.png rename to client/ui/assets/netbird-systemtray-update-disconnected-dark.png diff --git a/client/ui/netbird-systemtray-update-disconnected-macos.png b/client/ui/assets/netbird-systemtray-update-disconnected-macos.png similarity index 100% rename from client/ui/netbird-systemtray-update-disconnected-macos.png rename to client/ui/assets/netbird-systemtray-update-disconnected-macos.png diff --git a/client/ui/netbird-systemtray-update-disconnected.ico b/client/ui/assets/netbird-systemtray-update-disconnected.ico similarity index 100% rename from client/ui/netbird-systemtray-update-disconnected.ico rename to client/ui/assets/netbird-systemtray-update-disconnected.ico diff --git a/client/ui/netbird-systemtray-update-disconnected.png b/client/ui/assets/netbird-systemtray-update-disconnected.png similarity index 100% rename from client/ui/netbird-systemtray-update-disconnected.png rename to client/ui/assets/netbird-systemtray-update-disconnected.png diff --git a/client/ui/netbird.ico b/client/ui/assets/netbird.ico similarity index 100% rename from client/ui/netbird.ico rename to client/ui/assets/netbird.ico diff --git a/client/ui/netbird.png b/client/ui/assets/netbird.png similarity index 100% rename from client/ui/netbird.png rename to client/ui/assets/netbird.png diff --git a/client/ui/banner.bmp b/client/ui/build/banner.bmp similarity index 100% rename from client/ui/banner.bmp rename to client/ui/build/banner.bmp diff --git a/client/ui/build-ui-linux.sh b/client/ui/build/build-ui-linux.sh similarity index 100% rename from client/ui/build-ui-linux.sh rename to client/ui/build/build-ui-linux.sh diff --git a/client/ui/netbird.desktop b/client/ui/build/netbird.desktop similarity index 100% rename from client/ui/netbird.desktop rename to client/ui/build/netbird.desktop diff --git a/client/ui/client_ui.go b/client/ui/client_ui.go index 51eec59a5..914d4f3b9 100644 --- a/client/ui/client_ui.go +++ b/client/ui/client_ui.go @@ -35,7 +35,9 @@ import ( "github.com/netbirdio/netbird/client/proto" "github.com/netbirdio/netbird/client/ui/desktop" "github.com/netbirdio/netbird/client/ui/event" + "github.com/netbirdio/netbird/client/ui/process" "github.com/netbirdio/netbird/util" + "github.com/netbirdio/netbird/version" ) @@ -44,94 +46,125 @@ const ( failFastTimeout = time.Second ) +const ( + censoredPreSharedKey = "**********" +) + func main() { - var daemonAddr string - - defaultDaemonAddr := "unix:///var/run/netbird.sock" - if runtime.GOOS == "windows" { - defaultDaemonAddr = "tcp://127.0.0.1:41731" - } - - flag.StringVar( - &daemonAddr, "daemon-addr", - defaultDaemonAddr, - "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]") - - var showSettings bool - flag.BoolVar(&showSettings, "settings", false, "run settings windows") - var showRoutes bool - flag.BoolVar(&showRoutes, "networks", false, "run networks windows") - var errorMSG string - flag.StringVar(&errorMSG, "error-msg", "", "displays a error message window") - - tmpDir := "/tmp" - if runtime.GOOS == "windows" { - tmpDir = os.TempDir() - } - - var saveLogsInFile bool - flag.BoolVar(&saveLogsInFile, "use-log-file", false, fmt.Sprintf("save logs in a file: %s/netbird-ui-PID.log", tmpDir)) - - flag.Parse() + daemonAddr, showSettings, showNetworks, errorMsg, saveLogsInFile := parseFlags() + // Initialize file logging if needed. if saveLogsInFile { - logFile := path.Join(tmpDir, fmt.Sprintf("netbird-ui-%d.log", os.Getpid())) - err := util.InitLog("trace", logFile) - if err != nil { + if err := initLogFile(); err != nil { log.Errorf("error while initializing log: %v", err) return } } + // Create the Fyne application. a := app.NewWithID("NetBird") a.SetIcon(fyne.NewStaticResource("netbird", iconDisconnected)) - if errorMSG != "" { - showErrorMSG(errorMSG) + // Show error message window if needed. + if errorMsg != "" { + showErrorMessage(errorMsg) return } - client := newServiceClient(daemonAddr, a, showSettings, showRoutes) + // Create the service client (this also builds the settings or networks UI if requested). + client := newServiceClient(daemonAddr, a, showSettings, showNetworks) + + // Watch for theme/settings changes to update the icon. + go watchSettingsChanges(a, client) + + // Run in window mode if any UI flag was set. + if showSettings || showNetworks { + a.Run() + return + } + + // Check for another running process. + running, err := process.IsAnotherProcessRunning() + if err != nil { + log.Errorf("error while checking process: %v", err) + return + } + if running { + log.Warn("another process is running") + return + } + + client.setDefaultFonts() + systray.Run(client.onTrayReady, client.onTrayExit) +} + +// parseFlags reads and returns all needed command-line flags. +func parseFlags() (daemonAddr string, showSettings, showNetworks bool, errorMsg string, saveLogsInFile bool) { + defaultDaemonAddr := "unix:///var/run/netbird.sock" + if runtime.GOOS == "windows" { + defaultDaemonAddr = "tcp://127.0.0.1:41731" + } + flag.StringVar(&daemonAddr, "daemon-addr", defaultDaemonAddr, "Daemon service address to serve CLI requests [unix|tcp]://[path|host:port]") + flag.BoolVar(&showSettings, "settings", false, "run settings window") + flag.BoolVar(&showNetworks, "networks", false, "run networks window") + flag.StringVar(&errorMsg, "error-msg", "", "displays an error message window") + + tmpDir := "/tmp" + if runtime.GOOS == "windows" { + tmpDir = os.TempDir() + } + flag.BoolVar(&saveLogsInFile, "use-log-file", false, fmt.Sprintf("save logs in a file: %s/netbird-ui-PID.log", tmpDir)) + flag.Parse() + return +} + +// initLogFile initializes logging into a file. +func initLogFile() error { + tmpDir := "/tmp" + if runtime.GOOS == "windows" { + tmpDir = os.TempDir() + } + logFile := path.Join(tmpDir, fmt.Sprintf("netbird-ui-%d.log", os.Getpid())) + return util.InitLog("trace", logFile) +} + +// watchSettingsChanges listens for Fyne theme/settings changes and updates the client icon. +func watchSettingsChanges(a fyne.App, client *serviceClient) { settingsChangeChan := make(chan fyne.Settings) a.Settings().AddChangeListener(settingsChangeChan) - go func() { - for range settingsChangeChan { - client.updateIcon() - } - }() - - if showSettings || showRoutes { - a.Run() - } else { - running, err := isAnotherProcessRunning() - if err != nil { - log.Errorf("error while checking process: %v", err) - } - if running { - log.Warn("another process is running") - return - } - client.setDefaultFonts() - systray.Run(client.onTrayReady, client.onTrayExit) + for range settingsChangeChan { + client.updateIcon() } } -//go:embed netbird-systemtray-connected-macos.png +// showErrorMessage displays an error message in a simple window. +func showErrorMessage(msg string) { + a := app.New() + w := a.NewWindow("NetBird Error") + label := widget.NewLabel(msg) + label.Wrapping = fyne.TextWrapWord + w.SetContent(label) + w.Resize(fyne.NewSize(400, 100)) + w.Show() + a.Run() +} + +//go:embed assets/netbird-systemtray-connected-macos.png var iconConnectedMacOS []byte -//go:embed netbird-systemtray-disconnected-macos.png +//go:embed assets/netbird-systemtray-disconnected-macos.png var iconDisconnectedMacOS []byte -//go:embed netbird-systemtray-update-disconnected-macos.png +//go:embed assets/netbird-systemtray-update-disconnected-macos.png var iconUpdateDisconnectedMacOS []byte -//go:embed netbird-systemtray-update-connected-macos.png +//go:embed assets/netbird-systemtray-update-connected-macos.png var iconUpdateConnectedMacOS []byte -//go:embed netbird-systemtray-connecting-macos.png +//go:embed assets/netbird-systemtray-connecting-macos.png var iconConnectingMacOS []byte -//go:embed netbird-systemtray-error-macos.png +//go:embed assets/netbird-systemtray-error-macos.png var iconErrorMacOS []byte type serviceClient struct { @@ -154,6 +187,7 @@ type serviceClient struct { mAdminPanel *systray.MenuItem mSettings *systray.MenuItem mAbout *systray.MenuItem + mGitHub *systray.MenuItem mVersionUI *systray.MenuItem mVersionDaemon *systray.MenuItem mUpdate *systray.MenuItem @@ -300,18 +334,6 @@ func (s *serviceClient) showSettingsUI() { s.wSettings.Show() } -// showErrorMSG opens a fyne app window to display the supplied message -func showErrorMSG(msg string) { - app := app.New() - w := app.NewWindow("NetBird Error") - content := widget.NewLabel(msg) - content.Wrapping = fyne.TextWrapWord - w.SetContent(content) - w.Resize(fyne.NewSize(400, 100)) - w.Show() - app.Run() -} - // getSettingsForm to embed it into settings window. func (s *serviceClient) getSettingsForm() *widget.Form { return &widget.Form{ @@ -327,7 +349,7 @@ func (s *serviceClient) getSettingsForm() *widget.Form { }, SubmitText: "Save", OnSubmit: func() { - if s.iPreSharedKey.Text != "" && s.iPreSharedKey.Text != "**********" { + if s.iPreSharedKey.Text != "" && s.iPreSharedKey.Text != censoredPreSharedKey { // validate preSharedKey if it added if _, err := wgtypes.ParseKey(s.iPreSharedKey.Text); err != nil { dialog.ShowError(fmt.Errorf("Invalid Pre-shared Key Value"), s.wSettings) @@ -365,7 +387,7 @@ func (s *serviceClient) getSettingsForm() *widget.Form { WireguardPort: &port, } - if s.iPreSharedKey.Text != "**********" { + if s.iPreSharedKey.Text != censoredPreSharedKey { loginRequest.OptionalPreSharedKey = &s.iPreSharedKey.Text } @@ -587,26 +609,29 @@ func (s *serviceClient) onTrayReady() { s.mAdminPanel = systray.AddMenuItem("Admin Panel", "Netbird Admin Panel") systray.AddSeparator() - s.mSettings = systray.AddMenuItem("Settings", "Settings of the application") - s.mAllowSSH = s.mSettings.AddSubMenuItemCheckbox("Allow SSH", "Allow SSH connections", false) - s.mAutoConnect = s.mSettings.AddSubMenuItemCheckbox("Connect on Startup", "Connect automatically when the service starts", false) - s.mEnableRosenpass = s.mSettings.AddSubMenuItemCheckbox("Enable Quantum-Resistance", "Enable post-quantum security via Rosenpass", false) - s.mNotifications = s.mSettings.AddSubMenuItemCheckbox("Notifications", "Enable notifications", false) - s.mAdvancedSettings = s.mSettings.AddSubMenuItem("Advanced Settings", "Advanced settings of the application") - s.mCreateDebugBundle = s.mSettings.AddSubMenuItem("Create Debug Bundle", "Create and open debug information bundle") + s.mSettings = systray.AddMenuItem("Settings", settingsMenuDescr) + s.mAllowSSH = s.mSettings.AddSubMenuItemCheckbox("Allow SSH", allowSSHMenuDescr, false) + s.mAutoConnect = s.mSettings.AddSubMenuItemCheckbox("Connect on Startup", autoConnectMenuDescr, false) + s.mEnableRosenpass = s.mSettings.AddSubMenuItemCheckbox("Enable Quantum-Resistance", quantumResistanceMenuDescr, false) + s.mNotifications = s.mSettings.AddSubMenuItemCheckbox("Notifications", notificationsMenuDescr, false) + s.mAdvancedSettings = s.mSettings.AddSubMenuItem("Advanced Settings", advancedSettingsMenuDescr) + s.mCreateDebugBundle = s.mSettings.AddSubMenuItem("Create Debug Bundle", debugBundleMenuDescr) s.loadSettings() s.exitNodeMu.Lock() - s.mExitNode = systray.AddMenuItem("Exit Node", "Select exit node for routing traffic") + s.mExitNode = systray.AddMenuItem("Exit Node", exitNodeMenuDescr) s.mExitNode.Disable() s.exitNodeMu.Unlock() - s.mNetworks = systray.AddMenuItem("Networks", "Open the networks management window") + s.mNetworks = systray.AddMenuItem("Networks", networksMenuDescr) s.mNetworks.Disable() systray.AddSeparator() s.mAbout = systray.AddMenuItem("About", "About") s.mAbout.SetIcon(s.icAbout) + + s.mGitHub = s.mAbout.AddSubMenuItem("GitHub", "GitHub") + versionString := normalizedVersion(version.NetbirdVersion()) s.mVersionUI = s.mAbout.AddSubMenuItem(fmt.Sprintf("GUI: %s", versionString), fmt.Sprintf("GUI Version: %s", versionString)) s.mVersionUI.Disable() @@ -615,11 +640,11 @@ func (s *serviceClient) onTrayReady() { s.mVersionDaemon.Disable() s.mVersionDaemon.Hide() - s.mUpdate = s.mAbout.AddSubMenuItem("Download latest version", "Download latest version") + s.mUpdate = s.mAbout.AddSubMenuItem("Download latest version", latestVersionMenuDescr) s.mUpdate.Hide() systray.AddSeparator() - s.mQuit = systray.AddMenuItem("Quit", "Quit the client app") + s.mQuit = systray.AddMenuItem("Quit", quitMenuDescr) // update exit node menu in case service is already connected go s.updateExitNodes() @@ -717,6 +742,11 @@ func (s *serviceClient) onTrayReady() { case <-s.mQuit.ClickedCh: systray.Quit() return + case <-s.mGitHub.ClickedCh: + err := openURL("https://github.com/netbirdio/netbird") + if err != nil { + log.Errorf("%s", err) + } case <-s.mUpdate.ClickedCh: err := openURL(version.DownloadUrl()) if err != nil { diff --git a/client/ui/const.go b/client/ui/const.go new file mode 100644 index 000000000..0253750d1 --- /dev/null +++ b/client/ui/const.go @@ -0,0 +1,15 @@ +package main + +const ( + settingsMenuDescr = "Settings of the application" + allowSSHMenuDescr = "Allow SSH connections" + autoConnectMenuDescr = "Connect automatically when the service starts" + quantumResistanceMenuDescr = "Enable post-quantum security via Rosenpass" + notificationsMenuDescr = "Enable notifications" + advancedSettingsMenuDescr = "Advanced settings of the application" + debugBundleMenuDescr = "Create and open debug information bundle" + exitNodeMenuDescr = "Select exit node for routing traffic" + networksMenuDescr = "Open the networks management window" + latestVersionMenuDescr = "Download latest version" + quitMenuDescr = "Quit the client app" +) diff --git a/client/ui/icons.go b/client/ui/icons.go index 6f3a9dbc9..e88fb9378 100644 --- a/client/ui/icons.go +++ b/client/ui/icons.go @@ -6,38 +6,38 @@ import ( _ "embed" ) -//go:embed netbird.png +//go:embed assets/netbird.png var iconAbout []byte -//go:embed netbird-systemtray-connected.png +//go:embed assets/netbird-systemtray-connected.png var iconConnected []byte -//go:embed netbird-systemtray-connected-dark.png +//go:embed assets/netbird-systemtray-connected-dark.png var iconConnectedDark []byte -//go:embed netbird-systemtray-disconnected.png +//go:embed assets/netbird-systemtray-disconnected.png var iconDisconnected []byte -//go:embed netbird-systemtray-update-disconnected.png +//go:embed assets/netbird-systemtray-update-disconnected.png var iconUpdateDisconnected []byte -//go:embed netbird-systemtray-update-disconnected-dark.png +//go:embed assets/netbird-systemtray-update-disconnected-dark.png var iconUpdateDisconnectedDark []byte -//go:embed netbird-systemtray-update-connected.png +//go:embed assets/netbird-systemtray-update-connected.png var iconUpdateConnected []byte -//go:embed netbird-systemtray-update-connected-dark.png +//go:embed assets/netbird-systemtray-update-connected-dark.png var iconUpdateConnectedDark []byte -//go:embed netbird-systemtray-connecting.png +//go:embed assets/netbird-systemtray-connecting.png var iconConnecting []byte -//go:embed netbird-systemtray-connecting-dark.png +//go:embed assets/netbird-systemtray-connecting-dark.png var iconConnectingDark []byte -//go:embed netbird-systemtray-error.png +//go:embed assets/netbird-systemtray-error.png var iconError []byte -//go:embed netbird-systemtray-error-dark.png +//go:embed assets/netbird-systemtray-error-dark.png var iconErrorDark []byte diff --git a/client/ui/icons_windows.go b/client/ui/icons_windows.go index a2a924763..2107d3852 100644 --- a/client/ui/icons_windows.go +++ b/client/ui/icons_windows.go @@ -1,41 +1,41 @@ package main import ( - _ "embed" + _ "embed" ) -//go:embed netbird.ico +//go:embed assets/netbird.ico var iconAbout []byte -//go:embed netbird-systemtray-connected.ico +//go:embed assets/netbird-systemtray-connected.ico var iconConnected []byte -//go:embed netbird-systemtray-connected-dark.ico +//go:embed assets/netbird-systemtray-connected-dark.ico var iconConnectedDark []byte -//go:embed netbird-systemtray-disconnected.ico +//go:embed assets/netbird-systemtray-disconnected.ico var iconDisconnected []byte -//go:embed netbird-systemtray-update-disconnected.ico +//go:embed assets/netbird-systemtray-update-disconnected.ico var iconUpdateDisconnected []byte -//go:embed netbird-systemtray-update-disconnected-dark.ico +//go:embed assets/netbird-systemtray-update-disconnected-dark.ico var iconUpdateDisconnectedDark []byte -//go:embed netbird-systemtray-update-connected.ico +//go:embed assets/netbird-systemtray-update-connected.ico var iconUpdateConnected []byte -//go:embed netbird-systemtray-update-connected-dark.ico +//go:embed assets/netbird-systemtray-update-connected-dark.ico var iconUpdateConnectedDark []byte -//go:embed netbird-systemtray-connecting.ico +//go:embed assets/netbird-systemtray-connecting.ico var iconConnecting []byte -//go:embed netbird-systemtray-connecting-dark.ico +//go:embed assets/netbird-systemtray-connecting-dark.ico var iconConnectingDark []byte -//go:embed netbird-systemtray-error.ico +//go:embed assets/netbird-systemtray-error.ico var iconError []byte -//go:embed netbird-systemtray-error-dark.ico +//go:embed assets/netbird-systemtray-error-dark.ico var iconErrorDark []byte diff --git a/client/ui/network.go b/client/ui/network.go index 750788cf3..b21554f09 100644 --- a/client/ui/network.go +++ b/client/ui/network.go @@ -363,7 +363,7 @@ func (s *serviceClient) recreateExitNodeMenu(exitNodes []*proto.Network) { if runtime.GOOS == "linux" || runtime.GOOS == "freebsd" { s.mExitNode.Remove() - s.mExitNode = systray.AddMenuItem("Exit Node", "Select exit node for routing traffic") + s.mExitNode = systray.AddMenuItem("Exit Node", exitNodeMenuDescr) } for _, node := range exitNodes { diff --git a/client/ui/process.go b/client/ui/process/process.go similarity index 90% rename from client/ui/process.go rename to client/ui/process/process.go index bcb3dd879..f9a8a4fe9 100644 --- a/client/ui/process.go +++ b/client/ui/process/process.go @@ -1,4 +1,4 @@ -package main +package process import ( "os" @@ -8,7 +8,7 @@ import ( "github.com/shirou/gopsutil/v3/process" ) -func isAnotherProcessRunning() (bool, error) { +func IsAnotherProcessRunning() (bool, error) { processes, err := process.Processes() if err != nil { return false, err diff --git a/client/ui/process_nonwindows.go b/client/ui/process/process_nonwindows.go similarity index 96% rename from client/ui/process_nonwindows.go rename to client/ui/process/process_nonwindows.go index 0d17be2be..cf9f6443d 100644 --- a/client/ui/process_nonwindows.go +++ b/client/ui/process/process_nonwindows.go @@ -1,6 +1,6 @@ //go:build !windows -package main +package process import ( "os" diff --git a/client/ui/process_windows.go b/client/ui/process/process_windows.go similarity index 96% rename from client/ui/process_windows.go rename to client/ui/process/process_windows.go index b15b0ed24..2d211d1a4 100644 --- a/client/ui/process_windows.go +++ b/client/ui/process/process_windows.go @@ -1,4 +1,4 @@ -package main +package process import ( "os/user" diff --git a/formatter/formatter.go b/formatter/formatter.go deleted file mode 100644 index 74de38603..000000000 --- a/formatter/formatter.go +++ /dev/null @@ -1,83 +0,0 @@ -package formatter - -import ( - "fmt" - "strings" - "time" - - "github.com/sirupsen/logrus" -) - -// TextFormatter formats logs into text with included source code's path -type TextFormatter struct { - timestampFormat string - levelDesc []string -} - -// SyslogFormatter formats logs into text -type SyslogFormatter struct { - levelDesc []string -} - -var validLevelDesc = []string{"PANC", "FATL", "ERRO", "WARN", "INFO", "DEBG", "TRAC"} - - -// NewTextFormatter create new MyTextFormatter instance -func NewTextFormatter() *TextFormatter { - return &TextFormatter{ - levelDesc: validLevelDesc, - timestampFormat: time.RFC3339, // or RFC3339 - } -} - -// NewSyslogFormatter create new MySyslogFormatter instance -func NewSyslogFormatter() *SyslogFormatter { - return &SyslogFormatter{ - levelDesc: validLevelDesc, - } -} - -// Format renders a single log entry -func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) { - var fields string - keys := make([]string, 0, len(entry.Data)) - for k, v := range entry.Data { - if k == "source" { - continue - } - keys = append(keys, fmt.Sprintf("%s: %v", k, v)) - } - - if len(keys) > 0 { - fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) - } - - level := f.parseLevel(entry.Level) - - return []byte(fmt.Sprintf("%s %s %s%s: %s\n", entry.Time.Format(f.timestampFormat), level, fields, entry.Data["source"], entry.Message)), nil -} - -func (f *TextFormatter) parseLevel(level logrus.Level) string { - if len(f.levelDesc) < int(level) { - return "" - } - - return f.levelDesc[level] -} - -// Format renders a single log entry -func (f *SyslogFormatter) Format(entry *logrus.Entry) ([]byte, error) { - var fields string - keys := make([]string, 0, len(entry.Data)) - for k, v := range entry.Data { - if k == "source" { - continue - } - keys = append(keys, fmt.Sprintf("%s: %v", k, v)) - } - - if len(keys) > 0 { - fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) - } - return []byte(fmt.Sprintf("%s%s\n", fields, entry.Message)), nil -} diff --git a/formatter/hook/additional_empty.go b/formatter/hook/additional_empty.go new file mode 100644 index 000000000..4f5069482 --- /dev/null +++ b/formatter/hook/additional_empty.go @@ -0,0 +1,9 @@ +//go:build !loggoroutine + +package hook + +import log "github.com/sirupsen/logrus" + +func additionalEntries(_ *log.Entry) { + // This function is empty and is used to demonstrate the use of additional hooks. +} diff --git a/formatter/hook/additional_goroutine.go b/formatter/hook/additional_goroutine.go new file mode 100644 index 000000000..fb4e09f47 --- /dev/null +++ b/formatter/hook/additional_goroutine.go @@ -0,0 +1,12 @@ +//go:build loggoroutine + +package hook + +import ( + "github.com/petermattis/goid" + log "github.com/sirupsen/logrus" +) + +func additionalEntries(entry *log.Entry) { + entry.Data[EntryKeyGoroutineID] = goid.Get() +} diff --git a/formatter/hook.go b/formatter/hook/hook.go similarity index 96% rename from formatter/hook.go rename to formatter/hook/hook.go index 12f27e67d..1b6ceccc9 100644 --- a/formatter/hook.go +++ b/formatter/hook/hook.go @@ -1,4 +1,4 @@ -package formatter +package hook import ( "fmt" @@ -41,7 +41,8 @@ func (hook ContextHook) Levels() []logrus.Level { // Fire extend with the source information the entry.Data func (hook ContextHook) Fire(entry *logrus.Entry) error { src := hook.parseSrc(entry.Caller.File) - entry.Data["source"] = fmt.Sprintf("%s:%v", src, entry.Caller.Line) + entry.Data[EntryKeySource] = fmt.Sprintf("%s:%v", src, entry.Caller.Line) + additionalEntries(entry) if entry.Context == nil { return nil diff --git a/formatter/hook_test.go b/formatter/hook/hook_test.go similarity index 98% rename from formatter/hook_test.go rename to formatter/hook/hook_test.go index a4bcb0284..802163244 100644 --- a/formatter/hook_test.go +++ b/formatter/hook/hook_test.go @@ -1,4 +1,4 @@ -package formatter +package hook import ( "testing" diff --git a/formatter/hook/keys.go b/formatter/hook/keys.go new file mode 100644 index 000000000..09781a88b --- /dev/null +++ b/formatter/hook/keys.go @@ -0,0 +1,6 @@ +package hook + +const ( + EntryKeySource = "source" + EntryKeyGoroutineID = "goroutine_id" +) diff --git a/formatter/levels/levels.go b/formatter/levels/levels.go new file mode 100644 index 000000000..41ae80db3 --- /dev/null +++ b/formatter/levels/levels.go @@ -0,0 +1,3 @@ +package levels + +var ValidLevelDesc = []string{"PANC", "FATL", "ERRO", "WARN", "INFO", "DEBG", "TRAC"} diff --git a/formatter/logcat.go b/formatter/logcat/logcat.go similarity index 63% rename from formatter/logcat.go rename to formatter/logcat/logcat.go index e8f606229..c561d3283 100644 --- a/formatter/logcat.go +++ b/formatter/logcat/logcat.go @@ -1,26 +1,28 @@ -package formatter +package logcat import ( "fmt" "strings" "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/levels" ) -// LogcatFormatter formats logs into text what is fit for logcat -type LogcatFormatter struct { +// Formatter formats logs into text what is fit for logcat +type Formatter struct { levelDesc []string } // NewLogcatFormatter create new LogcatFormatter instance -func NewLogcatFormatter() *LogcatFormatter { - return &LogcatFormatter{ - levelDesc: []string{"PANC", "FATL", "ERRO", "WARN", "INFO", "DEBG", "TRAC"}, +func NewLogcatFormatter() *Formatter { + return &Formatter{ + levelDesc: levels.ValidLevelDesc, } } // Format renders a single log entry -func (f *LogcatFormatter) Format(entry *logrus.Entry) ([]byte, error) { +func (f *Formatter) Format(entry *logrus.Entry) ([]byte, error) { var fields string keys := make([]string, 0, len(entry.Data)) for k, v := range entry.Data { @@ -39,7 +41,7 @@ func (f *LogcatFormatter) Format(entry *logrus.Entry) ([]byte, error) { return []byte(fmt.Sprintf("[%s] %s%s %s\n", level, fields, entry.Data["source"], entry.Message)), nil } -func (f *LogcatFormatter) parseLevel(level logrus.Level) string { +func (f *Formatter) parseLevel(level logrus.Level) string { if len(f.levelDesc) < int(level) { return "" } diff --git a/formatter/logcat_test.go b/formatter/logcat/logcat_test.go similarity index 97% rename from formatter/logcat_test.go rename to formatter/logcat/logcat_test.go index 45ba5bc46..fd4d92881 100644 --- a/formatter/logcat_test.go +++ b/formatter/logcat/logcat_test.go @@ -1,4 +1,4 @@ -package formatter +package logcat import ( "testing" @@ -25,4 +25,5 @@ func TestLogcatMessageFormat(t *testing.T) { if parsedString != expectedString && parsedString != expectedStringVariant { t.Errorf("The log messages don't match. Expected: '%s', got: '%s'", expectedString, parsedString) } + } diff --git a/formatter/set.go b/formatter/set.go index 9dfea5a7f..a609e7b48 100644 --- a/formatter/set.go +++ b/formatter/set.go @@ -2,31 +2,37 @@ package formatter import ( "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/hook" + "github.com/netbirdio/netbird/formatter/logcat" + "github.com/netbirdio/netbird/formatter/syslog" + "github.com/netbirdio/netbird/formatter/txt" ) // SetTextFormatter set the text formatter for given logger. func SetTextFormatter(logger *logrus.Logger) { - logger.Formatter = NewTextFormatter() + logger.Formatter = txt.NewTextFormatter() logger.ReportCaller = true - logger.AddHook(NewContextHook()) + logger.AddHook(hook.NewContextHook()) } + // SetSyslogFormatter set the text formatter for given logger. func SetSyslogFormatter(logger *logrus.Logger) { - logger.Formatter = NewSyslogFormatter() + logger.Formatter = syslog.NewSyslogFormatter() logger.ReportCaller = true - logger.AddHook(NewContextHook()) + logger.AddHook(hook.NewContextHook()) } // SetJSONFormatter set the JSON formatter for given logger. func SetJSONFormatter(logger *logrus.Logger) { logger.Formatter = &logrus.JSONFormatter{} logger.ReportCaller = true - logger.AddHook(NewContextHook()) + logger.AddHook(hook.NewContextHook()) } // SetLogcatFormatter set the logcat formatter for given logger. func SetLogcatFormatter(logger *logrus.Logger) { - logger.Formatter = NewLogcatFormatter() + logger.Formatter = logcat.NewLogcatFormatter() logger.ReportCaller = true - logger.AddHook(NewContextHook()) + logger.AddHook(hook.NewContextHook()) } diff --git a/formatter/syslog/formatter.go b/formatter/syslog/formatter.go new file mode 100644 index 000000000..e72c30347 --- /dev/null +++ b/formatter/syslog/formatter.go @@ -0,0 +1,39 @@ +package syslog + +import ( + "fmt" + "strings" + + "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/levels" +) + +// Formatter formats logs into text +type Formatter struct { + levelDesc []string +} + +// NewSyslogFormatter create new MySyslogFormatter instance +func NewSyslogFormatter() *Formatter { + return &Formatter{ + levelDesc: levels.ValidLevelDesc, + } +} + +// Format renders a single log entry +func (f *Formatter) Format(entry *logrus.Entry) ([]byte, error) { + var fields string + keys := make([]string, 0, len(entry.Data)) + for k, v := range entry.Data { + if k == "source" { + continue + } + keys = append(keys, fmt.Sprintf("%s: %v", k, v)) + } + + if len(keys) > 0 { + fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) + } + return []byte(fmt.Sprintf("%s%s\n", fields, entry.Message)), nil +} diff --git a/formatter/syslog/formatter_test.go b/formatter/syslog/formatter_test.go new file mode 100644 index 000000000..110a3390b --- /dev/null +++ b/formatter/syslog/formatter_test.go @@ -0,0 +1,26 @@ +package syslog + +import ( + "testing" + "time" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" +) + +func TestLogSyslogFormat(t *testing.T) { + + someEntry := &logrus.Entry{ + Data: logrus.Fields{"att1": 1, "att2": 2, "source": "some/fancy/path.go:46"}, + Time: time.Date(2021, time.Month(2), 21, 1, 10, 30, 0, time.UTC), + Level: 3, + Message: "Some Message", + } + + formatter := NewSyslogFormatter() + result, _ := formatter.Format(someEntry) + + parsedString := string(result) + expectedString := "^\\[(att1: 1, att2: 2|att2: 2, att1: 1)\\] Some Message\\s+$" + assert.Regexp(t, expectedString, parsedString) +} diff --git a/formatter/txt/format.go b/formatter/txt/format.go new file mode 100644 index 000000000..a88c41044 --- /dev/null +++ b/formatter/txt/format.go @@ -0,0 +1,31 @@ +//go:build !loggoroutine + +package txt + +import ( + "fmt" + "strings" + + "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/hook" +) + +func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) { + var fields string + keys := make([]string, 0, len(entry.Data)) + for k, v := range entry.Data { + if k == hook.EntryKeySource { + continue + } + keys = append(keys, fmt.Sprintf("%s: %v", k, v)) + } + + if len(keys) > 0 { + fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) + } + + level := f.parseLevel(entry.Level) + + return []byte(fmt.Sprintf("%s %s %s%s: %s\n", entry.Time.Format(f.timestampFormat), level, fields, entry.Data[hook.EntryKeySource], entry.Message)), nil +} diff --git a/formatter/txt/format_gorutines.go b/formatter/txt/format_gorutines.go new file mode 100644 index 000000000..a39aee633 --- /dev/null +++ b/formatter/txt/format_gorutines.go @@ -0,0 +1,35 @@ +//go:build loggoroutine + +package txt + +import ( + "fmt" + "strings" + + "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/hook" +) + +func (f *TextFormatter) Format(entry *logrus.Entry) ([]byte, error) { + var fields string + keys := make([]string, 0, len(entry.Data)) + for k, v := range entry.Data { + if k == hook.EntryKeySource { + continue + } + + if k == hook.EntryKeyGoroutineID { + continue + } + keys = append(keys, fmt.Sprintf("%s: %v", k, v)) + } + + if len(keys) > 0 { + fields = fmt.Sprintf("[%s] ", strings.Join(keys, ", ")) + } + + level := f.parseLevel(entry.Level) + + return []byte(fmt.Sprintf("%s %s %d %s%s: %s\n", entry.Time.Format(f.timestampFormat), level, entry.Data[hook.EntryKeyGoroutineID], fields, entry.Data[hook.EntryKeySource], entry.Message)), nil +} diff --git a/formatter/txt/formatter.go b/formatter/txt/formatter.go new file mode 100644 index 000000000..3b2a3fb4d --- /dev/null +++ b/formatter/txt/formatter.go @@ -0,0 +1,31 @@ +package txt + +import ( + "time" + + "github.com/sirupsen/logrus" + + "github.com/netbirdio/netbird/formatter/levels" +) + +// TextFormatter formats logs into text with included source code's path +type TextFormatter struct { + timestampFormat string + levelDesc []string +} + +// NewTextFormatter create new MyTextFormatter instance +func NewTextFormatter() *TextFormatter { + return &TextFormatter{ + levelDesc: levels.ValidLevelDesc, + timestampFormat: time.RFC3339, // or RFC3339 + } +} + +func (f *TextFormatter) parseLevel(level logrus.Level) string { + if len(f.levelDesc) < int(level) { + return "" + } + + return f.levelDesc[level] +} diff --git a/formatter/formatter_test.go b/formatter/txt/formatter_test.go similarity index 55% rename from formatter/formatter_test.go rename to formatter/txt/formatter_test.go index 1ed207958..590af5d50 100644 --- a/formatter/formatter_test.go +++ b/formatter/txt/formatter_test.go @@ -1,4 +1,4 @@ -package formatter +package txt import ( "testing" @@ -24,20 +24,3 @@ func TestLogTextFormat(t *testing.T) { expectedString := "^2021-02-21T01:10:30Z WARN \\[(att1: 1, att2: 2|att2: 2, att1: 1)\\] some/fancy/path.go:46: Some Message\\s+$" assert.Regexp(t, expectedString, parsedString) } - -func TestLogSyslogFormat(t *testing.T) { - - someEntry := &logrus.Entry{ - Data: logrus.Fields{"att1": 1, "att2": 2, "source": "some/fancy/path.go:46"}, - Time: time.Date(2021, time.Month(2), 21, 1, 10, 30, 0, time.UTC), - Level: 3, - Message: "Some Message", - } - - formatter := NewSyslogFormatter() - result, _ := formatter.Format(someEntry) - - parsedString := string(result) - expectedString := "^\\[(att1: 1, att2: 2|att2: 2, att1: 1)\\] Some Message\\s+$" - assert.Regexp(t, expectedString, parsedString) -} diff --git a/go.mod b/go.mod index 62461adc9..dfd3fa0bd 100644 --- a/go.mod +++ b/go.mod @@ -19,8 +19,8 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 github.com/vishvananda/netlink v1.2.1-beta.2 - golang.org/x/crypto v0.35.0 - golang.org/x/sys v0.30.0 + golang.org/x/crypto v0.36.0 + golang.org/x/sys v0.31.0 golang.zx2c4.com/wireguard v0.0.0-20230704135630-469159ecf7d1 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 golang.zx2c4.com/wireguard/windows v0.5.3 @@ -65,6 +65,7 @@ require ( github.com/okta/okta-sdk-golang/v2 v2.18.0 github.com/oschwald/maxminddb-golang v1.12.0 github.com/patrickmn/go-cache v2.1.0+incompatible + github.com/petermattis/goid v0.0.0-20250303134427-723919f7f203 github.com/pion/logging v0.2.2 github.com/pion/randutil v0.1.0 github.com/pion/stun/v2 v2.0.0 @@ -96,8 +97,8 @@ require ( golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a golang.org/x/net v0.33.0 golang.org/x/oauth2 v0.19.0 - golang.org/x/sync v0.11.0 - golang.org/x/term v0.29.0 + golang.org/x/sync v0.12.0 + golang.org/x/term v0.30.0 google.golang.org/api v0.177.0 gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.5.7 @@ -231,7 +232,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect golang.org/x/image v0.18.0 // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/text v0.22.0 // indirect + golang.org/x/text v0.23.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect diff --git a/go.sum b/go.sum index bd01a035a..2794c7546 100644 --- a/go.sum +++ b/go.sum @@ -529,8 +529,8 @@ github.com/netbirdio/go-netroute v0.0.0-20240611143515-f59b0e1d3944 h1:TDtJKmM6S github.com/netbirdio/go-netroute v0.0.0-20240611143515-f59b0e1d3944/go.mod h1:sHA6TRxjQ6RLbnI+3R4DZo2Eseg/iKiPRfNmcuNySVQ= github.com/netbirdio/ice/v3 v3.0.0-20240315174635-e72a50fcb64e h1:PURA50S8u4mF6RrkYYCAvvPCixhqqEiEy3Ej6avh04c= github.com/netbirdio/ice/v3 v3.0.0-20240315174635-e72a50fcb64e/go.mod h1:YMLU7qbKfVjmEv7EoZPIVEI+kNYxWCdPK3VS0BU+U4Q= -github.com/netbirdio/management-integrations/integrations v0.0.0-20250226165736-0ac3dc443266 h1:z7yibtn9dqDpT/UhLYY5bF4ELK5H06d4iaUoteRCfwE= -github.com/netbirdio/management-integrations/integrations v0.0.0-20250226165736-0ac3dc443266/go.mod h1:smsjbLWt5BUYXRKFwbBvUvembwYYXxryY+EHXKnG5KQ= +github.com/netbirdio/management-integrations/integrations v0.0.0-20250307154727-58660ea9a141 h1:GZUkZd9ZMBGahNt+AbYYvZrSMpOnaBLjHiBbloOE7sc= +github.com/netbirdio/management-integrations/integrations v0.0.0-20250307154727-58660ea9a141/go.mod h1:A5QUfEZb5J3tw8EUB9e3q7Bgd/JtC0WlFT1onf3HPCY= github.com/netbirdio/service v0.0.0-20240911161631-f62744f42502 h1:3tHlFmhTdX9axERMVN63dqyFqnvuD+EMJHzM7mNGON8= github.com/netbirdio/service v0.0.0-20240911161631-f62744f42502/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM= github.com/netbirdio/signal-dispatcher/dispatcher v0.0.0-20241010133937-e0df50df217d h1:bRq5TKgC7Iq20pDiuC54yXaWnAVeS5PdGpSokFTlR28= @@ -573,6 +573,8 @@ github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/petermattis/goid v0.0.0-20250303134427-723919f7f203 h1:E7Kmf11E4K7B5hDti2K2NqPb1nlYlGYsu02S1JNd/Bs= +github.com/petermattis/goid v0.0.0-20250303134427-723919f7f203/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= github.com/pion/dtls/v2 v2.2.10 h1:u2Axk+FyIR1VFTPurktB+1zoEPGIW3bmyj3LEFrXjAA= github.com/pion/dtls/v2 v2.2.10/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= @@ -697,10 +699,6 @@ github.com/testcontainers/testcontainers-go/modules/postgres v0.31.0 h1:isAwFS3K github.com/testcontainers/testcontainers-go/modules/postgres v0.31.0/go.mod h1:ZNYY8vumNCEG9YI59A9d6/YaMY49uwRhmeU563EzFGw= github.com/things-go/go-socks5 v0.0.4 h1:jMQjIc+qhD4z9cITOMnBiwo9dDmpGuXmBlkRFrl/qD0= github.com/things-go/go-socks5 v0.0.4/go.mod h1:sh4K6WHrmHZpjxLTCHyYtXYH8OUuD+yZun41NomR1IQ= -github.com/ti-mo/conntrack v0.5.1 h1:opEwkFICnDbQc0BUXl73PHBK0h23jEIFVjXsqvF4GY0= -github.com/ti-mo/conntrack v0.5.1/go.mod h1:T6NCbkMdVU4qEIgwL0njA6lw/iCAbzchlnwm1Sa314o= -github.com/ti-mo/netfilter v0.5.2 h1:CTjOwFuNNeZ9QPdRXt1MZFLFUf84cKtiQutNauHWd40= -github.com/ti-mo/netfilter v0.5.2/go.mod h1:Btx3AtFiOVdHReTDmP9AE+hlkOcvIy403u7BXXbWZKo= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= @@ -792,8 +790,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= -golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -919,8 +917,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -993,8 +991,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -1002,8 +1000,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= -golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y= +golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1018,8 +1016,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/infrastructure_files/docker-compose.yml.tmpl b/infrastructure_files/docker-compose.yml.tmpl index b7904fb5b..dc491ae23 100644 --- a/infrastructure_files/docker-compose.yml.tmpl +++ b/infrastructure_files/docker-compose.yml.tmpl @@ -1,6 +1,5 @@ -version: "3" services: - #UI dashboard + # UI dashboard dashboard: image: netbirdio/dashboard:$NETBIRD_DASHBOARD_TAG restart: unless-stopped @@ -33,6 +32,7 @@ services: options: max-size: "500m" max-file: "2" + # Signal signal: image: netbirdio/signal:$NETBIRD_SIGNAL_TAG @@ -49,6 +49,7 @@ services: options: max-size: "500m" max-file: "2" + # Relay relay: image: netbirdio/relay:$NETBIRD_RELAY_TAG @@ -115,6 +116,7 @@ services: options: max-size: "500m" max-file: "2" + volumes: $MGMT_VOLUMENAME: $SIGNAL_VOLUMENAME: diff --git a/infrastructure_files/docker-compose.yml.tmpl.traefik b/infrastructure_files/docker-compose.yml.tmpl.traefik index dcd3f955c..b62d15b7c 100644 --- a/infrastructure_files/docker-compose.yml.tmpl.traefik +++ b/infrastructure_files/docker-compose.yml.tmpl.traefik @@ -1,6 +1,5 @@ -version: "3" services: - #UI dashboard + # UI dashboard dashboard: image: netbirdio/dashboard:$NETBIRD_DASHBOARD_TAG restart: unless-stopped @@ -32,6 +31,11 @@ services: - traefik.enable=true - traefik.http.routers.netbird-dashboard.rule=Host(`$NETBIRD_DOMAIN`) - traefik.http.services.netbird-dashboard.loadbalancer.server.port=80 + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "2" # Signal signal: @@ -40,15 +44,20 @@ services: volumes: - $SIGNAL_VOLUMENAME:/var/lib/netbird #ports: - # - 10000:80 + # - $NETBIRD_SIGNAL_PORT:80 # # port and command for Let's Encrypt validation # - 443:443 # command: ["--letsencrypt-domain", "$NETBIRD_LETSENCRYPT_DOMAIN", "--log-file", "console"] labels: - traefik.enable=true - traefik.http.routers.netbird-signal.rule=Host(`$NETBIRD_DOMAIN`) && PathPrefix(`/signalexchange.SignalExchange/`) - - traefik.http.services.netbird-signal.loadbalancer.server.port=80 + - traefik.http.services.netbird-signal.loadbalancer.server.port=10000 - traefik.http.services.netbird-signal.loadbalancer.server.scheme=h2c + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "2" # Relay relay: @@ -60,8 +69,12 @@ services: - NB_EXPOSED_ADDRESS=$NETBIRD_RELAY_DOMAIN:$NETBIRD_RELAY_PORT # todo: change to a secure secret - NB_AUTH_SECRET=$NETBIRD_RELAY_AUTH_SECRET - ports: - - $NETBIRD_RELAY_PORT:$NETBIRD_RELAY_PORT + # ports: + # - $NETBIRD_RELAY_PORT:$NETBIRD_RELAY_PORT + labels: + - traefik.enable=true + - traefik.http.routers.netbird-relay.rule=Host(`$NETBIRD_DOMAIN`) && PathPrefix(`/relay`) + - traefik.http.services.netbird-relay.loadbalancer.server.port=33080 logging: driver: "json-file" options: @@ -87,8 +100,9 @@ services: # # command for Let's Encrypt validation without dashboard container # command: ["--letsencrypt-domain", "$NETBIRD_LETSENCRYPT_DOMAIN", "--log-file", "console"] command: [ - "--port", "443", + "--port", "33073", "--log-file", "console", + "--log-level", "info", "--disable-anonymous-metrics=$NETBIRD_DISABLE_ANONYMOUS_METRICS", "--single-account-mode-domain=$NETBIRD_MGMT_SINGLE_ACCOUNT_MODE_DOMAIN", "--dns-domain=$NETBIRD_MGMT_DNS_DOMAIN" @@ -97,12 +111,17 @@ services: - traefik.enable=true - traefik.http.routers.netbird-api.rule=Host(`$NETBIRD_DOMAIN`) && PathPrefix(`/api`) - traefik.http.routers.netbird-api.service=netbird-api - - traefik.http.services.netbird-api.loadbalancer.server.port=443 + - traefik.http.services.netbird-api.loadbalancer.server.port=33073 - traefik.http.routers.netbird-management.rule=Host(`$NETBIRD_DOMAIN`) && PathPrefix(`/management.ManagementService/`) - traefik.http.routers.netbird-management.service=netbird-management - - traefik.http.services.netbird-management.loadbalancer.server.port=443 + - traefik.http.services.netbird-management.loadbalancer.server.port=33073 - traefik.http.services.netbird-management.loadbalancer.server.scheme=h2c + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "2" environment: - NETBIRD_STORE_ENGINE_POSTGRES_DSN=$NETBIRD_STORE_ENGINE_POSTGRES_DSN - NETBIRD_STORE_ENGINE_MYSQL_DSN=$NETBIRD_STORE_ENGINE_MYSQL_DSN @@ -119,6 +138,11 @@ services: network_mode: host command: - -c /etc/turnserver.conf + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "2" volumes: $MGMT_VOLUMENAME: diff --git a/infrastructure_files/observability/grafana/dashboards/.gitignore b/infrastructure_files/observability/grafana/dashboards/.gitignore new file mode 100644 index 000000000..e89fdc9ac --- /dev/null +++ b/infrastructure_files/observability/grafana/dashboards/.gitignore @@ -0,0 +1,2 @@ +# Some files eg. management.json are being ignored by root .gitignore. Need to un-ignore all json dashboards here. +!*.json \ No newline at end of file diff --git a/infrastructure_files/observability/grafana/dashboards/management.json b/infrastructure_files/observability/grafana/dashboards/management.json new file mode 100644 index 000000000..95983603f --- /dev/null +++ b/infrastructure_files/observability/grafana/dashboards/management.json @@ -0,0 +1,3569 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 82, + "links": [], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Number of active peer streams connected to the gRPC server", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + }, + { + "color": "red", + "value": 0 + }, + { + "color": "#EAB839", + "value": 8000 + }, + { + "color": "green", + "value": 11000 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 14, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": true, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "exemplar": false, + "expr": "management_grpc_connected_streams_ratio{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}", + "format": "time_series", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "Connected grpc streams", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Connected peers", + "type": "stat" + }, + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 4 + }, + "id": 59, + "title": "Core metrics / Peers", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Number of active peer streams connected to the gRPC server over time", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 5 + }, + "id": 60, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "management_grpc_connected_streams_ratio{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}", + "instant": false, + "legendFormat": "{{cluster}}/{{environment}}/{{job}}/{{host}}", + "range": true, + "refId": "A" + } + ], + "title": "Connected peers count", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Rate of updates with new meta data from the peer.\n\nConstant high numbers of meta updates indicate a version with an issue. This can generate an issue on larger deployments since it will trigger an account-wide network map update.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 5 + }, + "id": 61, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "rate(management_account_peer_meta_update_counter_ratio_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])", + "instant": false, + "legendFormat": "{{cluster}}/{{environment}}/{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Peer metadata updates rate", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 13 + }, + "id": 34, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of calculating the peer network map that is sent to the clients.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 14 + }, + "id": 18, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.5,sum(increase(management_account_get_peer_network_map_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "includeNullMetadata": true, + "legendFormat": "p50", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.9,sum(increase(management_account_get_peer_network_map_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "legendFormat": "p90", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(increase(management_account_get_peer_network_map_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "legendFormat": "p99", + "range": true, + "refId": "C", + "useBackend": false + } + ], + "title": "GetPeerNetworkMap Latency", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of triggering the account peers update and preparing the required data for the network map being sent to the clients.\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 14 + }, + "id": 40, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.5,sum(increase(management_account_update_account_peers_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "includeNullMetadata": true, + "legendFormat": "p50", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.9,sum(increase(management_account_update_account_peers_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "legendFormat": "p90", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(increase(management_account_update_account_peers_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "legendFormat": "p99", + "range": true, + "refId": "C", + "useBackend": false + } + ], + "title": "UpdateAccountPeers Latency", + "type": "timeseries" + } + ], + "title": "Core metrics / Network map", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 39, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Number of update messages piling up in the update channel queue.\n\nA high queue number indicates either a network issue or a high number of account updates.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 15 + }, + "id": 56, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.5,sum(increase(management_grpc_updatechannel_queue_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "includeNullMetadata": true, + "legendFormat": "p50", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.9,sum(increase(management_grpc_updatechannel_queue_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "legendFormat": "p90", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(increase(management_grpc_updatechannel_queue_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "legendFormat": "p99", + "range": true, + "refId": "C", + "useBackend": false + } + ], + "title": "updatechannel queue length", + "type": "timeseries" + } + ], + "title": "Core metrics / updatechannel", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 15 + }, + "id": 38, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of how long it takes to save or delete an account in the store\n\nWill let you know if the DB is not keeping up with the requests coming from management", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 41, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.50, sum(rate(management_store_persistence_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "instant": false, + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(management_store_persistence_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p90", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(management_store_persistence_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p99", + "range": true, + "refId": "C" + } + ], + "title": "Database persistence latency", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of how long it takes to execute a transaction in the store\n\nWill let you know if the DB is not keeping up with the requests coming from management", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 16 + }, + "id": 42, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.50, sum(rate(management_store_transaction_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "instant": false, + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(management_store_transaction_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p90", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(management_store_transaction_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p99", + "range": true, + "refId": "C" + } + ], + "title": "Database transaction latency", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of how long a process holds the acquired global lock in the store", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 58, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.50, sum(rate(management_store_global_lock_acquisition_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "instant": false, + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(management_store_global_lock_acquisition_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p90", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(management_store_global_lock_acquisition_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p99", + "range": true, + "refId": "C" + } + ], + "title": "Global lock duration", + "type": "timeseries" + } + ], + "title": "Core metrics / store persistence", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 37, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "A high number for a long period might indicate an inconsistency between the number of local users and IdP", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 17 + }, + "id": 47, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "rate(management_idp_authenticate_request_counter_ratio_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])", + "instant": false, + "legendFormat": "{{cluster}}/{{environment}}/{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "IdP authenticate request rate ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "A high number for a long period might indicate an inconsistency between the number of local users and IdP", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 17 + }, + "id": 48, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "rate(management_idp_get_account_counter_ratio_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])", + "instant": false, + "legendFormat": "{{cluster}}/{{environment}}/{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "IdP get_account request rate ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqpm" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 25 + }, + "id": 49, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "rate(management_idp_update_user_meta_counter_ratio_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])", + "instant": false, + "legendFormat": "{{cluster}}/{{environment}}/{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "IdP update_user_meta request rate ", + "type": "timeseries" + } + ], + "title": "Core metrics / IdP", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 36, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 18 + }, + "id": 50, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(management_http_request_counter_ratio_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",method=~\"GET|OPTIONS\"}[$__rate_interval])) by (job,method)", + "instant": false, + "legendFormat": "{{method}}", + "range": true, + "refId": "A" + } + ], + "title": "Read request rate (GET, OPTIONS)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 18 + }, + "id": 51, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(management_http_request_counter_ratio_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",method=~\"POST|PUT|DELETE\"}[$__rate_interval])) by (job,method)", + "instant": false, + "legendFormat": "{{method}}", + "range": true, + "refId": "A" + } + ], + "title": "Write request rate (PUT, POST,DELETE)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of incoming read HTTP requests (GET, OPTIONS)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 52, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.50, sum(rate(management_http_request_duration_ms_total_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",type=~\"read\"}[5m])) by (le))", + "instant": false, + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(management_http_request_duration_ms_total_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",type=~\"read\"}[5m])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p90", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(management_http_request_duration_ms_total_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",type=~\"read\"}[5m])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p99", + "range": true, + "refId": "C" + } + ], + "title": "Read request latency (GET, OPTIONS)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of incoming write HTTP requests (PUT, POST,DELETE)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 26 + }, + "id": 53, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.50, sum(rate(management_http_request_duration_ms_total_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",type=~\"write\"}[5m])) by (le))", + "instant": false, + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(management_http_request_duration_ms_total_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",type=~\"write\"}[5m])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p90", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(management_http_request_duration_ms_total_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",type=~\"write\"}[5m])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p99", + "range": true, + "refId": "C" + } + ], + "title": "Write request latency (PUT, POST,DELETE)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 34 + }, + "id": 54, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(management_http_request_counter_ratio_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (job,exported_endpoint,method)", + "hide": false, + "instant": false, + "legendFormat": "{{method}}-{{exported_endpoint}}", + "range": true, + "refId": "A" + } + ], + "title": "Request rate by endpoint", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 41 + }, + "id": 55, + "options": { + "legend": { + "calcs": [ + "lastNotNull" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(management_http_request_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[5m])) by (exported_endpoint,method,le))", + "hide": false, + "instant": false, + "legendFormat": "{{method}}-{{exported_endpoint}}", + "range": true, + "refId": "B" + } + ], + "title": "p90 latency by endpoint", + "type": "timeseries" + } + ], + "title": "HTTP metrics", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 35, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Rate of sync gRPC requests from the peers to establish a connection and receive network map updates (update channel)", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 18 + }, + "id": 43, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(management_grpc_sync_request_counter_ratio_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (job)", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Sync request rate ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of the sync gRPC requests from the peers to establish a connection and receive network map updates (update channel)\n\nIf those are to high client will probably retry before management is able to respond\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 18 + }, + "id": 45, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.50, sum(rate(management_grpc_sync_request_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "instant": false, + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(management_grpc_sync_request_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p90", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(management_grpc_sync_request_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p99", + "range": true, + "refId": "C" + } + ], + "title": "Sync request latency", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Rate of login gRPC requests from the peers to authenticate and receive initial configuration and relay credentials", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 44, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(management_grpc_login_request_counter_ratio_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (job)", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Login request rate ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of the login gRPC requests from the peers to authenticate and receive initial configuration and relay credentials\n\nIf those are to high client will probably retry before management is able to respond\n", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 26 + }, + "id": 46, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.50, sum(rate(management_grpc_login_request_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "instant": false, + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(management_grpc_login_request_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p90", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(management_grpc_login_request_duration_ms_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p99", + "range": true, + "refId": "C" + } + ], + "title": "Login request latency", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "GetKey gRPC request rate", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 34 + }, + "id": 57, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(management_grpc_key_request_counter_ratio_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (job)", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "GetKey request rate ", + "type": "timeseries" + } + ], + "title": "RPC metrics", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 21, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 69, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": false, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 51 + }, + "id": 11, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [ + "lastNotNull", + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Mean", + "sortDesc": true + }, + "orientation": "auto", + "showValue": "auto", + "stacking": "normal", + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 100 + }, + "pluginVersion": "11.5.0-81732", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "delta(management_updatechannel_close_one_duration_micro_count{application=\"management\", environment=\"$environment\", host=~\"$host\"}[$interval])", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "CloseOne", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "sum(delta(management_updatechannel_send_duration_micro_count{host=\"$host\", environment=\"$environment\"}[$interval]))", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "Send", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "sum(delta(management_updatechannel_create_duration_micro_count{host=\"$host\", environment=\"$environment\"}[$interval]))", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "Create", + "range": true, + "refId": "C", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "delta(management_updatechannel_get_all_duration_micro_count{host=\"$host\", environment=\"$environment\"}[$interval])", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "GetAll", + "range": true, + "refId": "D", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "delta(management_updatechannel_haschannel_duration_micro_count{host=\"$host\", environment=\"$environment\"}[$interval])", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "HasChannel", + "range": true, + "refId": "E", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "delta(management_updatechannel_close_multiple_channels_count{host=\"$host\", environment=\"$environment\"}[$interval])", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "CloseMultiple", + "range": true, + "refId": "F", + "useBackend": false + } + ], + "title": "Update Channel operations", + "type": "barchart" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of update channel operations by operation", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "fieldMinMax": false, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "µs" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 51 + }, + "id": 13, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.0-81732", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "histogram_quantile(0.95, sum by(le) (rate(management_updatechannel_close_one_duration_micro_bucket{application=\"management\", environment=\"$environment\", host=~\"$host\"}[$interval])))", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "CloseOne", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.95, sum by(le) (rate(management_updatechannel_send_duration_micro_bucket{host=\"$host\", environment=\"$environment\"}[$interval])))", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "Send", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.95, sum by(le) (rate(management_updatechannel_create_duration_micro_bucket{host=\"$host\", environment=\"$environment\"}[$interval])))", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "Create", + "range": true, + "refId": "C", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.95, sum by(le) (rate(management_updatechannel_get_all_duration_micro_bucket{host=\"$host\", environment=\"$environment\"}[$interval])))", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "GetAll", + "range": true, + "refId": "D", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.95, sum by(le) (rate(management_updatechannel_haschannel_duration_micro_bucket{host=\"$host\", environment=\"$environment\"}[$interval])))", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "CloseMultiple", + "range": true, + "refId": "E", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.95, sum by(le) (rate(management_updatechannel_close_multiple_channels_bucket{host=\"$host\", environment=\"$environment\"}[$interval])))", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "HasChannel", + "range": true, + "refId": "F", + "useBackend": false + } + ], + "title": "Update Channel methods p95 Duration", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Ratio between closed and created update channels", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMax": 100, + "axisSoftMin": 0, + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 32, + "gradientMode": "hue", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "line" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "percent" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "C {__name__=\"management_updatechannel_create_duration_micro_sum\", closed=\"true\", environment=\"production\", host=\"management\", instance=\"localhost:8081\", job=\"prometheus.scrape.local\"}" + }, + "properties": [ + { + "id": "displayName", + "value": "Recreation" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 59 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.0-81732", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "delta(management_updatechannel_create_duration_micro_count{environment=\"$environment\", closed=\"true\", application=\"management\", host=~\"$host\"}[$interval])", + "fullMetaSearch": false, + "hide": true, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sum by(environment) (delta(management_updatechannel_create_duration_micro_count{environment=\"$environment\", application=\"management\"}[$interval]))", + "fullMetaSearch": false, + "hide": true, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "__expr__", + "uid": "${DS_EXPRESSION}" + }, + "expression": "100-$A/$B*100", + "hide": false, + "refId": "Rate", + "type": "math" + } + ], + "title": "Percentage of Recreated channels", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Number of update messages piling up in the update channel queue.\n\nA high queue number indicates either a network issue or a high number of account updates.", + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 59 + }, + "id": 27, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Greens", + "steps": 73 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "axisWidth": 60, + "decimals": 1, + "reverse": false, + "unit": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sum by(le) (increase(management_grpc_updatechannel_queue_bucket{application=\"management\", environment=\"$environment\", host=~\"$host\"}[$__rate_interval]))", + "format": "heatmap", + "fullMetaSearch": false, + "includeNullMetadata": true, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Update Channel heat map", + "type": "heatmap" + } + ], + "title": "General", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 20 + }, + "id": 22, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of triggering the account peers update and preparing the required data for the network map being sent to the clients.\n\nWhen you see a lighter color on a higher timing bucket, your users may experience issues.", + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 23, + "x": 0, + "y": 83 + }, + "id": 20, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Oranges", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "axisWidth": 60, + "decimals": 1, + "reverse": false, + "unit": "ms" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "sum by(le) (increase(management_account_update_account_peers_duration_ms_bucket{application=\"management\", environment=\"$environment\", host=~\"$host\"}[$__rate_interval]))", + "format": "heatmap", + "fullMetaSearch": false, + "includeNullMetadata": true, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "UpdateAccountPeers Latency", + "type": "heatmap" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Number of objects in the network map like peers, routes, firewall rules, etc. that are sent to the clients", + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 23, + "x": 0, + "y": 91 + }, + "id": 19, + "options": { + "calculate": false, + "cellGap": 1, + "color": { + "exponent": 0.5, + "fill": "dark-orange", + "mode": "scheme", + "reverse": false, + "scale": "exponential", + "scheme": "Oranges", + "steps": 64 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": true + }, + "rowsFrame": { + "layout": "auto" + }, + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "axisWidth": 60, + "decimals": 0, + "reverse": false, + "unit": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "exemplar": false, + "expr": "sum by(le) (increase(management_account_network_map_object_count_bucket{application=\"management\", environment=\"$environment\", host=~\"$host\"}[$__rate_interval]))", + "format": "heatmap", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "interval": "", + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "NetworkMap Objects", + "type": "heatmap" + } + ], + "title": "Network Map", + "type": "row" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "73c8e14b-5699-4876-b887-4299930521a5" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(management_grpc_connected_streams_ratio,cluster)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "cluster", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(management_grpc_connected_streams_ratio,cluster)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "None", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(management_grpc_connected_streams_ratio{cluster=\"$cluster\"},environment)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "environment", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(management_grpc_connected_streams_ratio{cluster=\"$cluster\"},environment)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "netbird-management", + "value": "netbird-management" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(management_grpc_connected_streams_ratio{cluster=\"$cluster\", environment=\"$environment\"},job)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "job", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(management_grpc_connected_streams_ratio{cluster=\"$cluster\", environment=\"$environment\"},job)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(management_grpc_connected_streams_ratio{cluster=\"$cluster\", environment=\"$environment\", job=\"$job\"},host)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "host", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(management_grpc_connected_streams_ratio{cluster=\"$cluster\", environment=\"$environment\", job=\"$job\"},host)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Netbird / Management", + "uid": "bebypwoziton4b-v4", + "version": 38, + "weekStart": "" +} \ No newline at end of file diff --git a/infrastructure_files/observability/grafana/dashboards/readme.md b/infrastructure_files/observability/grafana/dashboards/readme.md new file mode 100644 index 000000000..3160921a6 --- /dev/null +++ b/infrastructure_files/observability/grafana/dashboards/readme.md @@ -0,0 +1,12 @@ +## Dashboard variables + +1. **datasource**: Select Prometheus server +2. **cluster**: Filter NetBird instances by cluster +3. **environment**: Filter by environment (dev, staging, UAT, prod) +4. **job**: Select target NetBird instance if multiple are running +5. **host**: Filter metrics by host + + +NOTE: +- Your installation may have a subset of these variables. +- The dashboard expects `exported_endpoint` instead of `endpoint` in HTTP request metrics. \ No newline at end of file diff --git a/infrastructure_files/observability/grafana/dashboards/relay.json b/infrastructure_files/observability/grafana/dashboards/relay.json new file mode 100644 index 000000000..b80c59743 --- /dev/null +++ b/infrastructure_files/observability/grafana/dashboards/relay.json @@ -0,0 +1,926 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": 97, + "links": [], + "panels": [ + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 24, + "title": "Core metrics", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Number of connected peers by host", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 1 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "exemplar": false, + "expr": "relay_peers{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}", + "format": "time_series", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{cluster}}/{{environment}}/{{job}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Connected peers", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Number of active connected peers by host\n\nIdeally, this number would stay around 20% of the total connections, indicating that most of the connections are P2P", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + }, + { + "color": "red", + "value": 0 + }, + { + "color": "#EAB839", + "value": 8000 + }, + { + "color": "green", + "value": 11000 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Idle peers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#727374", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 1 + }, + "id": 16, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.0-81732", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "relay_peers_active{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}", + "format": "time_series", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{cluster}}/{{environment}}/{{job}}", + "range": true, + "refId": "B", + "useBackend": false + } + ], + "title": "Active peers", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Number of idle connected peers by host", + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-RdYlGr" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "blue", + "value": null + }, + { + "color": "red", + "value": 0 + }, + { + "color": "#EAB839", + "value": 8000 + }, + { + "color": "green", + "value": 11000 + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Idle peers" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#727374", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 1 + }, + "id": 19, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.0-81732", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "relay_peers_idle{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{cluster}}/{{environment}}/{{job}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Idle peers", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Authentication latency faced by each relay peer", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 25, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.5,sum(rate(relay_peer_authentication_time_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}[$__rate_interval])) by (le))", + "instant": false, + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.9,sum(rate(relay_peer_authentication_time_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p90", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(rate(relay_peer_authentication_time_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p99", + "range": true, + "refId": "C" + } + ], + "title": "Relay peer authentication latency ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Time taken for storing each peer connection and metadata into in-memory database", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 26, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.5,sum(rate(relay_peer_store_time_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}[$__rate_interval])) by (le))", + "instant": false, + "legendFormat": "p50", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.9,sum(rate(relay_peer_store_time_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p90", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(rate(relay_peer_store_time_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}[$__rate_interval])) by (le))", + "hide": false, + "instant": false, + "legendFormat": "p99", + "range": true, + "refId": "C" + } + ], + "title": "Relay peer store latency ", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Total number of bytes sent/received to peers ", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 36, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "binBps" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 21, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true, + "sortBy": "Last *", + "sortDesc": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.0-81732", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "rate(relay_transfer_sent_bytes_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": true, + "legendFormat": "sent", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "rate(relay_transfer_received_bytes_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}[$__rate_interval]) *-1", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "legendFormat": "received", + "range": true, + "refId": "B", + "useBackend": false + } + ], + "title": "Relay traffic bandwidth", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "Prometheus", + "value": "73c8e14b-5699-4876-b887-4299930521a5" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "isNone": true, + "selected": false, + "text": "None", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(relay_peers,cluster)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "cluster", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(relay_peers,cluster)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "isNone": true, + "selected": false, + "text": "None", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(relay_peers{cluster=\"$cluster\"},environment)", + "description": "", + "hide": 0, + "includeAll": false, + "label": "environment", + "multi": false, + "name": "environment", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(relay_peers{cluster=\"$cluster\"},environment)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "netbird-relay", + "value": "netbird-relay" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(relay_peers{cluster=\"$cluster\", environment=\"$environment\"},job)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "job", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(relay_peers{cluster=\"$cluster\", environment=\"$environment\"},job)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allValue": "", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(relay_peers{cluster=\"$cluster\", environment=\"$environment\", job=\"$job\"},instance)", + "hide": 0, + "includeAll": true, + "label": "host", + "multi": true, + "name": "host", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(relay_peers{cluster=\"$cluster\", environment=\"$environment\", job=\"$job\"},instance)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Netbird / Relay", + "uid": "febyq2pgq2u-v003", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/infrastructure_files/observability/grafana/dashboards/signal.json b/infrastructure_files/observability/grafana/dashboards/signal.json new file mode 100644 index 000000000..5e36f6ce6 --- /dev/null +++ b/infrastructure_files/observability/grafana/dashboards/signal.json @@ -0,0 +1,1877 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": {}, + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "11.1.1" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "timeseries", + "name": "Time series", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 1, + "id": null, + "links": [], + "panels": [ + { + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 13, + "title": "Core metrics / peers", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Number of active connected peers", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "decimals": 2, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": true, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "sum(active_peers{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\"}) by (cluster,environment,job)", + "fullMetaSearch": false, + "includeNullMetadata": true, + "legendFormat": "{{cluster}}/{{environment}}/{{job}}/", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Total active peers", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of how long a peer was connected\n\nThis is mostly informational, but if most of the connections are short lived, you may need to check any reverse proxy or connectivity issues", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.5,sum(increase(peer_connection_duration_seconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p50", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.90,sum(increase(peer_connection_duration_seconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p90", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(increase(peer_connection_duration_seconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p99", + "range": true, + "refId": "C", + "useBackend": false + } + ], + "title": "Peer connection duration", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Number of active connected peers by host", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "max": 25000, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 15000 + }, + { + "color": "red", + "value": 20000 + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "{__name__=\"active_peers\", application=\"signal\", environment=\"prod\", host=\"signal-1-prod\", instance=\"localhost:9090\", job=\"prometheus.scrape.local\"}" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [] + } + ] + }, + "gridPos": { + "h": 4, + "w": 12, + "x": 0, + "y": 5 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "exemplar": false, + "expr": "active_peers{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}", + "format": "time_series", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "{{cluster}}/{{environment}}/{{job}}/{{host}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Active Peer-Connections per Host", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 14, + "panels": [], + "title": "Core metrics / messages", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "No. of messages forwarded per seconds. \nThis doesn't include the failed message count. They are tracked separately.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "mps" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 0, + "y": 10 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "rate(messages_forwarded_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])", + "instant": false, + "legendFormat": "{{cluster}}/{{environment}}/{{job}}", + "range": true, + "refId": "A" + } + ], + "title": "Forwarded messages rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "mps" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 12, + "x": 12, + "y": 10 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(message_forward_failures_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (cluster,environment,job,type)", + "instant": false, + "legendFormat": "{{type}}", + "range": true, + "refId": "A" + } + ], + "title": "Forwarded messages failure rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 15 + }, + "id": 17, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.5,sum(increase(message_forward_latency_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p50", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.90,sum(increase(message_forward_latency_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p90", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(increase(message_forward_latency_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p99", + "range": true, + "refId": "C", + "useBackend": false + } + ], + "title": "Forwarded messages latency", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 18, + "panels": [], + "title": "Core metrics / registerations", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "rate of peer Registration and deregistration", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "cps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 24 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.0-81732", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "rate(registrations_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": true, + "legendFormat": "registration", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "rate(deregistrations_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": true, + "legendFormat": "deregistration", + "range": true, + "refId": "B", + "useBackend": false + } + ], + "title": "Registration and deregistration rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "mps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 24 + }, + "id": 19, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(registration_failures_total{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (cluster,environment,job,error)", + "instant": false, + "legendFormat": "{{error}}", + "range": true, + "refId": "A" + } + ], + "title": "Registration failure rate", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "time needed to register new peers", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 32 + }, + "id": 20, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.5,sum(increase(registration_delay_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p50", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.90,sum(increase(registration_delay_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p90", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(increase(registration_delay_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p99", + "range": true, + "refId": "C", + "useBackend": false + } + ], + "title": "Peer registration latency", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Duration of how long it takes to load a connection from the registry.\n\nNOTE: It should be below 1 ms", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 32 + }, + "id": 21, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.5,sum(increase(get_registration_delay_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p50", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.90,sum(increase(get_registration_delay_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p90", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(increase(get_registration_delay_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\"}[$__rate_interval])) by (le,cluster,environment,job))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p99", + "range": true, + "refId": "C", + "useBackend": false + } + ], + "title": "get_registration request latency", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 12, + "panels": [], + "title": "RPC metrics", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Send method is used by peers intending to send a message to another peer. The send covers the RPC call of sending the message from the initiator to signal.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 41 + }, + "id": 9, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.0-81732", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(rpc_server_requests_per_rpc_count{rpc_method=~\"Send\"}[$__rate_interval])) by (rpc_method,rpc_grpc_status_code)", + "hide": false, + "instant": false, + "legendFormat": "code: {{rpc_grpc_status_code}}", + "range": true, + "refId": "B" + } + ], + "title": "RPC requests rate (method: Send)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "reqps" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 41 + }, + "id": 23, + "options": { + "legend": { + "calcs": [ + "lastNotNull", + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.0-81732", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(rate(rpc_server_requests_per_rpc_count{rpc_method=~\"ConnectStream\"}[$__rate_interval])) by (rpc_method,rpc_grpc_status_code)", + "hide": false, + "instant": false, + "legendFormat": "code: {{rpc_grpc_status_code}}", + "range": true, + "refId": "B" + } + ], + "title": "RPC requests rate (method: ConnectStream)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 49 + }, + "id": 22, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.5,sum(increase(rpc_server_duration_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",rpc_method=~\"Send\"}[$__rate_interval])) by (le,cluster,environment,job,rpc_method))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p50", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.90,sum(increase(rpc_server_duration_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",rpc_method=~\"Send\"}[$__rate_interval])) by (le,cluster,environment,job,rpc_method))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p90", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(increase(rpc_server_duration_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",rpc_method=~\"Send\"}[$__rate_interval])) by (le,cluster,environment,job,rpc_method))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p99", + "range": true, + "refId": "C", + "useBackend": false + } + ], + "title": "RPC request latency (method: Send)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "description": "Shows estimated time of how long a peer was connected", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 49 + }, + "id": 25, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.1.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.5,sum(increase(rpc_server_duration_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",rpc_method=~\"ConnectStream\"}[$__rate_interval])) by (le,cluster,environment,job,rpc_method))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p50", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.90,sum(increase(rpc_server_duration_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",rpc_method=~\"ConnectStream\"}[$__rate_interval])) by (le,cluster,environment,job,rpc_method))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p90", + "range": true, + "refId": "B", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "histogram_quantile(0.99,sum(increase(rpc_server_duration_milliseconds_bucket{cluster=~\"$cluster\",environment=~\"$environment\",job=~\"$job\",host=~\"$host\",rpc_method=~\"ConnectStream\"}[$__rate_interval])) by (le,cluster,environment,job,rpc_method))", + "format": "heatmap", + "fullMetaSearch": false, + "hide": false, + "includeNullMetadata": false, + "legendFormat": "p99", + "range": true, + "refId": "C", + "useBackend": false + } + ], + "title": "RPC request latency (method: ConnectStream)", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [ + { + "current": {}, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(active_peers,cluster)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "cluster", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(active_peers,cluster)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(active_peers{cluster=\"$cluster\"},environment)", + "description": "", + "hide": 0, + "includeAll": false, + "label": "environment", + "multi": false, + "name": "environment", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(active_peers{cluster=\"$cluster\"},environment)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(active_peers{cluster=\"$cluster\", environment=\"$environment\"},job)", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "job", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(active_peers{cluster=\"$cluster\", environment=\"$environment\"},job)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "allValue": "", + "current": {}, + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "definition": "label_values(active_peers{cluster=\"$cluster\", environment=\"$environment\", job=\"$job\"},host)", + "hide": 0, + "includeAll": true, + "label": "", + "multi": true, + "name": "host", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(active_peers{cluster=\"$cluster\", environment=\"$environment\", job=\"$job\"},host)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Netbird / Signal", + "uid": "cebyq0fs0m-v001", + "version": 15, + "weekStart": "" + } \ No newline at end of file diff --git a/management/cmd/management.go b/management/cmd/management.go index 9f8fa2fcb..75d4179cb 100644 --- a/management/cmd/management.go +++ b/management/cmd/management.go @@ -37,7 +37,7 @@ import ( "github.com/netbirdio/netbird/management/server/peers" "github.com/netbirdio/netbird/encryption" - "github.com/netbirdio/netbird/formatter" + "github.com/netbirdio/netbird/formatter/hook" mgmtProto "github.com/netbirdio/netbird/management/proto" "github.com/netbirdio/netbird/management/server" "github.com/netbirdio/netbird/management/server/auth" @@ -91,7 +91,7 @@ var ( flag.Parse() //nolint - ctx := context.WithValue(cmd.Context(), formatter.ExecutionContextKey, formatter.SystemSource) + ctx := context.WithValue(cmd.Context(), hook.ExecutionContextKey, hook.SystemSource) err := util.InitLog(logLevel, logFile) if err != nil { @@ -137,7 +137,7 @@ var ( ctx, cancel := context.WithCancel(cmd.Context()) defer cancel() //nolint - ctx = context.WithValue(ctx, formatter.ExecutionContextKey, formatter.SystemSource) + ctx = context.WithValue(ctx, hook.ExecutionContextKey, hook.SystemSource) err := handleRebrand(cmd) if err != nil { @@ -382,7 +382,7 @@ func unaryInterceptor( ) (interface{}, error) { reqID := uuid.New().String() //nolint - ctx = context.WithValue(ctx, formatter.ExecutionContextKey, formatter.GRPCSource) + ctx = context.WithValue(ctx, hook.ExecutionContextKey, hook.GRPCSource) //nolint ctx = context.WithValue(ctx, nbContext.RequestIDKey, reqID) return handler(ctx, req) @@ -397,7 +397,7 @@ func streamInterceptor( reqID := uuid.New().String() wrapped := grpcMiddleware.WrapServerStream(ss) //nolint - ctx := context.WithValue(ss.Context(), formatter.ExecutionContextKey, formatter.GRPCSource) + ctx := context.WithValue(ss.Context(), hook.ExecutionContextKey, hook.GRPCSource) //nolint wrapped.WrappedContext = context.WithValue(ctx, nbContext.RequestIDKey, reqID) return handler(srv, wrapped) diff --git a/management/cmd/migration_up.go b/management/cmd/migration_up.go index 183fc554d..de061dca2 100644 --- a/management/cmd/migration_up.go +++ b/management/cmd/migration_up.go @@ -8,7 +8,7 @@ import ( log "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "github.com/netbirdio/netbird/formatter" + "github.com/netbirdio/netbird/formatter/hook" "github.com/netbirdio/netbird/management/server/store" "github.com/netbirdio/netbird/util" ) @@ -30,7 +30,7 @@ var upCmd = &cobra.Command{ } //nolint - ctx := context.WithValue(cmd.Context(), formatter.ExecutionContextKey, formatter.SystemSource) + ctx := context.WithValue(cmd.Context(), hook.ExecutionContextKey, hook.SystemSource) if err := store.MigrateFileStoreToSqlite(ctx, mgmtDataDir); err != nil { return err diff --git a/management/server/integrations/port_forwarding/controller.go b/management/server/integrations/port_forwarding/controller.go index 6390868fe..6f062bb12 100644 --- a/management/server/integrations/port_forwarding/controller.go +++ b/management/server/integrations/port_forwarding/controller.go @@ -9,6 +9,7 @@ import ( type Controller interface { SendUpdate(ctx context.Context, accountID string, affectedProxyID string, affectedPeerIDs []string) GetProxyNetworkMaps(ctx context.Context, accountID string) (map[string]*nbtypes.NetworkMap, error) + IsPeerInIngressPorts(ctx context.Context, accountID, peerID string) (bool, error) } type ControllerMock struct { @@ -25,3 +26,7 @@ func (c *ControllerMock) SendUpdate(ctx context.Context, accountID string, affec func (c *ControllerMock) GetProxyNetworkMaps(ctx context.Context, accountID string) (map[string]*nbtypes.NetworkMap, error) { return make(map[string]*nbtypes.NetworkMap), nil } + +func (c *ControllerMock) IsPeerInIngressPorts(ctx context.Context, accountID, peerID string) (bool, error) { + return false, nil +} diff --git a/management/server/management_proto_test.go b/management/server/management_proto_test.go index 529a3b57f..87ab1f433 100644 --- a/management/server/management_proto_test.go +++ b/management/server/management_proto_test.go @@ -20,7 +20,7 @@ import ( "google.golang.org/grpc/keepalive" "github.com/netbirdio/netbird/encryption" - "github.com/netbirdio/netbird/formatter" + "github.com/netbirdio/netbird/formatter/hook" mgmtProto "github.com/netbirdio/netbird/management/proto" nbAccount "github.com/netbirdio/netbird/management/server/account" "github.com/netbirdio/netbird/management/server/activity" @@ -426,7 +426,7 @@ func startManagementForTest(t *testing.T, testFile string, config *Config) (*grp peersUpdateManager := NewPeersUpdateManager(nil) eventStore := &activity.InMemoryEventStore{} - ctx := context.WithValue(context.Background(), formatter.ExecutionContextKey, formatter.SystemSource) //nolint:staticcheck + ctx := context.WithValue(context.Background(), hook.ExecutionContextKey, hook.SystemSource) //nolint:staticcheck metrics, err := telemetry.NewDefaultAppMetrics(context.Background()) require.NoError(t, err) diff --git a/management/server/peer.go b/management/server/peer.go index 0554032ad..a2b6e2165 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -346,6 +346,10 @@ func (am *DefaultAccountManager) DeletePeer(ctx context.Context, accountID, peer return err } + if err = am.validatePeerDelete(ctx, accountID, peerID); err != nil { + return err + } + updateAccountPeers, err = isPeerInActiveGroup(ctx, transaction, accountID, peerID) if err != nil { return err @@ -371,6 +375,9 @@ func (am *DefaultAccountManager) DeletePeer(ctx context.Context, accountID, peer eventsToStore, err = deletePeers(ctx, am, transaction, accountID, userID, []*nbpeer.Peer{peer}) return err }) + if err != nil { + return err + } for _, storeEvent := range eventsToStore { storeEvent() @@ -1505,3 +1512,17 @@ func ConvertSliceToMap(existingLabels []string) map[string]struct{} { } return labelMap } + +// validatePeerDelete checks if the peer can be deleted. +func (am *DefaultAccountManager) validatePeerDelete(ctx context.Context, accountId, peerId string) error { + linkedInIngressPorts, err := am.proxyController.IsPeerInIngressPorts(ctx, accountId, peerId) + if err != nil { + return err + } + + if linkedInIngressPorts { + return status.Errorf(status.PreconditionFailed, "peer is linked to ingress ports: %s", peerId) + } + + return nil +} diff --git a/management/server/telemetry/http_api_metrics.go b/management/server/telemetry/http_api_metrics.go index 5ef9e6d02..ae27466d9 100644 --- a/management/server/telemetry/http_api_metrics.go +++ b/management/server/telemetry/http_api_metrics.go @@ -13,7 +13,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" - "github.com/netbirdio/netbird/formatter" + "github.com/netbirdio/netbird/formatter/hook" nbContext "github.com/netbirdio/netbird/management/server/context" ) @@ -167,7 +167,7 @@ func (m *HTTPMiddleware) Handler(h http.Handler) http.Handler { reqStart := time.Now() //nolint - ctx := context.WithValue(r.Context(), formatter.ExecutionContextKey, formatter.HTTPSource) + ctx := context.WithValue(r.Context(), hook.ExecutionContextKey, hook.HTTPSource) reqID := uuid.New().String() //nolint