detached 6dc6603

feat(traffic): expose smart tcp status counters

commit
6dc660313517f3066556ecb58a6ca9783385a8d5
author
brice · · 2026-06-30 13:28 UTC
parent
3515791
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
4 files · +118 -33
M internal/adapters/dto/traffic.go +43 -8
@@ -23,6 +23,7 @@ type TrafficEntryPointStatus struct {
2323 TotalErrors int64 `json:"total_errors"`
2424 BytesIn int64 `json:"bytes_in"`
2525 BytesOut int64 `json:"bytes_out"`
26+ SmartTCP SmartTCPCounters `json:"smart_tcp"`
2627 }
2728
2829 type TrafficRouterStatus struct {
@@ -54,13 +55,29 @@ type TrafficBackendStatus struct {
5455 }
5556
5657 type TrafficCounters struct {
57- ActiveTCPConnections int64 `json:"active_tcp_connections"`
58- ActiveUDPSessions int64 `json:"active_udp_sessions"`
59- TotalAccepted int64 `json:"total_accepted"`
60- TotalRefused int64 `json:"total_refused"`
61- TotalErrors int64 `json:"total_errors"`
62- BytesIn int64 `json:"bytes_in"`
63- BytesOut int64 `json:"bytes_out"`
58+ ActiveTCPConnections int64 `json:"active_tcp_connections"`
59+ ActiveUDPSessions int64 `json:"active_udp_sessions"`
60+ TotalAccepted int64 `json:"total_accepted"`
61+ TotalRefused int64 `json:"total_refused"`
62+ TotalErrors int64 `json:"total_errors"`
63+ BytesIn int64 `json:"bytes_in"`
64+ BytesOut int64 `json:"bytes_out"`
65+ SmartTCP SmartTCPCounters `json:"smart_tcp"`
66+}
67+
68+type SmartTCPCounters struct {
69+ HTTPAccepted int64 `json:"http_accepted"`
70+ H2CAccepted int64 `json:"h2c_accepted"`
71+ HTTPSFallbackAccepted int64 `json:"https_fallback_accepted"`
72+ TLSPassthroughAccepted int64 `json:"tls_passthrough_accepted"`
73+ RawFallbackAccepted int64 `json:"raw_fallback_accepted"`
74+ EntrypointCIDRRefused int64 `json:"entrypoint_cidr_refused"`
75+ RawFallbackCIDRRefused int64 `json:"raw_fallback_cidr_refused"`
76+ PROXYRefused int64 `json:"proxy_refused"`
77+ UnknownNoFallbackRefused int64 `json:"unknown_no_fallback_refused"`
78+ MalformedRejected int64 `json:"malformed_rejected"`
79+ SniffTimeout int64 `json:"sniff_timeout"`
80+ ClientHelloTooLarge int64 `json:"client_hello_too_large"`
6481 }
6582
6683 func TrafficStatusFromDomain(status domain.TrafficStatus) TrafficStatusResponse {
@@ -81,7 +98,7 @@ func trafficEntryPointsFromDomain(values []domain.EntryPointStatus) []TrafficEnt
8198 Name: value.Name, Address: value.Address, Protocol: value.Protocol, Active: value.Active,
8299 ActiveTCPConnections: value.ActiveTCPConnections, ActiveUDPSessions: value.ActiveUDPSessions,
83100 TotalAccepted: value.TotalAccepted, TotalRefused: value.TotalRefused, TotalErrors: value.TotalErrors,
84- BytesIn: value.BytesIn, BytesOut: value.BytesOut,
101+ BytesIn: value.BytesIn, BytesOut: value.BytesOut, SmartTCP: smartTCPCountersFromDomain(value.SmartTCP),
85102 })
86103 }
87104 return out
@@ -125,5 +142,23 @@ func trafficCountersFromDomain(value domain.TrafficCounters) TrafficCounters {
125142 TotalErrors: value.TotalErrors,
126143 BytesIn: value.BytesIn,
127144 BytesOut: value.BytesOut,
145+ SmartTCP: smartTCPCountersFromDomain(value.SmartTCP),
146+ }
147+}
148+
149+func smartTCPCountersFromDomain(value domain.SmartTCPCounters) SmartTCPCounters {
150+ return SmartTCPCounters{
151+ HTTPAccepted: value.HTTPAccepted,
152+ H2CAccepted: value.H2CAccepted,
153+ HTTPSFallbackAccepted: value.HTTPSFallbackAccepted,
154+ TLSPassthroughAccepted: value.TLSPassthroughAccepted,
155+ RawFallbackAccepted: value.RawFallbackAccepted,
156+ EntrypointCIDRRefused: value.EntrypointCIDRRefused,
157+ RawFallbackCIDRRefused: value.RawFallbackCIDRRefused,
158+ PROXYRefused: value.PROXYRefused,
159+ UnknownNoFallbackRefused: value.UnknownNoFallbackRefused,
160+ MalformedRejected: value.MalformedRejected,
161+ SniffTimeout: value.SniffTimeout,
162+ ClientHelloTooLarge: value.ClientHelloTooLarge,
128163 }
129164 }
@@ -23,6 +23,7 @@ type TrafficEntryPointStatus struct {
23 TotalErrors int64 `json:"total_errors"`23 TotalErrors int64 `json:"total_errors"`
24 BytesIn int64 `json:"bytes_in"`24 BytesIn int64 `json:"bytes_in"`
25 BytesOut int64 `json:"bytes_out"`25 BytesOut int64 `json:"bytes_out"`
26+ SmartTCP SmartTCPCounters `json:"smart_tcp"`
26 }27 }
27 28
28 type TrafficRouterStatus struct {29 type TrafficRouterStatus struct {
@@ -54,13 +55,29 @@ type TrafficBackendStatus struct {
54 }55 }
55 56
56 type TrafficCounters struct {57 type TrafficCounters struct {
57- ActiveTCPConnections int64 `json:"active_tcp_connections"`58+ ActiveTCPConnections int64 `json:"active_tcp_connections"`
58- ActiveUDPSessions int64 `json:"active_udp_sessions"`59+ ActiveUDPSessions int64 `json:"active_udp_sessions"`
59- TotalAccepted int64 `json:"total_accepted"`60+ TotalAccepted int64 `json:"total_accepted"`
60- TotalRefused int64 `json:"total_refused"`61+ TotalRefused int64 `json:"total_refused"`
61- TotalErrors int64 `json:"total_errors"`62+ TotalErrors int64 `json:"total_errors"`
62- BytesIn int64 `json:"bytes_in"`63+ BytesIn int64 `json:"bytes_in"`
63- BytesOut int64 `json:"bytes_out"`64+ BytesOut int64 `json:"bytes_out"`
65+ SmartTCP SmartTCPCounters `json:"smart_tcp"`
66+}
67+
68+type SmartTCPCounters struct {
69+ HTTPAccepted int64 `json:"http_accepted"`
70+ H2CAccepted int64 `json:"h2c_accepted"`
71+ HTTPSFallbackAccepted int64 `json:"https_fallback_accepted"`
72+ TLSPassthroughAccepted int64 `json:"tls_passthrough_accepted"`
73+ RawFallbackAccepted int64 `json:"raw_fallback_accepted"`
74+ EntrypointCIDRRefused int64 `json:"entrypoint_cidr_refused"`
75+ RawFallbackCIDRRefused int64 `json:"raw_fallback_cidr_refused"`
76+ PROXYRefused int64 `json:"proxy_refused"`
77+ UnknownNoFallbackRefused int64 `json:"unknown_no_fallback_refused"`
78+ MalformedRejected int64 `json:"malformed_rejected"`
79+ SniffTimeout int64 `json:"sniff_timeout"`
80+ ClientHelloTooLarge int64 `json:"client_hello_too_large"`
64 }81 }
65 82
66 func TrafficStatusFromDomain(status domain.TrafficStatus) TrafficStatusResponse {83 func TrafficStatusFromDomain(status domain.TrafficStatus) TrafficStatusResponse {
@@ -81,7 +98,7 @@ func trafficEntryPointsFromDomain(values []domain.EntryPointStatus) []TrafficEnt
81 Name: value.Name, Address: value.Address, Protocol: value.Protocol, Active: value.Active,98 Name: value.Name, Address: value.Address, Protocol: value.Protocol, Active: value.Active,
82 ActiveTCPConnections: value.ActiveTCPConnections, ActiveUDPSessions: value.ActiveUDPSessions,99 ActiveTCPConnections: value.ActiveTCPConnections, ActiveUDPSessions: value.ActiveUDPSessions,
83 TotalAccepted: value.TotalAccepted, TotalRefused: value.TotalRefused, TotalErrors: value.TotalErrors,100 TotalAccepted: value.TotalAccepted, TotalRefused: value.TotalRefused, TotalErrors: value.TotalErrors,
84- BytesIn: value.BytesIn, BytesOut: value.BytesOut,101+ BytesIn: value.BytesIn, BytesOut: value.BytesOut, SmartTCP: smartTCPCountersFromDomain(value.SmartTCP),
85 })102 })
86 }103 }
87 return out104 return out
@@ -125,5 +142,23 @@ func trafficCountersFromDomain(value domain.TrafficCounters) TrafficCounters {
125 TotalErrors: value.TotalErrors,142 TotalErrors: value.TotalErrors,
126 BytesIn: value.BytesIn,143 BytesIn: value.BytesIn,
127 BytesOut: value.BytesOut,144 BytesOut: value.BytesOut,
145+ SmartTCP: smartTCPCountersFromDomain(value.SmartTCP),
146+ }
147+}
148+
149+func smartTCPCountersFromDomain(value domain.SmartTCPCounters) SmartTCPCounters {
150+ return SmartTCPCounters{
151+ HTTPAccepted: value.HTTPAccepted,
152+ H2CAccepted: value.H2CAccepted,
153+ HTTPSFallbackAccepted: value.HTTPSFallbackAccepted,
154+ TLSPassthroughAccepted: value.TLSPassthroughAccepted,
155+ RawFallbackAccepted: value.RawFallbackAccepted,
156+ EntrypointCIDRRefused: value.EntrypointCIDRRefused,
157+ RawFallbackCIDRRefused: value.RawFallbackCIDRRefused,
158+ PROXYRefused: value.PROXYRefused,
159+ UnknownNoFallbackRefused: value.UnknownNoFallbackRefused,
160+ MalformedRejected: value.MalformedRejected,
161+ SniffTimeout: value.SniffTimeout,
162+ ClientHelloTooLarge: value.ClientHelloTooLarge,
128 }163 }
129 }164 }
M internal/adapters/in/cli/traffic_status.go +62 -20
@@ -46,48 +46,90 @@ func renderTrafficStatus(out io.Writer, status *dto.TrafficStatusResponse, jsonO
4646 if jsonOut {
4747 return writeJSON(out, status)
4848 }
49+ if err := renderTrafficStatusHeader(out, status); err != nil {
50+ return err
51+ }
52+ if err := renderTrafficEntryPoints(out, status.EntryPoints); err != nil {
53+ return err
54+ }
55+ if err := renderTrafficRouters(out, status.Routers); err != nil {
56+ return err
57+ }
58+ if err := renderTrafficServices(out, status.Services); err != nil {
59+ return err
60+ }
61+ return renderTrafficTotals(out, status.Counters)
62+}
63+
64+func renderTrafficStatusHeader(out io.Writer, status *dto.TrafficStatusResponse) error {
4965 if err := cliWriteLine(out, cliRenderTitle("Traffic Status")); err != nil {
5066 return err
5167 }
5268 if err := cliWriteLine(out, cliRenderMeta("Reload", status.LastReloadStatus)); err != nil {
5369 return err
5470 }
55- if status.LastReloadError != "" {
56- if err := cliWriteLine(out, cliRenderWarning("Last reload error: "+status.LastReloadError)); err != nil {
57- return err
58- }
71+ if status.LastReloadError == "" {
72+ return nil
5973 }
74+ return cliWriteLine(out, cliRenderWarning("Last reload error: "+status.LastReloadError))
75+}
76+
77+func renderTrafficEntryPoints(out io.Writer, entries []dto.TrafficEntryPointStatus) error {
6078 if err := cliWriteLine(out, ""); err != nil {
6179 return err
6280 }
6381 if err := cliWriteLine(out, "Entrypoints:"); err != nil {
6482 return err
6583 }
66- if len(status.EntryPoints) == 0 {
67- if err := cliWriteLine(out, cliRenderMuted(" none")); err != nil {
84+ if len(entries) == 0 {
85+ return cliWriteLine(out, cliRenderMuted(" none"))
86+ }
87+ for _, entry := range entries {
88+ if err := renderTrafficEntryPoint(out, entry); err != nil {
6889 return err
6990 }
70- } else {
71- for _, entry := range status.EntryPoints {
72- if err := cliWritef(out, " %s %s %s active=%t tcp=%d udp=%d accepted=%d refused=%d errors=%d\n",
73- entry.Name, entry.Protocol, entry.Address, entry.Active, entry.ActiveTCPConnections, entry.ActiveUDPSessions,
74- entry.TotalAccepted, entry.TotalRefused, entry.TotalErrors); err != nil {
75- return err
76- }
77- }
7891 }
79- if err := renderTrafficRouters(out, status.Routers); err != nil {
92+ return nil
93+}
94+
95+func renderTrafficEntryPoint(out io.Writer, entry dto.TrafficEntryPointStatus) error {
96+ if err := cliWritef(out, " %s %s %s active=%t tcp=%d udp=%d accepted=%d refused=%d errors=%d\n",
97+ entry.Name, entry.Protocol, entry.Address, entry.Active, entry.ActiveTCPConnections, entry.ActiveUDPSessions,
98+ entry.TotalAccepted, entry.TotalRefused, entry.TotalErrors); err != nil {
8099 return err
81100 }
82- if err := renderTrafficServices(out, status.Services); err != nil {
83- return err
101+ if hasSmartTCPCounters(entry.SmartTCP) {
102+ return renderSmartTCPCounters(out, " smart_tcp", entry.SmartTCP)
84103 }
104+ return nil
105+}
106+
107+func renderTrafficTotals(out io.Writer, counters dto.TrafficCounters) error {
85108 if err := cliWriteLine(out, ""); err != nil {
86109 return err
87110 }
88- return cliWritef(out, "Totals: tcp=%d udp=%d accepted=%d refused=%d errors=%d bytes_in=%d bytes_out=%d\n",
89- status.Counters.ActiveTCPConnections, status.Counters.ActiveUDPSessions, status.Counters.TotalAccepted,
90- status.Counters.TotalRefused, status.Counters.TotalErrors, status.Counters.BytesIn, status.Counters.BytesOut)
111+ if err := cliWritef(out, "Totals: tcp=%d udp=%d accepted=%d refused=%d errors=%d bytes_in=%d bytes_out=%d\n",
112+ counters.ActiveTCPConnections, counters.ActiveUDPSessions, counters.TotalAccepted,
113+ counters.TotalRefused, counters.TotalErrors, counters.BytesIn, counters.BytesOut); err != nil {
114+ return err
115+ }
116+ if hasSmartTCPCounters(counters.SmartTCP) {
117+ return renderSmartTCPCounters(out, "Smart TCP totals", counters.SmartTCP)
118+ }
119+ return nil
120+}
121+
122+func hasSmartTCPCounters(c dto.SmartTCPCounters) bool {
123+ return c.HTTPAccepted != 0 || c.H2CAccepted != 0 || c.HTTPSFallbackAccepted != 0 || c.TLSPassthroughAccepted != 0 ||
124+ c.RawFallbackAccepted != 0 || c.EntrypointCIDRRefused != 0 || c.RawFallbackCIDRRefused != 0 || c.PROXYRefused != 0 ||
125+ c.UnknownNoFallbackRefused != 0 || c.MalformedRejected != 0 || c.SniffTimeout != 0 || c.ClientHelloTooLarge != 0
126+}
127+
128+func renderSmartTCPCounters(out io.Writer, label string, c dto.SmartTCPCounters) error {
129+ return cliWritef(out, "%s: http_accepted=%d h2c_accepted=%d https_fallback_accepted=%d tls_passthrough_accepted=%d raw_fallback_accepted=%d entrypoint_cidr_refused=%d raw_fallback_cidr_refused=%d proxy_refused=%d unknown_no_fallback_refused=%d malformed_rejected=%d sniff_timeout=%d client_hello_too_large=%d\n",
130+ label, c.HTTPAccepted, c.H2CAccepted, c.HTTPSFallbackAccepted, c.TLSPassthroughAccepted, c.RawFallbackAccepted,
131+ c.EntrypointCIDRRefused, c.RawFallbackCIDRRefused, c.PROXYRefused, c.UnknownNoFallbackRefused, c.MalformedRejected,
132+ c.SniffTimeout, c.ClientHelloTooLarge)
91133 }
92134
93135 func renderTrafficRouters(out io.Writer, routers []dto.TrafficRouterStatus) error {
@@ -46,48 +46,90 @@ func renderTrafficStatus(out io.Writer, status *dto.TrafficStatusResponse, jsonO
46 if jsonOut {46 if jsonOut {
47 return writeJSON(out, status)47 return writeJSON(out, status)
48 }48 }
49+ if err := renderTrafficStatusHeader(out, status); err != nil {
50+ return err
51+ }
52+ if err := renderTrafficEntryPoints(out, status.EntryPoints); err != nil {
53+ return err
54+ }
55+ if err := renderTrafficRouters(out, status.Routers); err != nil {
56+ return err
57+ }
58+ if err := renderTrafficServices(out, status.Services); err != nil {
59+ return err
60+ }
61+ return renderTrafficTotals(out, status.Counters)
62+}
63+
64+func renderTrafficStatusHeader(out io.Writer, status *dto.TrafficStatusResponse) error {
49 if err := cliWriteLine(out, cliRenderTitle("Traffic Status")); err != nil {65 if err := cliWriteLine(out, cliRenderTitle("Traffic Status")); err != nil {
50 return err66 return err
51 }67 }
52 if err := cliWriteLine(out, cliRenderMeta("Reload", status.LastReloadStatus)); err != nil {68 if err := cliWriteLine(out, cliRenderMeta("Reload", status.LastReloadStatus)); err != nil {
53 return err69 return err
54 }70 }
55- if status.LastReloadError != "" {71+ if status.LastReloadError == "" {
56- if err := cliWriteLine(out, cliRenderWarning("Last reload error: "+status.LastReloadError)); err != nil {72+ return nil
57- return err
58- }
59 }73 }
74+ return cliWriteLine(out, cliRenderWarning("Last reload error: "+status.LastReloadError))
75+}
76+
77+func renderTrafficEntryPoints(out io.Writer, entries []dto.TrafficEntryPointStatus) error {
60 if err := cliWriteLine(out, ""); err != nil {78 if err := cliWriteLine(out, ""); err != nil {
61 return err79 return err
62 }80 }
63 if err := cliWriteLine(out, "Entrypoints:"); err != nil {81 if err := cliWriteLine(out, "Entrypoints:"); err != nil {
64 return err82 return err
65 }83 }
66- if len(status.EntryPoints) == 0 {84+ if len(entries) == 0 {
67- if err := cliWriteLine(out, cliRenderMuted(" none")); err != nil {85+ return cliWriteLine(out, cliRenderMuted(" none"))
86+ }
87+ for _, entry := range entries {
88+ if err := renderTrafficEntryPoint(out, entry); err != nil {
68 return err89 return err
69 }90 }
70- } else {
71- for _, entry := range status.EntryPoints {
72- if err := cliWritef(out, " %s %s %s active=%t tcp=%d udp=%d accepted=%d refused=%d errors=%d\n",
73- entry.Name, entry.Protocol, entry.Address, entry.Active, entry.ActiveTCPConnections, entry.ActiveUDPSessions,
74- entry.TotalAccepted, entry.TotalRefused, entry.TotalErrors); err != nil {
75- return err
76- }
77- }
78 }91 }
79- if err := renderTrafficRouters(out, status.Routers); err != nil {92+ return nil
93+}
94+
95+func renderTrafficEntryPoint(out io.Writer, entry dto.TrafficEntryPointStatus) error {
96+ if err := cliWritef(out, " %s %s %s active=%t tcp=%d udp=%d accepted=%d refused=%d errors=%d\n",
97+ entry.Name, entry.Protocol, entry.Address, entry.Active, entry.ActiveTCPConnections, entry.ActiveUDPSessions,
98+ entry.TotalAccepted, entry.TotalRefused, entry.TotalErrors); err != nil {
80 return err99 return err
81 }100 }
82- if err := renderTrafficServices(out, status.Services); err != nil {101+ if hasSmartTCPCounters(entry.SmartTCP) {
83- return err102+ return renderSmartTCPCounters(out, " smart_tcp", entry.SmartTCP)
84 }103 }
104+ return nil
105+}
106+
107+func renderTrafficTotals(out io.Writer, counters dto.TrafficCounters) error {
85 if err := cliWriteLine(out, ""); err != nil {108 if err := cliWriteLine(out, ""); err != nil {
86 return err109 return err
87 }110 }
88- return cliWritef(out, "Totals: tcp=%d udp=%d accepted=%d refused=%d errors=%d bytes_in=%d bytes_out=%d\n",111+ if err := cliWritef(out, "Totals: tcp=%d udp=%d accepted=%d refused=%d errors=%d bytes_in=%d bytes_out=%d\n",
89- status.Counters.ActiveTCPConnections, status.Counters.ActiveUDPSessions, status.Counters.TotalAccepted,112+ counters.ActiveTCPConnections, counters.ActiveUDPSessions, counters.TotalAccepted,
90- status.Counters.TotalRefused, status.Counters.TotalErrors, status.Counters.BytesIn, status.Counters.BytesOut)113+ counters.TotalRefused, counters.TotalErrors, counters.BytesIn, counters.BytesOut); err != nil {
114+ return err
115+ }
116+ if hasSmartTCPCounters(counters.SmartTCP) {
117+ return renderSmartTCPCounters(out, "Smart TCP totals", counters.SmartTCP)
118+ }
119+ return nil
120+}
121+
122+func hasSmartTCPCounters(c dto.SmartTCPCounters) bool {
123+ return c.HTTPAccepted != 0 || c.H2CAccepted != 0 || c.HTTPSFallbackAccepted != 0 || c.TLSPassthroughAccepted != 0 ||
124+ c.RawFallbackAccepted != 0 || c.EntrypointCIDRRefused != 0 || c.RawFallbackCIDRRefused != 0 || c.PROXYRefused != 0 ||
125+ c.UnknownNoFallbackRefused != 0 || c.MalformedRejected != 0 || c.SniffTimeout != 0 || c.ClientHelloTooLarge != 0
126+}
127+
128+func renderSmartTCPCounters(out io.Writer, label string, c dto.SmartTCPCounters) error {
129+ return cliWritef(out, "%s: http_accepted=%d h2c_accepted=%d https_fallback_accepted=%d tls_passthrough_accepted=%d raw_fallback_accepted=%d entrypoint_cidr_refused=%d raw_fallback_cidr_refused=%d proxy_refused=%d unknown_no_fallback_refused=%d malformed_rejected=%d sniff_timeout=%d client_hello_too_large=%d\n",
130+ label, c.HTTPAccepted, c.H2CAccepted, c.HTTPSFallbackAccepted, c.TLSPassthroughAccepted, c.RawFallbackAccepted,
131+ c.EntrypointCIDRRefused, c.RawFallbackCIDRRefused, c.PROXYRefused, c.UnknownNoFallbackRefused, c.MalformedRejected,
132+ c.SniffTimeout, c.ClientHelloTooLarge)
91 }133 }
92 134
93 func renderTrafficRouters(out io.Writer, routers []dto.TrafficRouterStatus) error {135 func renderTrafficRouters(out io.Writer, routers []dto.TrafficRouterStatus) error {
M internal/adapters/in/cli/traffic_test.go +7 -2
@@ -31,6 +31,7 @@ func TestTrafficStatusHumanOutput(t *testing.T) {
3131 EntryPoints: []dto.TrafficEntryPointStatus{{
3232 Name: "postgres", Address: "127.0.0.1:5432", Protocol: domain.EntryPointProtocolTCP,
3333 Active: true, ActiveTCPConnections: 1, TotalAccepted: 2, BytesIn: 10, BytesOut: 20,
34+ SmartTCP: dto.SmartTCPCounters{HTTPAccepted: 1, PROXYRefused: 1},
3435 }},
3536 Routers: []dto.TrafficRouterStatus{{
3637 Name: "pg-router", EntryPoint: "postgres", Protocol: domain.RouterProtocolTCP,
@@ -40,7 +41,7 @@ func TestTrafficStatusHumanOutput(t *testing.T) {
4041 Name: "network_service:postgres:db", Active: true,
4142 Backends: []dto.TrafficBackendStatus{{Name: "postgres:db", Host: "127.0.0.1", Port: 5432, Protocol: domain.NetworkProtocolTCP, Active: true}},
4243 }},
43- Counters: dto.TrafficCounters{ActiveTCPConnections: 1, TotalAccepted: 2, BytesIn: 10, BytesOut: 20},
44+ Counters: dto.TrafficCounters{ActiveTCPConnections: 1, TotalAccepted: 2, BytesIn: 10, BytesOut: 20, SmartTCP: dto.SmartTCPCounters{HTTPAccepted: 1, PROXYRefused: 1}},
4445 }
4546 var buf bytes.Buffer
4647 require.NoError(t, renderTrafficStatus(&buf, status, false))
@@ -52,14 +53,18 @@ func TestTrafficStatusHumanOutput(t *testing.T) {
5253 assert.Contains(t, output, "network_service:postgres:db")
5354 assert.Contains(t, output, "tcp://127.0.0.1:5432")
5455 assert.Contains(t, output, "accepted=2")
56+ assert.Contains(t, output, "smart_tcp")
57+ assert.Contains(t, output, "http_accepted=1")
58+ assert.Contains(t, output, "proxy_refused=1")
5559 }
5660
5761 func TestTrafficStatusJSONOutput(t *testing.T) {
58- status := &dto.TrafficStatusResponse{LastReloadStatus: "ok", Counters: dto.TrafficCounters{ActiveUDPSessions: 3}}
62+ status := &dto.TrafficStatusResponse{LastReloadStatus: "ok", Counters: dto.TrafficCounters{ActiveUDPSessions: 3, SmartTCP: dto.SmartTCPCounters{SniffTimeout: 1}}}
5963 var buf bytes.Buffer
6064 require.NoError(t, renderTrafficStatus(&buf, status, true))
6165 var got dto.TrafficStatusResponse
6266 require.NoError(t, json.Unmarshal(buf.Bytes(), &got))
6367 assert.Equal(t, "ok", got.LastReloadStatus)
6468 assert.Equal(t, int64(3), got.Counters.ActiveUDPSessions)
69+ assert.Equal(t, int64(1), got.Counters.SmartTCP.SniffTimeout)
6570 }
@@ -31,6 +31,7 @@ func TestTrafficStatusHumanOutput(t *testing.T) {
31 EntryPoints: []dto.TrafficEntryPointStatus{{31 EntryPoints: []dto.TrafficEntryPointStatus{{
32 Name: "postgres", Address: "127.0.0.1:5432", Protocol: domain.EntryPointProtocolTCP,32 Name: "postgres", Address: "127.0.0.1:5432", Protocol: domain.EntryPointProtocolTCP,
33 Active: true, ActiveTCPConnections: 1, TotalAccepted: 2, BytesIn: 10, BytesOut: 20,33 Active: true, ActiveTCPConnections: 1, TotalAccepted: 2, BytesIn: 10, BytesOut: 20,
34+ SmartTCP: dto.SmartTCPCounters{HTTPAccepted: 1, PROXYRefused: 1},
34 }},35 }},
35 Routers: []dto.TrafficRouterStatus{{36 Routers: []dto.TrafficRouterStatus{{
36 Name: "pg-router", EntryPoint: "postgres", Protocol: domain.RouterProtocolTCP,37 Name: "pg-router", EntryPoint: "postgres", Protocol: domain.RouterProtocolTCP,
@@ -40,7 +41,7 @@ func TestTrafficStatusHumanOutput(t *testing.T) {
40 Name: "network_service:postgres:db", Active: true,41 Name: "network_service:postgres:db", Active: true,
41 Backends: []dto.TrafficBackendStatus{{Name: "postgres:db", Host: "127.0.0.1", Port: 5432, Protocol: domain.NetworkProtocolTCP, Active: true}},42 Backends: []dto.TrafficBackendStatus{{Name: "postgres:db", Host: "127.0.0.1", Port: 5432, Protocol: domain.NetworkProtocolTCP, Active: true}},
42 }},43 }},
43- Counters: dto.TrafficCounters{ActiveTCPConnections: 1, TotalAccepted: 2, BytesIn: 10, BytesOut: 20},44+ Counters: dto.TrafficCounters{ActiveTCPConnections: 1, TotalAccepted: 2, BytesIn: 10, BytesOut: 20, SmartTCP: dto.SmartTCPCounters{HTTPAccepted: 1, PROXYRefused: 1}},
44 }45 }
45 var buf bytes.Buffer46 var buf bytes.Buffer
46 require.NoError(t, renderTrafficStatus(&buf, status, false))47 require.NoError(t, renderTrafficStatus(&buf, status, false))
@@ -52,14 +53,18 @@ func TestTrafficStatusHumanOutput(t *testing.T) {
52 assert.Contains(t, output, "network_service:postgres:db")53 assert.Contains(t, output, "network_service:postgres:db")
53 assert.Contains(t, output, "tcp://127.0.0.1:5432")54 assert.Contains(t, output, "tcp://127.0.0.1:5432")
54 assert.Contains(t, output, "accepted=2")55 assert.Contains(t, output, "accepted=2")
56+ assert.Contains(t, output, "smart_tcp")
57+ assert.Contains(t, output, "http_accepted=1")
58+ assert.Contains(t, output, "proxy_refused=1")
55 }59 }
56 60
57 func TestTrafficStatusJSONOutput(t *testing.T) {61 func TestTrafficStatusJSONOutput(t *testing.T) {
58- status := &dto.TrafficStatusResponse{LastReloadStatus: "ok", Counters: dto.TrafficCounters{ActiveUDPSessions: 3}}62+ status := &dto.TrafficStatusResponse{LastReloadStatus: "ok", Counters: dto.TrafficCounters{ActiveUDPSessions: 3, SmartTCP: dto.SmartTCPCounters{SniffTimeout: 1}}}
59 var buf bytes.Buffer63 var buf bytes.Buffer
60 require.NoError(t, renderTrafficStatus(&buf, status, true))64 require.NoError(t, renderTrafficStatus(&buf, status, true))
61 var got dto.TrafficStatusResponse65 var got dto.TrafficStatusResponse
62 require.NoError(t, json.Unmarshal(buf.Bytes(), &got))66 require.NoError(t, json.Unmarshal(buf.Bytes(), &got))
63 assert.Equal(t, "ok", got.LastReloadStatus)67 assert.Equal(t, "ok", got.LastReloadStatus)
64 assert.Equal(t, int64(3), got.Counters.ActiveUDPSessions)68 assert.Equal(t, int64(3), got.Counters.ActiveUDPSessions)
69+ assert.Equal(t, int64(1), got.Counters.SmartTCP.SniffTimeout)
65 }70 }
M internal/adapters/in/http/admin/handler_traffic_test.go +6 -3
@@ -18,10 +18,11 @@ func TestHandler_TrafficStatus(t *testing.T) {
1818 trafficSvc.EXPECT().Status().Return(domain.TrafficStatus{
1919 LastReloadStatus: "ok",
2020 EntryPoints: []domain.EntryPointStatus{{
21- Name: "postgres", Address: "127.0.0.1:5432", Protocol: domain.EntryPointProtocolTCP,
21+ Name: "edge", Address: "127.0.0.1:8443", Protocol: domain.EntryPointProtocolSmartTCP,
2222 Active: true, ActiveTCPConnections: 2, TotalAccepted: 3, BytesIn: 11, BytesOut: 22,
23+ SmartTCP: domain.SmartTCPCounters{HTTPAccepted: 1, PROXYRefused: 1},
2324 }},
24- Counters: domain.TrafficCounters{ActiveTCPConnections: 2, TotalAccepted: 3, BytesIn: 11, BytesOut: 22},
25+ Counters: domain.TrafficCounters{ActiveTCPConnections: 2, TotalAccepted: 3, BytesIn: 11, BytesOut: 22, SmartTCP: domain.SmartTCPCounters{HTTPAccepted: 1, PROXYRefused: 1}},
2526 })
2627 handler := newTestHandler(t, func(d *HandlerDeps) {
2728 d.TrafficSvc = trafficSvc
@@ -37,9 +38,11 @@ func TestHandler_TrafficStatus(t *testing.T) {
3738 require.NoError(t, json.NewDecoder(resp.Body).Decode(&body))
3839 assert.Equal(t, "ok", body.LastReloadStatus)
3940 require.Len(t, body.EntryPoints, 1)
40- assert.Equal(t, "postgres", body.EntryPoints[0].Name)
41+ assert.Equal(t, "edge", body.EntryPoints[0].Name)
4142 assert.Equal(t, int64(2), body.Counters.ActiveTCPConnections)
4243 assert.Equal(t, int64(22), body.Counters.BytesOut)
44+ assert.Equal(t, int64(1), body.EntryPoints[0].SmartTCP.HTTPAccepted)
45+ assert.Equal(t, int64(1), body.Counters.SmartTCP.PROXYRefused)
4346 }
4447
4548 func TestHandler_TrafficStatusRequiresStatusRead(t *testing.T) {
@@ -18,10 +18,11 @@ func TestHandler_TrafficStatus(t *testing.T) {
18 trafficSvc.EXPECT().Status().Return(domain.TrafficStatus{18 trafficSvc.EXPECT().Status().Return(domain.TrafficStatus{
19 LastReloadStatus: "ok",19 LastReloadStatus: "ok",
20 EntryPoints: []domain.EntryPointStatus{{20 EntryPoints: []domain.EntryPointStatus{{
21- Name: "postgres", Address: "127.0.0.1:5432", Protocol: domain.EntryPointProtocolTCP,21+ Name: "edge", Address: "127.0.0.1:8443", Protocol: domain.EntryPointProtocolSmartTCP,
22 Active: true, ActiveTCPConnections: 2, TotalAccepted: 3, BytesIn: 11, BytesOut: 22,22 Active: true, ActiveTCPConnections: 2, TotalAccepted: 3, BytesIn: 11, BytesOut: 22,
23+ SmartTCP: domain.SmartTCPCounters{HTTPAccepted: 1, PROXYRefused: 1},
23 }},24 }},
24- Counters: domain.TrafficCounters{ActiveTCPConnections: 2, TotalAccepted: 3, BytesIn: 11, BytesOut: 22},25+ Counters: domain.TrafficCounters{ActiveTCPConnections: 2, TotalAccepted: 3, BytesIn: 11, BytesOut: 22, SmartTCP: domain.SmartTCPCounters{HTTPAccepted: 1, PROXYRefused: 1}},
25 })26 })
26 handler := newTestHandler(t, func(d *HandlerDeps) {27 handler := newTestHandler(t, func(d *HandlerDeps) {
27 d.TrafficSvc = trafficSvc28 d.TrafficSvc = trafficSvc
@@ -37,9 +38,11 @@ func TestHandler_TrafficStatus(t *testing.T) {
37 require.NoError(t, json.NewDecoder(resp.Body).Decode(&body))38 require.NoError(t, json.NewDecoder(resp.Body).Decode(&body))
38 assert.Equal(t, "ok", body.LastReloadStatus)39 assert.Equal(t, "ok", body.LastReloadStatus)
39 require.Len(t, body.EntryPoints, 1)40 require.Len(t, body.EntryPoints, 1)
40- assert.Equal(t, "postgres", body.EntryPoints[0].Name)41+ assert.Equal(t, "edge", body.EntryPoints[0].Name)
41 assert.Equal(t, int64(2), body.Counters.ActiveTCPConnections)42 assert.Equal(t, int64(2), body.Counters.ActiveTCPConnections)
42 assert.Equal(t, int64(22), body.Counters.BytesOut)43 assert.Equal(t, int64(22), body.Counters.BytesOut)
44+ assert.Equal(t, int64(1), body.EntryPoints[0].SmartTCP.HTTPAccepted)
45+ assert.Equal(t, int64(1), body.Counters.SmartTCP.PROXYRefused)
43 }46 }
44 47
45 func TestHandler_TrafficStatusRequiresStatusRead(t *testing.T) {48 func TestHandler_TrafficStatusRequiresStatusRead(t *testing.T) {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close