Skip to content

Commit 73719a5

Browse files
authored
Make sure some logs that are long are in fact returned in its entirety (#163)
1 parent 494c062 commit 73719a5

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

src/createCloudJob.ts

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import * as sleep from 'await-sleep'
77
import Publisher from './publisher'
88
import { Runlog } from './RunLog'
99
import promisify from './promisify'
10+
11+
import * as crypto from 'crypto'
12+
1013
const clusterName = 'violinist-cluster'
1114
const sleepWhilePolling = 5000
1215
// 3 hours (180 mins) hours with the interval above.
@@ -16,6 +19,49 @@ const createLogGroup = (taskDefinition) => {
1619
return util.format('/ecs/%s', taskDefinition)
1720
}
1821

22+
async function getAllLogEvents ({ logs, logGroupName, logStreamName, startTime = 0, startFromHead = true, pageLimit = 1000 }) {
23+
let nextToken
24+
const events = []
25+
const seen = new Set()
26+
let guard = 0
27+
28+
while (true) {
29+
const res = await logs.getLogEvents({
30+
logGroupName,
31+
logStreamName,
32+
startTime,
33+
startFromHead,
34+
limit: pageLimit,
35+
nextToken
36+
}).promise()
37+
38+
for (const e of res.events) {
39+
// We only want unique events, so we use a Set to track seen event IDs.
40+
// This prevents duplicates in the final events array.
41+
const hash = crypto.createHash('sha1')
42+
hash.update(e.message + e.timestamp)
43+
e.eventId = hash.digest('hex')
44+
if (!seen.has(e.eventId)) {
45+
seen.add(e.eventId)
46+
events.push(e)
47+
}
48+
}
49+
50+
// If the forward token didn't change, there are no more pages.
51+
if (res.nextForwardToken === nextToken) {
52+
break
53+
};
54+
nextToken = res.nextForwardToken
55+
56+
// Safety to avoid accidental infinite loops
57+
if (++guard > 50) {
58+
throw new Error('Pagination guard tripped')
59+
}
60+
}
61+
62+
return events
63+
}
64+
1965
const createEcsName = (data) => {
2066
// Should be named like this:
2167
// PHP version 7.1 => 71
@@ -131,13 +177,14 @@ const createCloudJob = (config, job: Job, gitRev) => {
131177
while (true) {
132178
try {
133179
retries++
134-
const list = await watchClient.getLogEvents({
135-
limit: 100,
180+
events = await getAllLogEvents({
181+
logs: watchClient,
136182
logGroupName: createLogGroup(taskDefinition),
137183
logStreamName: util.format('ecs/%s/%s', name, arnParts[2])
138-
}).promise()
139-
events = list.events
140-
if (events.length) {
184+
})
185+
// We require the first one to start with "[{" since thats the opening of the JSON stream.
186+
// But also, the last one should end with "}]"
187+
if (events.length && events[0].message.startsWith('[{') && events[events.length - 1].message.endsWith('}]')) {
141188
break
142189
}
143190
} catch (logErr) {

test/src/fakeWatchClient.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ export default class fakeWatchClient extends fakeAwsBase {
88

99
getPromiseOutput() {
1010
return {
11+
nextForwardToken: 'nextToken',
1112
events: [
1213
{
13-
message: 'One log message',
14+
message: '[{"message: "One log message"',
1415

1516
},
1617
{
17-
message: 'Log message 2'
18+
message: '},"message":"Log message 2"}]',
1819
}
1920
]
2021
}
2122
}
22-
}
23+
}

0 commit comments

Comments
 (0)