Skip to content
This repository was archived by the owner on Apr 6, 2026. It is now read-only.

Commit a1311c9

Browse files
authored
fix: logs get log events pagination (#37)
* fix(cognito): auto-generate sub, fix JWT sub claim, add AdminUserGlobalSignOut (#68) * fix: return stable cursor tokens in GetLogEvents to fix SDK pagination loop
1 parent e71a606 commit a1311c9

2 files changed

Lines changed: 72 additions & 0 deletions

File tree

sdk-test-java/src/main/java/com/floci/test/tests/CloudWatchLogsTests.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public void run(TestContext ctx) {
3434
testCreateLogStream(ctx, cw);
3535
testPutAndGetLogEvents(ctx, cw);
3636
testGetLogEventsTimeFilter(ctx, cw);
37+
testGetLogEventsPagination(ctx, cw);
3738
testFilterLogEvents(ctx, cw);
3839
testDeleteLogStream(ctx, cw);
3940
testDeleteLogGroup(ctx, cw);
@@ -140,6 +141,55 @@ private void testGetLogEventsTimeFilter(TestContext ctx, CloudWatchLogsClient cw
140141
}
141142
}
142143

144+
private void testGetLogEventsPagination(TestContext ctx, CloudWatchLogsClient cw) {
145+
String stream = "stream-pagination";
146+
try {
147+
cw.createLogStream(b -> b.logGroupName(GROUP_NAME).logStreamName(stream));
148+
149+
long base = System.currentTimeMillis() - 10000;
150+
List<InputLogEvent> events = new java.util.ArrayList<>();
151+
for (int i = 0; i < 7; i++) {
152+
final int idx = i;
153+
events.add(InputLogEvent.builder().timestamp(base + idx).message("page-msg-" + idx).build());
154+
}
155+
cw.putLogEvents(b -> b.logGroupName(GROUP_NAME).logStreamName(stream).logEvents(events));
156+
157+
// Page 1: limit=3, startFromHead
158+
GetLogEventsResponse page1 = cw.getLogEvents(b -> b
159+
.logGroupName(GROUP_NAME).logStreamName(stream)
160+
.limit(3).startFromHead(true));
161+
ctx.check("CWL GetLogEvents pagination page1 count=3", page1.events().size() == 3);
162+
ctx.check("CWL GetLogEvents pagination page1 first message",
163+
"page-msg-0".equals(page1.events().get(0).message()));
164+
165+
// Page 2: use nextForwardToken
166+
GetLogEventsResponse page2 = cw.getLogEvents(b -> b
167+
.logGroupName(GROUP_NAME).logStreamName(stream)
168+
.limit(3).nextToken(page1.nextForwardToken()));
169+
ctx.check("CWL GetLogEvents pagination page2 count=3", page2.events().size() == 3);
170+
ctx.check("CWL GetLogEvents pagination page2 first message",
171+
"page-msg-3".equals(page2.events().get(0).message()));
172+
173+
// Page 3 (last): remaining 1 event
174+
GetLogEventsResponse page3 = cw.getLogEvents(b -> b
175+
.logGroupName(GROUP_NAME).logStreamName(stream)
176+
.limit(3).nextToken(page2.nextForwardToken()));
177+
ctx.check("CWL GetLogEvents pagination page3 count=1", page3.events().size() == 1);
178+
ctx.check("CWL GetLogEvents pagination page3 message",
179+
"page-msg-6".equals(page3.events().get(0).message()));
180+
181+
// End-of-stream: token must echo back (SDK uses this to stop)
182+
GetLogEventsResponse atEnd = cw.getLogEvents(b -> b
183+
.logGroupName(GROUP_NAME).logStreamName(stream)
184+
.limit(3).nextToken(page3.nextForwardToken()));
185+
ctx.check("CWL GetLogEvents end-of-stream token echoed",
186+
page3.nextForwardToken().equals(atEnd.nextForwardToken()));
187+
188+
} catch (Exception e) {
189+
ctx.check("CWL GetLogEvents pagination", false, e);
190+
}
191+
}
192+
143193
private void testFilterLogEvents(TestContext ctx, CloudWatchLogsClient cw) {
144194
try {
145195
String stream3 = "stream-filter-test";

sdk-test-java/src/main/java/com/floci/test/tests/CognitoTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public void run(TestContext ctx) {
6060
.username(fUsername)
6161
.userAttributes(AttributeType.builder().name("email").value("test@example.com").build()));
6262
ctx.check("Cognito AdminCreateUser", resp.user().username().equals(fUsername));
63+
64+
boolean hasSub = resp.user().attributes().stream().anyMatch(a -> "sub".equals(a.name()));
65+
ctx.check("Cognito AdminCreateUser contains sub", hasSub);
6366
} catch (Exception e) {
6467
ctx.check("Cognito AdminCreateUser", false, e);
6568
}
@@ -87,6 +90,13 @@ public void run(TestContext ctx) {
8790
final String token = accessToken;
8891
GetUserResponse resp = cognito.getUser(b -> b.accessToken(token));
8992
ctx.check("Cognito GetUser", resp.username().equals(fUsername));
93+
94+
try {
95+
cognito.adminUserGlobalSignOut(b -> b.userPoolId(fPoolId).username(fUsername));
96+
ctx.check("Cognito AdminUserGlobalSignOut", true);
97+
} catch (Exception e) {
98+
ctx.check("Cognito AdminUserGlobalSignOut", false, e);
99+
}
90100
} catch (Exception e) {
91101
ctx.check("Cognito GetUser", false, e);
92102
}
@@ -170,6 +180,18 @@ public void run(TestContext ctx) {
170180
String payload = new String(Base64.getUrlDecoder().decode(parts[1]), StandardCharsets.UTF_8);
171181
ctx.check("Cognito JWT cognito:groups claim",
172182
payload.contains("\"cognito:groups\"") && payload.contains("\"test-group\""));
183+
184+
// Verify consistent sub in JWT
185+
String subAttr = null;
186+
AdminGetUserResponse userResp = cognito.adminGetUser(b -> b.userPoolId(fPoolId).username(fUsername));
187+
for (AttributeType attr : userResp.userAttributes()) {
188+
if ("sub".equals(attr.name())) {
189+
subAttr = attr.value();
190+
}
191+
}
192+
ctx.check("Cognito JWT sub claim match",
193+
payload.contains("\"sub\":\"" + subAttr + "\""));
194+
173195
} catch (Exception e) {
174196
ctx.check("Cognito JWT cognito:groups claim", false, e);
175197
}

0 commit comments

Comments
 (0)