1 | |
2 |
|
3 | |
4 | async function authHeaders( |
5 | auth: RT.IxiaIxnetwork, |
6 | base: string |
7 | ): Promise<Record<string, string>> { |
8 | if (auth.api_key) return { "X-Api-Key": auth.api_key } |
9 | if (!auth.username) return {} |
10 | const response = await fetch(`${base}/api/v1/auth/session`, { |
11 | method: "POST", |
12 | headers: { "Content-Type": "application/json", Accept: "application/json" }, |
13 | body: JSON.stringify({ username: auth.username, password: auth.password }), |
14 | }) |
15 | if (!response.ok) { |
16 | throw new Error(`${response.status} ${await response.text()}`) |
17 | } |
18 | const { apiKey } = (await response.json()) as { apiKey: string } |
19 | return { "X-Api-Key": apiKey } |
20 | } |
21 |
|
22 | type Page = { |
23 | isReady?: boolean |
24 | currentPage?: number |
25 | pageSize?: number |
26 | totalPages?: number |
27 | totalRows?: number |
28 | columnCaptions?: string[] |
29 | pageValues?: (string | number | null)[][][] |
30 | } |
31 |
|
32 | |
33 | * Get traffic statistics |
34 | * Read one page of a statistics view: "Traffic Item Statistics" (default) or "Flow Statistics". Returns the page's rows keyed by column caption, plus current_page and total_pages to fetch the next page. |
35 | */ |
36 | export async function main( |
37 | auth: RT.IxiaIxnetwork, |
38 | session_id: number, |
39 | view_caption: string = "Traffic Item Statistics", |
40 | page: number = 1, |
41 | page_size: number | undefined |
42 | ) { |
43 | const base = auth.base_url.replace(/\/+$/, "") |
44 | const headers = { |
45 | ...(await authHeaders(auth, base)), |
46 | Accept: "application/json", |
47 | } |
48 | const caption = view_caption || "Traffic Item Statistics" |
49 | const viewsUrl = `${base}/api/v1/sessions/${session_id}/ixnetwork/statistics/view` |
50 |
|
51 | const viewsResponse = await fetch(viewsUrl, { headers }) |
52 | if (!viewsResponse.ok) { |
53 | throw new Error(`${viewsResponse.status} ${await viewsResponse.text()}`) |
54 | } |
55 | const views = (await viewsResponse.json()) as { |
56 | id: number |
57 | caption?: string |
58 | }[] |
59 |
|
60 | |
61 | let view: { id: number; caption?: string } | undefined |
62 | const captions: string[] = [] |
63 | for (const item of views) { |
64 | let current = item |
65 | if (current.caption == null) { |
66 | const viewResponse = await fetch(`${viewsUrl}/${item.id}`, { headers }) |
67 | if (!viewResponse.ok) { |
68 | throw new Error(`${viewResponse.status} ${await viewResponse.text()}`) |
69 | } |
70 | current = (await viewResponse.json()) as { id: number; caption?: string } |
71 | } |
72 | captions.push(current.caption ?? "") |
73 | if (current.caption?.toLowerCase() === caption.toLowerCase()) { |
74 | view = current |
75 | break |
76 | } |
77 | } |
78 | if (!view) { |
79 | throw new Error( |
80 | `No statistics view "${caption}". Available views: ${captions.join(", ")}` |
81 | ) |
82 | } |
83 | |
84 | const dataUrl = `${viewsUrl}/${view.id}/data` |
85 |
|
86 | |
87 | const patch = await fetch(dataUrl, { |
88 | method: "PATCH", |
89 | headers: { ...headers, "Content-Type": "application/json" }, |
90 | body: JSON.stringify({ |
91 | currentPage: page || 1, |
92 | pageSize: page_size || undefined, |
93 | }), |
94 | }) |
95 | if (!patch.ok) { |
96 | throw new Error(`${patch.status} ${await patch.text()}`) |
97 | } |
98 |
|
99 | const response = await fetch(dataUrl, { headers }) |
100 | if (!response.ok) { |
101 | throw new Error(`${response.status} ${await response.text()}`) |
102 | } |
103 | const data = (await response.json()) as Page |
104 |
|
105 | const columns = data.columnCaptions ?? [] |
106 | |
107 | const rows = (data.pageValues ?? []).map((group) => |
108 | Object.fromEntries(columns.map((c, i) => [c, group[0]?.[i]])) |
109 | ) |
110 |
|
111 | return { |
112 | view_id: view.id, |
113 | caption: view.caption, |
114 | is_ready: data.isReady, |
115 | current_page: data.currentPage, |
116 | page_size: data.pageSize, |
117 | total_pages: data.totalPages, |
118 | total_rows: data.totalRows, |
119 | column_captions: columns, |
120 | rows, |
121 | page_values: data.pageValues, |
122 | } |
123 | } |
124 |
|