Skip to content

Commit

Permalink
Add support for fetching container logs from a given time (#670)
Browse files Browse the repository at this point in the history
  • Loading branch information
NuShoSinkuPomogliTebeTvoiSankcii authored Nov 23, 2023
1 parent 40cd6f6 commit 29ed50e
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 5 deletions.
11 changes: 11 additions & 0 deletions docs/features/containers.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,3 +527,14 @@ const container = await new GenericContainer("alpine")
})
.start();
```

You can specify a point in time as a UNIX timestamp from which you want the logs to start:

```javascript
const msInSec = 1000;
const tenSecondsAgoMs = new Date().getTime() - 10 * msInSec;
const since = tenSecondsAgoMs / msInSec;

(await container.logs({ since }))
.on("data", line => console.log(line))
```
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export class AbstractStartedContainer implements StartedTestContainer {
return this.startedTestContainer.exec(command);
}

public logs(): Promise<Readable> {
return this.startedTestContainer.logs();
public logs(opts?: { since?: number }): Promise<Readable> {
return this.startedTestContainer.logs(opts);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { GenericContainer } from "./generic-container";
import { containerLog } from "../common";
import { Wait } from "../wait-strategies/wait";

describe("GenericContainer logs", () => {
jest.setTimeout(180_000);
Expand All @@ -26,6 +27,32 @@ describe("GenericContainer logs", () => {
await container.stop();
});

it("should stream logs with since option from a started container", async () => {
const pauseMs = 5 * 1000;
const logBeforeSleep = "first";
const logAfterSleep = "second";
const container = await new GenericContainer("cristianrgreco/testcontainer:1.1.14")
.withEntrypoint([
"/bin/sh",
"-c",
`echo ${logBeforeSleep} && sleep ${pauseMs / 1000} && echo ${logAfterSleep} && sleep infinity`,
])
.withWaitStrategy(Wait.forLogMessage(logBeforeSleep))
.start();

await new Promise((resolve) => setTimeout(resolve, pauseMs));

const inSleepTimestamp = new Date().getTime() - pauseMs + 1000;
const since = Math.floor(inSleepTimestamp / 1000);

const stream = await container.logs({ since });
const log: string = await new Promise((resolve) => stream.on("data", (line) => resolve(line.trim())));

expect(log).toBe(logAfterSleep);

await container.stop();
});

it("should stream logs from a running container after restart", async () => {
const containerLogTraceSpy = jest.spyOn(containerLog, "trace");
const container = await new GenericContainer("cristianrgreco/testcontainer:1.1.14").withExposedPorts(8080).start();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,9 @@ export class StartedGenericContainer implements StartedTestContainer {
return output;
}

public async logs(): Promise<Readable> {
public async logs(opts?: { since?: number }): Promise<Readable> {
const client = await getContainerRuntimeClient();
return client.container.logs(this.container);

return client.container.logs(this.container, opts);
}
}
2 changes: 1 addition & 1 deletion packages/testcontainers/src/test-container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export interface StartedTestContainer {
copyFilesToContainer(filesToCopy: FileToCopy[]): Promise<void>;
copyContentToContainer(contentsToCopy: ContentToCopy[]): Promise<void>;
exec(command: string | string[]): Promise<ExecResult>;
logs(): Promise<Readable>;
logs(opts?: { since?: number }): Promise<Readable>;
}

export interface StoppedTestContainer {
Expand Down

0 comments on commit 29ed50e

Please sign in to comment.