From 90673c35c2e1f55fe179a6da33313729b7c492e3 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Thu, 10 Oct 2024 16:00:11 -0400 Subject: [PATCH 01/16] feat(manager): move and update metrics cards in the server view --- server_manager/index.html | 4 + server_manager/www/ui_components/app-root.ts | 2 +- .../www/ui_components/outline-server-view.ts | 109 ++++++++++++------ 3 files changed, 78 insertions(+), 37 deletions(-) diff --git a/server_manager/index.html b/server_manager/index.html index 943ce3c6bc..2d1b35b8f5 100644 --- a/server_manager/index.html +++ b/server_manager/index.html @@ -27,6 +27,10 @@ http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline' outline: data:; connect-src https: 'self'; frame-src https://s3.amazonaws.com/outline-vpn/ ss:" /> + + + + Outline Manager diff --git a/server_manager/www/ui_components/app-root.ts b/server_manager/www/ui_components/app-root.ts index b72549c3f1..45fe2ee024 100644 --- a/server_manager/www/ui_components/app-root.ts +++ b/server_manager/www/ui_components/app-root.ts @@ -736,7 +736,7 @@ export class AppRoot extends polymerElementWithLocalize { type: Object, value: { contactView: true, - serverMetricsTab: false, + serverMetricsTab: true, }, }, }; diff --git a/server_manager/www/ui_components/outline-server-view.ts b/server_manager/www/ui_components/outline-server-view.ts index 99af7b1ea0..95e1da2976 100644 --- a/server_manager/www/ui_components/outline-server-view.ts +++ b/server_manager/www/ui_components/outline-server-view.ts @@ -33,6 +33,8 @@ import './outline-server-progress-step'; import './outline-server-settings'; import './outline-share-dialog'; import './outline-sort-span'; +import '../views/server_view/server_stat_grid'; +import '../views/server_view/server_stat_card'; import {html, PolymerElement} from '@polymer/polymer'; import type {PolymerElementProperties} from '@polymer/polymer/interfaces'; import type {DomRepeat} from '@polymer/polymer/lib/elements/dom-repeat'; @@ -394,6 +396,10 @@ export class ServerView extends DirMixin(PolymerElement) { .flex-1 { flex: 1; } + + :host { + --server-stat-card-background: var(--background-contrast-color); + } /* Mirror icons */ :host(:dir(rtl)) iron-icon, :host(:dir(rtl)) .share-button, @@ -554,45 +560,49 @@ export class ServerView extends DirMixin(PolymerElement) { on-selected-changed="_selectedTabChanged" >
-
-
- -
-

- [[_formatInboundBytesValue(totalInboundBytes, language)]] -

-

[[_formatInboundBytesUnit(totalInboundBytes, language)]]

-
-

[[localize('server-data-transfer')]]

-
-
-
- +
@@ -727,7 +737,13 @@ export class ServerView extends DirMixin(PolymerElement) {
key.id === id); } + _computeServerMetrics() { + return [ + { + icon: 'devices', + name: 'Devices used in the last 30 days', + value: 83.7, + }, + { + icon: 'timer', + name: 'User hours spent on the VPN in the last 30 days', + value: 12.3, + }, + { + icon: 'swap_horiz', + name: 'Data transferred in the last 30 days', + units: 'GB', + value: 2345, + }, + ]; + } + _closeAddAccessKeyHelpBubble() { (this.$.addAccessKeyHelpBubble as OutlineHelpBubble).hide(); } From 51b17e922966996ec0400752d191c14dc2aedfd6 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:01:23 -0400 Subject: [PATCH 02/16] getting close. trying to figure out this weird data model --- server_manager/images/Material-Icons.woff2 | Bin 0 -> 128616 bytes server_manager/index.html | 11 ++++-- server_manager/model/server.ts | 12 +++++++ server_manager/www/app.ts | 33 ++++++++++++++++++ server_manager/www/shadowbox_server.ts | 22 ++++++++++++ server_manager/www/testing/models.ts | 3 ++ .../www/ui_components/outline-server-view.ts | 23 +++++++++--- 7 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 server_manager/images/Material-Icons.woff2 diff --git a/server_manager/images/Material-Icons.woff2 b/server_manager/images/Material-Icons.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..f1fd22ff1c117e187f088de6746eb1f82187a992 GIT binary patch literal 128616 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�{V5Ux10YTPcjn|+#u(mL`-~}?0-nmK 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�TBx-D<>G7m^i?qG-6W%>!-QfH!oA6h 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 Nw1oHH?|-Rs0009$rq=)f literal 0 HcmV?d00001 diff --git a/server_manager/index.html b/server_manager/index.html index 2d1b35b8f5..06b3b18456 100644 --- a/server_manager/index.html +++ b/server_manager/index.html @@ -28,8 +28,15 @@ content="default-src 'self' 'unsafe-inline' outline: data:; connect-src https: 'self'; frame-src https://s3.amazonaws.com/outline-vpn/ ss:" /> - - + Outline Manager diff --git a/server_manager/model/server.ts b/server_manager/model/server.ts index 040908080f..381649f61a 100644 --- a/server_manager/model/server.ts +++ b/server_manager/model/server.ts @@ -39,6 +39,9 @@ export interface Server { // Returns stats for bytes transferred across all access keys of this server. getDataUsage(): Promise; + // Returns tunnel time by location + getTunnelTimeByLocation(): Promise; + // Adds a new access key to this server. addAccessKey(): Promise; @@ -193,3 +196,12 @@ export type BytesByAccessKey = Map; export interface DataLimit { readonly bytes: number; } + +export type TunnelTimeSecondsByLocation = { + location: string; + asn: number; + asorg: string; + tunnel_time: { + seconds: number; + }; +}[]; diff --git a/server_manager/www/app.ts b/server_manager/www/app.ts index a5e90a0225..18d9902588 100644 --- a/server_manager/www/app.ts +++ b/server_manager/www/app.ts @@ -971,6 +971,7 @@ export class App { this.appRoot.showError(this.appRoot.localize('error-keys-get')); } this.showTransferStats(server, view); + this.showTunnelTimeStats(server, view); }, 0); } @@ -1074,6 +1075,21 @@ export class App { } } + private async refreshTunnelTimeStats( + selectedServer: server_model.Server, + serverView: ServerView + ) { + const tunnelTimeByLocation = await selectedServer.getTunnelTimeByLocation(); + + serverView.totalUserHours = tunnelTimeByLocation.reduce( + (sum, {tunnel_time: {seconds}}) => sum + seconds / (60 * 60), + 0 + ); + serverView.totalDevices = serverView.totalUserHours / (30 * 24); + + console.log(serverView); + } + private showTransferStats( selectedServer: server_model.Server, serverView: ServerView @@ -1091,6 +1107,23 @@ export class App { }, statsRefreshRateMs); } + private showTunnelTimeStats( + selectedServer: server_model.Server, + serverView: ServerView + ) { + this.refreshTunnelTimeStats(selectedServer, serverView); + // Get transfer stats once per minute for as long as server is selected. + const statsRefreshRateMs = 60 * 1000; + const intervalId = setInterval(() => { + if (this.selectedServer !== selectedServer) { + // Server is no longer running, stop interval + clearInterval(intervalId); + return; + } + this.refreshTunnelTimeStats(selectedServer, serverView); + }, statsRefreshRateMs); + } + // Converts the access key model to the format used by outline-server-view. private convertToUiAccessKey( remoteAccessKey: server_model.AccessKey diff --git a/server_manager/www/shadowbox_server.ts b/server_manager/www/shadowbox_server.ts index cdc969ab92..47a65c1064 100644 --- a/server_manager/www/shadowbox_server.ts +++ b/server_manager/www/shadowbox_server.ts @@ -161,6 +161,28 @@ export class ShadowboxServer implements server.Server { return usageMap; } + async getTunnelTimeByLocation(): Promise { + //TODO + return [ + { + location: 'CA', + asn: 1, + asorg: 'IDK', + tunnel_time: { + seconds: 10000, + }, + }, + { + location: 'US', + asn: 2, + asorg: 'WHATEVER', + tunnel_time: { + seconds: 200000, + }, + }, + ]; + } + getName(): string { return this.serverConfig?.name; } diff --git a/server_manager/www/testing/models.ts b/server_manager/www/testing/models.ts index 95db487b12..b29513d480 100644 --- a/server_manager/www/testing/models.ts +++ b/server_manager/www/testing/models.ts @@ -168,6 +168,9 @@ export class FakeServer implements server.Server { getDataUsage() { return Promise.resolve(new Map()); } + getTunnelTimeByLocation() { + return Promise.resolve([]); + } addAccessKey() { const accessKey = { id: Math.floor(Math.random()).toString(), diff --git a/server_manager/www/ui_components/outline-server-view.ts b/server_manager/www/ui_components/outline-server-view.ts index 95e1da2976..18c26db0e7 100644 --- a/server_manager/www/ui_components/outline-server-view.ts +++ b/server_manager/www/ui_components/outline-server-view.ts @@ -397,6 +397,10 @@ export class ServerView extends DirMixin(PolymerElement) { flex: 1; } + div[name='metrics'] { + margin-top: 15px; + } + :host { --server-stat-card-background: var(--background-contrast-color); } @@ -800,6 +804,8 @@ export class ServerView extends DirMixin(PolymerElement) { isServerReachable: Boolean, retryDisplayingServer: Function, totalInboundBytes: Number, + totalUserHours: Number, + totalDevices: Number, baselineDataTransfer: Number, accessKeyRows: Array, hasNonAdminAccessKeys: Boolean, @@ -845,6 +851,8 @@ export class ServerView extends DirMixin(PolymerElement) { /** Callback for retrying to display an unreachable server. */ retryDisplayingServer: () => void = null; totalInboundBytes = 0; + totalUserHours = 0; + totalDevices = 0; /** The number to which access key transfer amounts are compared for progress bar display */ baselineDataTransfer = Number.POSITIVE_INFINITY; accessKeyRows: DisplayAccessKey[] = []; @@ -943,18 +951,25 @@ export class ServerView extends DirMixin(PolymerElement) { { icon: 'devices', name: 'Devices used in the last 30 days', - value: 83.7, + value: this.totalDevices.toFixed(2), }, { icon: 'timer', name: 'User hours spent on the VPN in the last 30 days', - value: 12.3, + units: 'hours', + value: this.totalUserHours.toFixed(2), }, { icon: 'swap_horiz', name: 'Data transferred in the last 30 days', - units: 'GB', - value: 2345, + units: this._formatInboundBytesUnit( + this.totalInboundBytes, + this.language + ), + value: this._formatInboundBytesValue( + this.totalInboundBytes, + this.language + ), }, ]; } From 4b51e45ed5b8ee6a65bd79543ecbfb373dd5ec65 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:12:44 -0400 Subject: [PATCH 03/16] style update --- server_manager/www/ui_components/outline-server-view.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server_manager/www/ui_components/outline-server-view.ts b/server_manager/www/ui_components/outline-server-view.ts index 18c26db0e7..0a83d686e1 100644 --- a/server_manager/www/ui_components/outline-server-view.ts +++ b/server_manager/www/ui_components/outline-server-view.ts @@ -403,6 +403,8 @@ export class ServerView extends DirMixin(PolymerElement) { :host { --server-stat-card-background: var(--background-contrast-color); + --server-stat-card-foreground: var(--medium-gray); + --server-stat-card-highlight: var(--light-gray); } /* Mirror icons */ :host(:dir(rtl)) iron-icon, From 8d5d9a5b937cb91521db2dab5b03c61732e882c1 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:18:59 -0400 Subject: [PATCH 04/16] don't use reduce lol --- server_manager/www/app.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/server_manager/www/app.ts b/server_manager/www/app.ts index 18d9902588..f834b708fa 100644 --- a/server_manager/www/app.ts +++ b/server_manager/www/app.ts @@ -1081,13 +1081,15 @@ export class App { ) { const tunnelTimeByLocation = await selectedServer.getTunnelTimeByLocation(); - serverView.totalUserHours = tunnelTimeByLocation.reduce( - (sum, {tunnel_time: {seconds}}) => sum + seconds / (60 * 60), - 0 - ); - serverView.totalDevices = serverView.totalUserHours / (30 * 24); + let sum = 0; + for (const { + tunnel_time: {seconds}, + } of tunnelTimeByLocation) { + sum += seconds / (60 * 60); + } - console.log(serverView); + serverView.totalUserHours = sum; + serverView.totalDevices = serverView.totalUserHours / (30 * 24); } private showTransferStats( From 80af4c7939d2954e84b2ecdceb03f35e4062a092 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:53:09 -0400 Subject: [PATCH 05/16] okay it roughly works end to end --- .../www/ui_components/outline-server-view.ts | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/server_manager/www/ui_components/outline-server-view.ts b/server_manager/www/ui_components/outline-server-view.ts index 0a83d686e1..efd5783375 100644 --- a/server_manager/www/ui_components/outline-server-view.ts +++ b/server_manager/www/ui_components/outline-server-view.ts @@ -747,7 +747,7 @@ export class ServerView extends DirMixin(PolymerElement) {
@@ -821,6 +821,10 @@ export class ServerView extends DirMixin(PolymerElement) { selectedPage: String, selectedTab: String, featureFlags: Object, + serverMetrics: { + type: Array, + computed: '_computeServerMetrics(totalDevices, totalUserHours, totalInboundBytes, language)', + }, }; } @@ -948,30 +952,29 @@ export class ServerView extends DirMixin(PolymerElement) { return this.accessKeyRows.find(key => key.id === id); } - _computeServerMetrics() { + _computeServerMetrics( + totalDevices: number, + totalUserHours: number, + totalInboundBytes: number, + language: string + ) { return [ { icon: 'devices', name: 'Devices used in the last 30 days', - value: this.totalDevices.toFixed(2), + value: totalDevices.toFixed(2), }, { icon: 'timer', name: 'User hours spent on the VPN in the last 30 days', units: 'hours', - value: this.totalUserHours.toFixed(2), + value: totalUserHours.toFixed(2), }, { icon: 'swap_horiz', name: 'Data transferred in the last 30 days', - units: this._formatInboundBytesUnit( - this.totalInboundBytes, - this.language - ), - value: this._formatInboundBytesValue( - this.totalInboundBytes, - this.language - ), + units: this._formatInboundBytesUnit(totalInboundBytes, language), + value: this._formatInboundBytesValue(totalInboundBytes, language), }, ]; } From f30ccc7e538e0f95e9e592c84b0dc4224195d1eb Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:16:10 -0400 Subject: [PATCH 06/16] add metrics messages --- server_manager/messages/master_messages.json | 16 ++++++++++++++++ server_manager/www/ui_components/app-root.ts | 2 +- .../www/ui_components/outline-server-view.ts | 11 ++++++----- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/server_manager/messages/master_messages.json b/server_manager/messages/master_messages.json index 18d6a6b10c..db1386ade8 100644 --- a/server_manager/messages/master_messages.json +++ b/server_manager/messages/master_messages.json @@ -1099,6 +1099,22 @@ "message": "Metrics", "description": "This string appears within the server view as a header of the section that displays server metrics." }, + "server_metrics_data_transferred": { + "message": "Data transferred in the last 30 days", + "description": "This string indicates to the user that the metric displayed counts how much data was sent through the server over the last 30 days" + }, + "server_metrics_user_hours": { + "message": "User hours spent on the VPN in the last 30 days", + "description": "This string indicates to the user that the metric displayed counts how many hours users used the VPN over the last 30 days." + }, + "server_metrics_user_hours_unit": { + "message": "hours", + "description": "This string indicates to the user that the metric displayed is in hours." + }, + "server_metrics_average_devices": { + "message": "Average number of devices used in the last 30 days", + "description": "This string indicates to the user that the metric displayed corresponds to the average number of devices that used the VPN over the last 30 days." + }, "server_my_access_key": { "message": "My access key", "description": "This string appears within the server view as the header for the default server access key. This key is meant to be used by the server administrator." diff --git a/server_manager/www/ui_components/app-root.ts b/server_manager/www/ui_components/app-root.ts index 45fe2ee024..b72549c3f1 100644 --- a/server_manager/www/ui_components/app-root.ts +++ b/server_manager/www/ui_components/app-root.ts @@ -736,7 +736,7 @@ export class AppRoot extends polymerElementWithLocalize { type: Object, value: { contactView: true, - serverMetricsTab: true, + serverMetricsTab: false, }, }, }; diff --git a/server_manager/www/ui_components/outline-server-view.ts b/server_manager/www/ui_components/outline-server-view.ts index efd5783375..0fbd1118ef 100644 --- a/server_manager/www/ui_components/outline-server-view.ts +++ b/server_manager/www/ui_components/outline-server-view.ts @@ -823,7 +823,8 @@ export class ServerView extends DirMixin(PolymerElement) { featureFlags: Object, serverMetrics: { type: Array, - computed: '_computeServerMetrics(totalDevices, totalUserHours, totalInboundBytes, language)', + computed: + '_computeServerMetrics(totalDevices, totalUserHours, totalInboundBytes, language)', }, }; } @@ -961,18 +962,18 @@ export class ServerView extends DirMixin(PolymerElement) { return [ { icon: 'devices', - name: 'Devices used in the last 30 days', + name: this.localize('server-metrics-average-devices'), value: totalDevices.toFixed(2), }, { icon: 'timer', - name: 'User hours spent on the VPN in the last 30 days', - units: 'hours', + name: this.localize('server-metrics-user-hours'), + units: this.localize('server-metrics-user-hours-unit'), value: totalUserHours.toFixed(2), }, { icon: 'swap_horiz', - name: 'Data transferred in the last 30 days', + name: this.localize('server-metrics-data-transferred'), units: this._formatInboundBytesUnit(totalInboundBytes, language), value: this._formatInboundBytesValue(totalInboundBytes, language), }, From ee8c388eeaa4d0e138320c7a3d986834c79c5ec0 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:27:46 -0400 Subject: [PATCH 07/16] access key tab --- server_manager/messages/master_messages.json | 10 ++++++++++ .../www/ui_components/outline-server-view.ts | 11 ++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/server_manager/messages/master_messages.json b/server_manager/messages/master_messages.json index db1386ade8..729b23474e 100644 --- a/server_manager/messages/master_messages.json +++ b/server_manager/messages/master_messages.json @@ -1051,6 +1051,16 @@ "message": "Access keys", "description": "This string appears within the server view as a header of a table column that displays server access keys." }, + "server_access_keys_tab": { + "message": "Access keys ($KEY_COUNT$)", + "description": "This string is a tab header indicating to the user that they're currently managing their access keys.", + "placeholders": { + "KEY_COUNT": { + "content": "{keyCount}", + "example": "12" + } + } + }, "server_connections": { "message": "Connections", "description": "This string appears within the server view as a header of the section that displays server information and access keys." diff --git a/server_manager/www/ui_components/outline-server-view.ts b/server_manager/www/ui_components/outline-server-view.ts index 0fbd1118ef..935862475d 100644 --- a/server_manager/www/ui_components/outline-server-view.ts +++ b/server_manager/www/ui_components/outline-server-view.ts @@ -549,10 +549,15 @@ export class ServerView extends DirMixin(PolymerElement) { attr-for-selected="name" noink="" > - [[localize('server-connections')]] + Date: Tue, 12 Nov 2024 11:28:52 -0500 Subject: [PATCH 08/16] update to use new "endpoint" - feedback next --- server_manager/model/server.ts | 34 +++++++++----- server_manager/www/app.ts | 6 +-- server_manager/www/shadowbox_server.ts | 62 +++++++++++++++++++------- server_manager/www/testing/models.ts | 29 +++++++++++- 4 files changed, 99 insertions(+), 32 deletions(-) diff --git a/server_manager/model/server.ts b/server_manager/model/server.ts index 381649f61a..49edaa5af3 100644 --- a/server_manager/model/server.ts +++ b/server_manager/model/server.ts @@ -39,8 +39,8 @@ export interface Server { // Returns stats for bytes transferred across all access keys of this server. getDataUsage(): Promise; - // Returns tunnel time by location - getTunnelTimeByLocation(): Promise; + // Returns server metrics + getServerMetrics(): Promise; // Adds a new access key to this server. addAccessKey(): Promise; @@ -197,11 +197,25 @@ export interface DataLimit { readonly bytes: number; } -export type TunnelTimeSecondsByLocation = { - location: string; - asn: number; - asorg: string; - tunnel_time: { - seconds: number; - }; -}[]; +export type ServerMetricsJson = { + servers: { + location: string; + asn: number; + asOrg: string; + tunnelTime: { + seconds: number; + }; + dataTransferred: { + bytes: number; + }; + }[]; + accessKeys: { + accessKeyId: number; + tunnelTime: { + seconds: number; + }; + dataTransferred: { + bytes: number; + }; + }[]; +}; diff --git a/server_manager/www/app.ts b/server_manager/www/app.ts index f834b708fa..7c71925a1e 100644 --- a/server_manager/www/app.ts +++ b/server_manager/www/app.ts @@ -1079,12 +1079,12 @@ export class App { selectedServer: server_model.Server, serverView: ServerView ) { - const tunnelTimeByLocation = await selectedServer.getTunnelTimeByLocation(); + const serverMetrics = await selectedServer.getServerMetrics(); let sum = 0; for (const { - tunnel_time: {seconds}, - } of tunnelTimeByLocation) { + tunnelTime: {seconds}, + } of serverMetrics.servers) { sum += seconds / (60 * 60); } diff --git a/server_manager/www/shadowbox_server.ts b/server_manager/www/shadowbox_server.ts index 47a65c1064..7fd391ca56 100644 --- a/server_manager/www/shadowbox_server.ts +++ b/server_manager/www/shadowbox_server.ts @@ -161,26 +161,54 @@ export class ShadowboxServer implements server.Server { return usageMap; } - async getTunnelTimeByLocation(): Promise { + async getServerMetrics(): Promise { //TODO - return [ - { - location: 'CA', - asn: 1, - asorg: 'IDK', - tunnel_time: { - seconds: 10000, + return { + servers: [ + { + location: 'CA', + asn: 1, + asOrg: 'IDK', + tunnelTime: { + seconds: 10000, + }, + dataTransferred: { + bytes: 10000, + }, }, - }, - { - location: 'US', - asn: 2, - asorg: 'WHATEVER', - tunnel_time: { - seconds: 200000, + { + location: 'US', + asn: 2, + asOrg: 'WHATEVER', + tunnelTime: { + seconds: 200000, + }, + dataTransferred: { + bytes: 200000, + }, }, - }, - ]; + ], + accessKeys: [ + { + accessKeyId: 0, + tunnelTime: { + seconds: 10000, + }, + dataTransferred: { + bytes: 10000, + }, + }, + { + accessKeyId: 1, + tunnelTime: { + seconds: 200000, + }, + dataTransferred: { + bytes: 200000, + }, + }, + ], + }; } getName(): string { diff --git a/server_manager/www/testing/models.ts b/server_manager/www/testing/models.ts index b29513d480..b47ecfc692 100644 --- a/server_manager/www/testing/models.ts +++ b/server_manager/www/testing/models.ts @@ -168,8 +168,33 @@ export class FakeServer implements server.Server { getDataUsage() { return Promise.resolve(new Map()); } - getTunnelTimeByLocation() { - return Promise.resolve([]); + getServerMetrics() { + return Promise.resolve({ + servers: [ + { + location: '', + asn: 0, + asOrg: '', + tunnelTime: { + seconds: 0, + }, + dataTransferred: { + bytes: 0, + }, + }, + ], + accessKeys: [ + { + accessKeyId: 0, + tunnelTime: { + seconds: 0, + }, + dataTransferred: { + bytes: 0, + }, + }, + ], + }); } addAccessKey() { const accessKey = { From 2a6076dae22f099b722593b2a7b8f17a0fe71d17 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Tue, 12 Nov 2024 13:42:19 -0500 Subject: [PATCH 09/16] feedback --- server_manager/model/server.ts | 5 -- server_manager/www/app.ts | 99 ++++++++++++-------------- server_manager/www/shadowbox_server.ts | 27 +------ 3 files changed, 46 insertions(+), 85 deletions(-) diff --git a/server_manager/model/server.ts b/server_manager/model/server.ts index 49edaa5af3..aab5edb1c6 100644 --- a/server_manager/model/server.ts +++ b/server_manager/model/server.ts @@ -36,9 +36,6 @@ export interface Server { // Lists the access keys for this server, including the admin. listAccessKeys(): Promise; - // Returns stats for bytes transferred across all access keys of this server. - getDataUsage(): Promise; - // Returns server metrics getServerMetrics(): Promise; @@ -189,8 +186,6 @@ export interface AccessKey { dataLimit?: DataLimit; } -export type BytesByAccessKey = Map; - // Data transfer allowance, measured in bytes. // NOTE: Must be kept in sync with the definition in src/shadowbox/access_key.ts. export interface DataLimit { diff --git a/server_manager/www/app.ts b/server_manager/www/app.ts index 7c71925a1e..8a16f34781 100644 --- a/server_manager/www/app.ts +++ b/server_manager/www/app.ts @@ -970,8 +970,7 @@ export class App { console.error(`Failed to load access keys: ${error}`); this.appRoot.showError(this.appRoot.localize('error-keys-get')); } - this.showTransferStats(server, view); - this.showTunnelTimeStats(server, view); + this.showServerMetrics(server, view); }, 0); } @@ -1036,30 +1035,56 @@ export class App { } } - private async refreshTransferStats( + private async refreshServerMetrics( selectedServer: server_model.Server, serverView: ServerView ) { try { - const usageMap = await selectedServer.getDataUsage(); - const keyTransfers = [...usageMap.values()]; + const serverMetrics = await selectedServer.getServerMetrics(); + + let totalUserHours = 0; + for (const { + tunnelTime: {seconds}, + } of serverMetrics.servers) { + // convert to hours + totalUserHours += seconds / (60 * 60); + } + + serverView.totalUserHours = totalUserHours; + serverView.totalDevices = serverView.totalUserHours / (30 * 24); + let totalInboundBytes = 0; - for (const accessKeyBytes of keyTransfers) { - totalInboundBytes += accessKeyBytes; + for (const { + dataTransferred: {bytes}, + } of serverMetrics.accessKeys) { + totalInboundBytes += bytes; } + serverView.totalInboundBytes = totalInboundBytes; // Update all the displayed access keys, even if usage didn't change, in case data limits did. + const keyDataTransferMap = serverMetrics.accessKeys.reduce( + (map, {accessKeyId, dataTransferred}) => { + map.set(String(accessKeyId), dataTransferred.bytes); + return map; + }, + new Map() + ); + let keyTransferMax = 0; let dataLimitMax = selectedServer.getDefaultDataLimit()?.bytes ?? 0; - for (const key of await selectedServer.listAccessKeys()) { - serverView.updateAccessKeyRow(key.id, { - transferredBytes: usageMap.get(key.id) ?? 0, - dataLimitBytes: key.dataLimit?.bytes, + for (const accessKey of await selectedServer.listAccessKeys()) { + serverView.updateAccessKeyRow(accessKey.id, { + transferredBytes: keyDataTransferMap.get(accessKey.id) ?? 0, + dataLimitBytes: accessKey.dataLimit?.bytes, }); - keyTransferMax = Math.max(keyTransferMax, usageMap.get(key.id) ?? 0); - dataLimitMax = Math.max(dataLimitMax, key.dataLimit?.bytes ?? 0); + keyTransferMax = Math.max( + keyTransferMax, + keyDataTransferMap.get(accessKey.id) ?? 0 + ); + dataLimitMax = Math.max(dataLimitMax, accessKey.dataLimit?.bytes ?? 0); } + serverView.baselineDataTransfer = Math.max(keyTransferMax, dataLimitMax); } catch (e) { // Since failures are invisible to users we generally want exceptions here to bubble @@ -1075,45 +1100,11 @@ export class App { } } - private async refreshTunnelTimeStats( - selectedServer: server_model.Server, - serverView: ServerView - ) { - const serverMetrics = await selectedServer.getServerMetrics(); - - let sum = 0; - for (const { - tunnelTime: {seconds}, - } of serverMetrics.servers) { - sum += seconds / (60 * 60); - } - - serverView.totalUserHours = sum; - serverView.totalDevices = serverView.totalUserHours / (30 * 24); - } - - private showTransferStats( - selectedServer: server_model.Server, - serverView: ServerView - ) { - this.refreshTransferStats(selectedServer, serverView); - // Get transfer stats once per minute for as long as server is selected. - const statsRefreshRateMs = 60 * 1000; - const intervalId = setInterval(() => { - if (this.selectedServer !== selectedServer) { - // Server is no longer running, stop interval - clearInterval(intervalId); - return; - } - this.refreshTransferStats(selectedServer, serverView); - }, statsRefreshRateMs); - } - - private showTunnelTimeStats( + private showServerMetrics( selectedServer: server_model.Server, serverView: ServerView ) { - this.refreshTunnelTimeStats(selectedServer, serverView); + this.refreshServerMetrics(selectedServer, serverView); // Get transfer stats once per minute for as long as server is selected. const statsRefreshRateMs = 60 * 1000; const intervalId = setInterval(() => { @@ -1122,7 +1113,7 @@ export class App { clearInterval(intervalId); return; } - this.refreshTunnelTimeStats(selectedServer, serverView); + this.refreshServerMetrics(selectedServer, serverView); }, statsRefreshRateMs); } @@ -1193,7 +1184,7 @@ export class App { this.appRoot.showNotification(this.appRoot.localize('saved')); serverView.defaultDataLimitBytes = limit?.bytes; serverView.isDefaultDataLimitEnabled = true; - this.refreshTransferStats(this.selectedServer, serverView); + this.refreshServerMetrics(this.selectedServer, serverView); // Don't display the feature collection disclaimer anymore. serverView.showFeatureMetricsDisclaimer = false; window.localStorage.setItem( @@ -1219,7 +1210,7 @@ export class App { await this.selectedServer.removeDefaultDataLimit(); serverView.isDefaultDataLimitEnabled = false; this.appRoot.showNotification(this.appRoot.localize('saved')); - this.refreshTransferStats(this.selectedServer, serverView); + this.refreshServerMetrics(this.selectedServer, serverView); } catch (error) { console.error(`Failed to remove server default data limit: ${error}`); this.appRoot.showError(this.appRoot.localize('error-remove-data-limit')); @@ -1267,7 +1258,7 @@ export class App { const serverView = await this.appRoot.getServerView(server.getId()); try { await server.setAccessKeyDataLimit(keyId, {bytes: dataLimitBytes}); - this.refreshTransferStats(server, serverView); + this.refreshServerMetrics(server, serverView); this.appRoot.showNotification(this.appRoot.localize('saved')); return true; } catch (error) { @@ -1288,7 +1279,7 @@ export class App { const serverView = await this.appRoot.getServerView(server.getId()); try { await server.removeAccessKeyDataLimit(keyId); - this.refreshTransferStats(server, serverView); + this.refreshServerMetrics(server, serverView); this.appRoot.showNotification(this.appRoot.localize('saved')); return true; } catch (error) { diff --git a/server_manager/www/shadowbox_server.ts b/server_manager/www/shadowbox_server.ts index 7fd391ca56..5d7726d0bb 100644 --- a/server_manager/www/shadowbox_server.ts +++ b/server_manager/www/shadowbox_server.ts @@ -36,19 +36,6 @@ interface ServerConfigJson { accessKeyDataLimit?: server.DataLimit; } -// Byte transfer stats for the past 30 days, including both inbound and outbound. -// TODO: this is copied at src/shadowbox/model/metrics.ts. Both copies should -// be kept in sync, until we can find a way to share code between the web_app -// and shadowbox. -interface DataUsageByAccessKeyJson { - // The accessKeyId should be of type AccessKeyId, however that results in the tsc - // error TS1023: An index signature parameter type must be 'string' or 'number'. - // See https://github.com/Microsoft/TypeScript/issues/2491 - // TODO: this still says "UserId", changing to "AccessKeyId" will require - // a change on the shadowbox server. - bytesTransferredByUserId: {[accessKeyId: string]: number}; -} - // Converts the access key JSON from the API to its model. function makeAccessKeyModel(apiAccessKey: AccessKeyJson): server.AccessKey { return apiAccessKey as server.AccessKey; @@ -149,20 +136,8 @@ export class ShadowboxServer implements server.Server { await this.api.request(`access-keys/${keyId}/data-limit`, 'DELETE'); } - async getDataUsage(): Promise { - const jsonResponse = - await this.api.request('metrics/transfer'); - const usageMap = new Map(); - for (const [accessKeyId, bytes] of Object.entries( - jsonResponse.bytesTransferredByUserId - )) { - usageMap.set(accessKeyId, bytes ?? 0); - } - return usageMap; - } - async getServerMetrics(): Promise { - //TODO + //TODO: this.api.request('server/metrics') return { servers: [ { From 2b1d7daf045cb9976ffb39cc59e80a50b7c33c44 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Thu, 21 Nov 2024 17:21:35 -0500 Subject: [PATCH 10/16] endpoint implemented --- server_manager/model/server.ts | 8 +-- server_manager/www/shadowbox_server.ts | 87 ++++++++++++-------------- 2 files changed, 44 insertions(+), 51 deletions(-) diff --git a/server_manager/model/server.ts b/server_manager/model/server.ts index aab5edb1c6..f55fd72b01 100644 --- a/server_manager/model/server.ts +++ b/server_manager/model/server.ts @@ -197,19 +197,19 @@ export type ServerMetricsJson = { location: string; asn: number; asOrg: string; - tunnelTime: { + tunnelTime?: { seconds: number; }; - dataTransferred: { + dataTransferred?: { bytes: number; }; }[]; accessKeys: { accessKeyId: number; - tunnelTime: { + tunnelTime?: { seconds: number; }; - dataTransferred: { + dataTransferred?: { bytes: number; }; }[]; diff --git a/server_manager/www/shadowbox_server.ts b/server_manager/www/shadowbox_server.ts index 5d7726d0bb..84855b583b 100644 --- a/server_manager/www/shadowbox_server.ts +++ b/server_manager/www/shadowbox_server.ts @@ -36,6 +36,19 @@ interface ServerConfigJson { accessKeyDataLimit?: server.DataLimit; } +// Byte transfer stats for the past 30 days, including both inbound and outbound. +// TODO: this is copied at src/shadowbox/model/metrics.ts. Both copies should +// be kept in sync, until we can find a way to share code between the web_app +// and shadowbox. +interface DataUsageByAccessKeyJson { + // The accessKeyId should be of type AccessKeyId, however that results in the tsc + // error TS1023: An index signature parameter type must be 'string' or 'number'. + // See https://github.com/Microsoft/TypeScript/issues/2491 + // TODO: this still says "UserId", changing to "AccessKeyId" will require + // a change on the shadowbox server. + bytesTransferredByUserId: {[accessKeyId: string]: number}; +} + // Converts the access key JSON from the API to its model. function makeAccessKeyModel(apiAccessKey: AccessKeyJson): server.AccessKey { return apiAccessKey as server.AccessKey; @@ -137,53 +150,33 @@ export class ShadowboxServer implements server.Server { } async getServerMetrics(): Promise { - //TODO: this.api.request('server/metrics') - return { - servers: [ - { - location: 'CA', - asn: 1, - asOrg: 'IDK', - tunnelTime: { - seconds: 10000, - }, - dataTransferred: { - bytes: 10000, - }, - }, - { - location: 'US', - asn: 2, - asOrg: 'WHATEVER', - tunnelTime: { - seconds: 200000, - }, - dataTransferred: { - bytes: 200000, - }, - }, - ], - accessKeys: [ - { - accessKeyId: 0, - tunnelTime: { - seconds: 10000, - }, - dataTransferred: { - bytes: 10000, - }, - }, - { - accessKeyId: 1, - tunnelTime: { - seconds: 200000, - }, - dataTransferred: { - bytes: 200000, - }, - }, - ], - }; + try { + const result = await this.api.request( + 'experimental/server/metrics' + ); + + return result; + } catch (e) { + // fallback to metrics/transfer endpoint + const result: server.ServerMetricsJson = { + servers: [], + accessKeys: [], + }; + + const jsonResponse = + await this.api.request('metrics/transfer'); + + for (const [accessKeyId, bytes] of Object.entries( + jsonResponse.bytesTransferredByUserId + )) { + result.accessKeys.push({ + accessKeyId: Number(accessKeyId), + dataTransferred: {bytes}, + }); + } + + return result; + } } getName(): string { From a0f32b125f05e1c7ac223c677ee63c49c28bc9a9 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:27:39 -0500 Subject: [PATCH 11/16] Update server_manager/www/app.ts Co-authored-by: Vinicius Fortuna --- server_manager/www/app.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/server_manager/www/app.ts b/server_manager/www/app.ts index 8a16f34781..ad823d7633 100644 --- a/server_manager/www/app.ts +++ b/server_manager/www/app.ts @@ -1054,10 +1054,8 @@ export class App { serverView.totalDevices = serverView.totalUserHours / (30 * 24); let totalInboundBytes = 0; - for (const { - dataTransferred: {bytes}, - } of serverMetrics.accessKeys) { - totalInboundBytes += bytes; + for (const dataTransferred of serverMetrics.accessKeys) { + totalInboundBytes += dataTransferred.bytes; } serverView.totalInboundBytes = totalInboundBytes; From 70c811250905b958f102ab31eda76bb58deb7774 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:26:16 -0500 Subject: [PATCH 12/16] Update server_manager/model/server.ts Co-authored-by: Vinicius Fortuna --- server_manager/model/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server_manager/model/server.ts b/server_manager/model/server.ts index f55fd72b01..a5592c24b8 100644 --- a/server_manager/model/server.ts +++ b/server_manager/model/server.ts @@ -193,7 +193,7 @@ export interface DataLimit { } export type ServerMetricsJson = { - servers: { + server: { location: string; asn: number; asOrg: string; From fb7f672b660825604de7bb6eef9742e4bd5273b3 Mon Sep 17 00:00:00 2001 From: Daniel LaCosse <3759828+daniellacosse@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:56:00 -0500 Subject: [PATCH 13/16] partial feedback --- server_manager/index.html | 5 ++++- server_manager/www/app.ts | 8 +++----- server_manager/www/shadowbox_server.ts | 2 +- server_manager/www/testing/models.ts | 2 +- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/server_manager/index.html b/server_manager/index.html index 06b3b18456..a411c1af05 100644 --- a/server_manager/index.html +++ b/server_manager/index.html @@ -29,7 +29,10 @@ />