Skip to content

Commit

Permalink
how does this look?
Browse files Browse the repository at this point in the history
  • Loading branch information
daniellacosse committed Aug 26, 2024
1 parent 8632a97 commit b709e5e
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 27 deletions.
12 changes: 0 additions & 12 deletions src/shadowbox/model/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,3 @@ export interface DataUsageByUser {
export interface DataUsageTimeframe {
hours: number;
}


export interface TunneltimeMetrics {
access_key?: Map<string, number>;
country?: Map<string, number>;
asn?: Map<string, number>;
}

export interface TunneltimeQuery {
hours?: number;
groupName?: 'access_key' | 'country' | 'asn';
}
50 changes: 35 additions & 15 deletions src/shadowbox/server/manager_metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,31 @@
// limitations under the License.

import {PrometheusClient} from '../infrastructure/prometheus_scraper';
import {DataUsageByUser, DataUsageTimeframe, TunneltimeMetrics, TunneltimeQuery} from '../model/metrics';
import {DataUsageByUser, DataUsageTimeframe} from '../model/metrics';

type TunnelTimeDimension = 'access_key' | 'country' | 'asn';

interface TunneTimeRequest {
params: {
sinceIsoTimestamp?: number;
dimensions?: TunnelTimeDimension[];
}
}

interface TunnelTimeResponse {
data: {
access_key?: string;
country?: string;
asn?: number;
tunnel_time: {
hours: number;
}
}[]
}

export interface ManagerMetrics {
getOutboundByteTransfer(timeframe: DataUsageTimeframe): Promise<DataUsageByUser>;
getTunneltime(query: TunneltimeQuery): Promise<TunneltimeMetrics>;
getTunnelTime(request: TunneTimeRequest): Promise<TunnelTimeResponse>;
}

// Reads manager metrics from a Prometheus instance.
Expand All @@ -42,20 +62,20 @@ export class PrometheusManagerMetrics implements ManagerMetrics {
return {bytesTransferredByUserId: usage};
}

async getTunneltime({ hours = 24 * 30, groupName = 'access_key' }: TunneltimeQuery): Promise<TunneltimeMetrics> {
const { result } = await this.prometheusClient.query(
`sum(increase(shadowsocks_tunnel_time_seconds[${hours}h])) by (${groupName})`
);
async getTunnelTime({ params: { dimensions, sinceIsoTimestamp }}: TunneTimeRequest): Promise<TunnelTimeResponse> {
const timeExpression = sinceIsoTimestamp ? `[${Math.round((Date.now() - sinceIsoTimestamp) / 1000)}s]` : '';
const dimensionsExpression = dimensions ? ` by (${dimensions.join()})` : '';
const prometheusQuery = `sum(increase(shadowsocks_tunnel_time_seconds${timeExpression}))${dimensionsExpression}`;

return {[groupName]: result.reduce((groupMap, { metric, value: [, rawValue] }) => {
const groupValue = Math.round(parseFloat(rawValue));
const groupKey = metric[groupName];
if (groupValue === 0 || !groupKey) {
return groupMap;
}
const { result } = await this.prometheusClient.query(prometheusQuery);

groupMap.set(groupKey, groupValue);
return groupMap;
}, new Map())};
return {
data: result.map((entry) => ({
access_key: entry.metric['access_key'],
country: entry.metric['country'],
asn: entry.metric['asn'] ? parseInt(entry.metric['asn']) : undefined,
tunnel_time: { hours: Math.round(parseFloat(entry.value[1]) / 60 / 60) },
})),
};
}
}

0 comments on commit b709e5e

Please sign in to comment.