Skip to content

Commit 5964b67

Browse files
feat: support records endpoint
1 parent b1ee8a0 commit 5964b67

4 files changed

Lines changed: 305 additions & 12 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ const { Search } = require('sumologic-client');
4848
to: '2019-06-25T17:14:31+09:00'
4949
};
5050

51-
const it = await client.getIterator(searchParams);
51+
const it = await client.getMessageIterator(searchParams);
5252

5353
for await (let response of it) {
5454
// check the latest backend state and total
5555
// number of results gathered so far:
5656
console.log(response.state);
5757

58-
// new search results since the last iteration:
58+
// new search results since the last iteration:
5959
console.log(response.results);
6060
}
6161
})();

src/search.js

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,12 @@ class Search {
148148
* which case this method will return results gathered **so far**. If you call this while the
149149
* results are still being gathered, be sure to call this again with the corresponding offset.
150150
*/
151-
async getJobResults(id, offset = 0) {
151+
async getJobResults(type, id, offset = 0) {
152152
log('getJobResults');
153153

154154
const requestParams = {
155155
method: 'get',
156-
url: `/search/jobs/${id}/messages?offset=${offset}&limit=${this.config.searchPageLimit}`
156+
url: `/search/jobs/${id}/${type}s?offset=${offset}&limit=${this.config.searchPageLimit}`
157157
};
158158

159159
const response = await this.request(requestParams);
@@ -176,7 +176,7 @@ class Search {
176176
this._nonce = new Object();
177177
}
178178

179-
async *getIterator(queryParams) {
179+
async *_getIterator(type, queryParams) {
180180
const jobId = await this.newSearchJob(queryParams);
181181
let myNonce;
182182

@@ -185,6 +185,7 @@ class Search {
185185

186186
let resultsGatheredSoFar = 0;
187187
let state = null;
188+
const countAttribute = `${type}Count`;
188189

189190
while (true) {
190191
if (this._nonce !== myNonce) {
@@ -196,7 +197,7 @@ class Search {
196197
// refresh the state, unless already done gathering results:
197198
if (!(state && state.state === Search.STATE_DONE_GATHERING_RESULTS)) {
198199
state = await this.getJobState(jobId);
199-
log(`state=${state.state}, cnt=${state.messageCount}`);
200+
log(`state=${state.state}, cnt=${state[countAttribute]}`);
200201
}
201202

202203
if (state.state === Search.STATE_NOT_STARTED) {
@@ -216,15 +217,15 @@ class Search {
216217
throw new Error('Search job has been force paused. This behavior is currently not supported.');
217218
}
218219

219-
const results = await this.getJobResults(jobId, resultsGatheredSoFar);
220+
const results = await this.getJobResults(type, jobId, resultsGatheredSoFar);
220221

221222
yield { state, results };
222223

223-
resultsGatheredSoFar += results.messages.length;
224+
resultsGatheredSoFar += results[`${type}s`].length;
224225
log(`gathered so far: ${resultsGatheredSoFar}`);
225226

226227
if (state.state === Search.STATE_DONE_GATHERING_RESULTS) {
227-
if (state.messageCount === resultsGatheredSoFar) {
228+
if (state[countAttribute] === resultsGatheredSoFar) {
228229
log('job done gathering results, and we downloaded everything; wrapping up');
229230
await this.deleteSearchJob(jobId);
230231
return;
@@ -237,6 +238,27 @@ class Search {
237238
}
238239
}
239240

241+
242+
/**
243+
* Gets message results gathered so far, from a given offset. This does not take the current job state
244+
* into consideration. E.g. this method may be called when results are still being gathered, in
245+
* which case this method will return results gathered **so far**. If you call this while the
246+
* results are still being gathered, be sure to call this again with the corresponding offset.
247+
*/
248+
async getMessageIterator(id, offset = 0) {
249+
return await this._getIterator('message', id, offset);
250+
}
251+
252+
/**
253+
* Gets record results gathered so far, from a given offset. This does not take the current job state
254+
* into consideration. E.g. this method may be called when results are still being gathered, in
255+
* which case this method will return results gathered **so far**. If you call this while the
256+
* results are still being gathered, be sure to call this again with the corresponding offset.
257+
*/
258+
async getRecordIterator(id, offset = 0) {
259+
return await this._getIterator('record', id, offset);
260+
}
261+
240262
_getBasicAuthSecret() {
241263
// eslint-disable-next-line no-undef
242264
let btoa = typeof window === 'undefined' ? undefined : window.btoa;

test/fixtures/02.js

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
module.exports = [{
2+
scope: 'https://api.jp.sumologic.com:443',
3+
method: 'POST',
4+
path: '/api/v1/search/jobs',
5+
body: {
6+
query: 'sample_query',
7+
from: '2019-06-25T10:14:31+09:00',
8+
to: '2019-06-25T17:14:31+09:00',
9+
timeZone: 'Asia/Tokyo'
10+
},
11+
status: 202,
12+
response: {
13+
id: '750D3ABE4460BA73',
14+
link: {
15+
rel: 'self',
16+
href: 'https://api.jp.sumologic.com/api/v1/search/jobs/750D3ABE4460BA73'
17+
}
18+
},
19+
rawHeaders: [
20+
'Date',
21+
'Wed, 10 Jul 2019 04:10:36 GMT',
22+
'Content-Type',
23+
'application/json',
24+
'Transfer-Encoding',
25+
'chunked',
26+
'Connection',
27+
'close',
28+
'Set-Cookie',
29+
'AWSALB=Pxmydyk+9LMvAEfZH2h55jJve2ufmwdneWqzPcrul85wJo8SD0DoFmSBQIDhde3Sv1rp4Z/D3JXi7l0MLGtr0e1IhE6XhN8ihEAQoMPtEcPrJCRi7EYX0AJCS/03; Expires=Wed, 17 Jul 2019 04:10:36 GMT; Path=/',
30+
'Cache-Control',
31+
'no-cache, no-store, max-age=0, must-revalidate',
32+
'Pragma',
33+
'no-cache',
34+
'Expires',
35+
'Thu, 01 Jan 1970 00:00:00 GMT',
36+
'X-XSS-Protection',
37+
'1; mode=block',
38+
'X-Frame-Options',
39+
'DENY',
40+
'X-Content-Type-Options',
41+
'nosniff',
42+
'Set-Cookie',
43+
'JSESSIONID=node0z8u0k92qywg3ek8wy6br6dj2843.node0; Path=/api',
44+
'Location',
45+
'https://api.jp.sumologic.com/api/v1/search/jobs/750D3ABE4460BA73'
46+
]
47+
},
48+
{
49+
scope: 'https://api.jp.sumologic.com:443',
50+
method: 'GET',
51+
path: '/api/v1/search/jobs/750D3ABE4460BA73',
52+
body: '',
53+
status: 200,
54+
response: {
55+
state: 'DONE GATHERING RESULTS',
56+
histogramBuckets: [
57+
{
58+
startTimestamp: 1561425300000,
59+
length: 300000,
60+
count: 576
61+
},
62+
{
63+
startTimestamp: 1561425271000,
64+
length: 29000,
65+
count: 78
66+
}
67+
],
68+
messageCount: 3,
69+
recordCount: 3,
70+
pendingWarnings: [],
71+
pendingErrors: []
72+
},
73+
rawHeaders: [
74+
'Date',
75+
'Wed, 10 Jul 2019 04:10:36 GMT',
76+
'Content-Type',
77+
'application/json;charset=utf-8',
78+
'Transfer-Encoding',
79+
'chunked',
80+
'Connection',
81+
'close',
82+
'Set-Cookie',
83+
'AWSALB=G6vGpwo8A/C1Zu+1IpQU3WVBpYJqr+JToBZ0+s8l3EPYaePY5gVHxz8IJUTa1Mf/YdJnS09GFLakCjPP3v4z5CAqyObDcQTWUb+UI8ddmyxFEuSt+C7A8xApOZlm; Expires=Wed, 17 Jul 2019 04:10:36 GMT; Path=/',
84+
'Cache-Control',
85+
'no-cache, no-store, max-age=0, must-revalidate',
86+
'Pragma',
87+
'no-cache',
88+
'Expires',
89+
'Thu, 01 Jan 1970 00:00:00 GMT',
90+
'X-XSS-Protection',
91+
'1; mode=block',
92+
'X-Frame-Options',
93+
'DENY',
94+
'X-Content-Type-Options',
95+
'nosniff',
96+
'Set-Cookie',
97+
'JSESSIONID=node0shrdo704xzmy1sgazlho1l8z42840.node0; Path=/api',
98+
'Vary',
99+
'Accept-Encoding, User-Agent'
100+
]
101+
}, {
102+
scope: 'https://api.jp.sumologic.com:443',
103+
method: 'GET',
104+
path: '/api/v1/search/jobs/750D3ABE4460BA73/records?offset=0&limit=50000',
105+
body: '',
106+
status: 200,
107+
response: {
108+
fields: [
109+
{
110+
name: 'sample-field',
111+
fieldType: 'long',
112+
keyField: false
113+
}
114+
],
115+
records: [
116+
{
117+
"map": {
118+
"_count": "1",
119+
"key": "aggregation key1",
120+
}
121+
},
122+
{
123+
"map": {
124+
"_count": "2",
125+
"key": "aggregation key2",
126+
}
127+
},
128+
{
129+
"map": {
130+
"_count": "3",
131+
"key": "aggregation key3",
132+
}
133+
}
134+
]
135+
},
136+
rawHeaders: [
137+
'Date',
138+
'Wed, 10 Jul 2019 04:10:36 GMT',
139+
'Content-Type',
140+
'application/json;charset=utf-8',
141+
'Transfer-Encoding',
142+
'chunked',
143+
'Connection',
144+
'close',
145+
'Set-Cookie',
146+
'AWSALB=TwtM7wDsw4K/kc52LbyjxJZNENNUeDU/t0/9NVDxUU/0EqLuCyor/Ym9eevsol1hl8BTFVnuVEIGxdkgM0mqzDEUHARpwhHjl8axm8NKxpJFYV+BMU9lyuLbMdXo; Expires=Wed, 17 Jul 2019 04:10:36 GMT; Path=/',
147+
'Cache-Control',
148+
'no-cache, no-store, max-age=0, must-revalidate',
149+
'Pragma',
150+
'no-cache',
151+
'Expires',
152+
'Thu, 01 Jan 1970 00:00:00 GMT',
153+
'X-XSS-Protection',
154+
'1; mode=block',
155+
'X-Frame-Options',
156+
'DENY',
157+
'X-Content-Type-Options',
158+
'nosniff',
159+
'Set-Cookie',
160+
'JSESSIONID=node013d6vnkzzyjexr2dcnemtws1d2841.node0; Path=/api',
161+
'Vary',
162+
'Accept-Encoding, User-Agent'
163+
]
164+
}, {
165+
scope: 'https://api.jp.sumologic.com:443',
166+
method: 'DELETE',
167+
path: '/api/v1/search/jobs/750D3ABE4460BA73',
168+
body: '',
169+
status: 200,
170+
response: {
171+
id: '750D3ABE4460BA73'
172+
},
173+
rawHeaders: [
174+
'Date',
175+
'Wed, 10 Jul 2019 04:10:37 GMT',
176+
'Content-Type',
177+
'application/json;charset=utf-8',
178+
'Transfer-Encoding',
179+
'chunked',
180+
'Connection',
181+
'close',
182+
'Set-Cookie',
183+
'AWSALB=lmcUMXglhcyc2AeVaWGWPZB9eWMxQ8VEJHBgZlUuqa37n5yLlvp01+7LL2Z8ghzQkm7CxmBlzW3u+Anhi5HwJIuMeJ/hDQFpM5Xw2dJNynVWe8sR0xO4QuR5yU4B; Expires=Wed, 17 Jul 2019 04:10:37 GMT; Path=/',
184+
'Cache-Control',
185+
'no-cache, no-store, max-age=0, must-revalidate',
186+
'Pragma',
187+
'no-cache',
188+
'Expires',
189+
'Thu, 01 Jan 1970 00:00:00 GMT',
190+
'X-XSS-Protection',
191+
'1; mode=block',
192+
'X-Frame-Options',
193+
'DENY',
194+
'X-Content-Type-Options',
195+
'nosniff',
196+
'Set-Cookie',
197+
'JSESSIONID=node0mkt2s73n3p8umrb4rofhd25a2842.node0; Path=/api'
198+
]
199+
}];

0 commit comments

Comments
 (0)