0

Get traffic statistics

by
Published today

Read one page of the Traffic Item Statistics or Flow Statistics view of an IxNetwork session.

Script ixia_ixnetwork Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 6 hours ago
1
//native
2

3
// X-Api-Key header: the resource's api_key, or one obtained from username/password
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
  // Keysight's clients read each view's caption with a GET on the view; skip it when the list already has it
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
  // /data replaces /page, deprecated since IxNetwork 8.50
84
  const dataUrl = `${viewsUrl}/${view.id}/data`
85

86
  // the view's current page is server-side state: select the page (and size) before reading it
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
  // each pageValues entry groups an ingress row with its egress-tracking rows; the first is the row itself
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