Skip to content

Commit

Permalink
Do some plumbing, and add tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
David Griffin committed Dec 9, 2024
1 parent 8c4a7d1 commit 9cffc75
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 33 deletions.
69 changes: 68 additions & 1 deletion __tests__/unit/logger.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { LOG_LEVELS, parseDebugLevel } from "../../src";
import { ConsoleLogHandler, LOG_LEVELS, parseDebugLevel } from "../../src";
import { LogHandler } from "../../src/util/logging";

describe("logging", () => {
describe("parseDebugLevel", () => {
Expand Down Expand Up @@ -32,3 +33,69 @@ describe("logging", () => {
);
});
});

describe("levels", () => {
describe("TRACE log level", () => {
const logger: LogHandler = new ConsoleLogHandler(LOG_LEVELS.DEBUG);
it("always log", () => {
logger.trace("Should log trace");
logger.debug("Should log debug");
logger.warn("Should log warnings");
logger.error("Should log errors");
});
});
describe("DEBUG log level", () => {
const logger: LogHandler = new ConsoleLogHandler(LOG_LEVELS.DEBUG);
it("skipped", () => {
logger.trace("Should not log", "foo");
});
it("debug", () => {
logger.debug("Should log something");
});
it("warn", () => {
logger.warn("Should also log (%s substitution!)", "with");
});
});
describe("ERROR log level", () => {
const logger: LogHandler = new ConsoleLogHandler(LOG_LEVELS.ERROR);
it("skipped", () => {
logger.trace("Should not log", "foo");
logger.debug("Should not log", "bar");
logger.warn("Should not log");
});
it("logged", () => {
logger.error("Should log (%s substitution!)", "with");
});
});
});

describe("Log messages", () => {
const logger: LogHandler = new ConsoleLogHandler(LOG_LEVELS.TRACE);
describe("Log message construction", () => {
it("trace", () => {
logger.trace("hello %s world", "foo", "bar"); // hello foo world bar
logger.trace("hello %s %s world", "foo", "bar"); // hello foo bar world
logger.trace("hello %s %s %s world", "foo", "bar"); // hello foo bar %s world
});
it("debug", () => {
logger.debug("hello %s world", "foo", "bar"); // hello foo world bar
logger.debug("hello %s %s world", "foo", "bar"); // hello foo bar world
logger.debug("hello %s %s %s world", "foo", "bar"); // hello foo bar %s world
});
it("info", () => {
logger.info("hello %s world", "foo", "bar"); // hello foo world bar
logger.info("hello %s %s world", "foo", "bar"); // hello foo bar world
logger.info("hello %s %s %s world", "foo", "bar"); // hello foo bar %s world
});
it("warn", () => {
logger.warn("hello %s world", "foo", "bar"); // hello foo world bar
logger.warn("hello %s %s world", "foo", "bar"); // hello foo bar world
logger.warn("hello %s %s %s world", "foo", "bar"); // hello foo bar %s world
});
it("error", () => {
logger.error("hello %s world", "foo", "bar"); // hello foo world bar
logger.error("hello %s %s world", "foo", "bar"); // hello foo bar world
logger.error("hello %s %s %s world", "foo", "bar"); // hello foo bar %s world
});
});
});
12 changes: 11 additions & 1 deletion src/client-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ export interface ClientConfiguration {
*/
fetch_keepalive?: boolean;

/**
* A log handler instance.
*/
logger?: LogHandler;

/**
Expand Down Expand Up @@ -199,6 +202,11 @@ export type StreamClientConfiguration = {
*/
secret: string;

/**
* A log handler instance.
*/
logger: LogHandler;

/**
* Indicates if stream should include "status" events, periodic events that
* update the client with the latest valid timestamp (in the event of a
Expand Down Expand Up @@ -226,10 +234,12 @@ export type FeedClientConfiguration = Required<
| "client_timeout_buffer_ms"
| "query_timeout_ms"
| "secret"
| "logger"
| "endpoint"
>
> & {
/**
* The underlying {@link HTTPClient} that will execute the actual HTTP calls
* The underlying {@link HTTPClient} that will execute the actual HTTP calls.
*/
httpClient: HTTPClient;

Expand Down
71 changes: 59 additions & 12 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
isHTTPResponse,
isStreamClient,
type HTTPClient,
HTTPResponse,
} from "./http-client";
import { Query } from "./query-builder";
import { TaggedTypeFormat } from "./tagged-type";
Expand Down Expand Up @@ -103,6 +104,8 @@ export class Client {
readonly #clientConfiguration: RequiredClientConfig;
/** The underlying {@link HTTPClient} client. */
readonly #httpClient: HTTPClient & Partial<HTTPStreamClient>;
/** A LogHandler instance. */
readonly #logger: LogHandler;
/** The last transaction timestamp this client has seen */
#lastTxnTs?: number;
/** true if this client is closed false otherwise */
Expand Down Expand Up @@ -135,6 +138,12 @@ export class Client {
logger: this.#getLogger(clientConfiguration),
};

if (clientConfiguration && clientConfiguration.logger) {
this.#logger = clientConfiguration.logger;
} else {
this.#logger = new ConsoleLogHandler(LOG_LEVELS.ERROR);
}

this.#validateConfiguration();

if (!httpClient) {
Expand Down Expand Up @@ -362,6 +371,7 @@ export class Client {
const streamClientConfig: StreamClientConfiguration = {
...this.#clientConfiguration,
httpStreamClient: streamClient,
logger: this.#logger,
...options,
};

Expand Down Expand Up @@ -438,6 +448,7 @@ export class Client {
const clientConfiguration: FeedClientConfiguration = {
...this.#clientConfiguration,
httpClient: this.#httpClient,
logger: this.#logger,
...options,
};

Expand Down Expand Up @@ -606,19 +617,34 @@ in an environmental variable named FAUNA_SECRET or pass it to the Client\
};
this.#setHeaders(requestConfig, headers);

const isTaggedFormat = requestConfig.format === "tagged";
const isTaggedFormat: boolean = requestConfig.format === "tagged";

const client_timeout_ms =
const client_timeout_ms: number =
requestConfig.query_timeout_ms +
this.#clientConfiguration.client_timeout_buffer_ms;
const method = "POST";
this.#logger.debug(
"Fauna HTTP %s Request to %s (timeout: %s), headers: %s",
method,
this.#clientConfiguration.endpoint.toString(),
client_timeout_ms.toString(),
JSON.stringify(headers),
);

const response = await this.#httpClient.request({
const response: HTTPResponse = await this.#httpClient.request({
client_timeout_ms,
data: queryRequest,
headers,
method: "POST",
method,
});

this.#logger.debug(
"Fauna HTTP Response %s from %s, headers: %s",
response.status,
this.#clientConfiguration.endpoint.toString(),
JSON.stringify(response.headers),
);

let parsedResponse;
try {
parsedResponse = {
Expand Down Expand Up @@ -764,6 +790,8 @@ export class StreamClient<T extends QueryValue = any> {
#streamAdapter?: StreamAdapter;
/** A saved copy of the EventSource once received */
#eventSource?: EventSource;
/** A LogHandler instance. */
#logger: LogHandler;

/**
*
Expand All @@ -785,6 +813,7 @@ export class StreamClient<T extends QueryValue = any> {
}

this.#clientConfiguration = clientConfiguration;
this.#logger = clientConfiguration.logger;

this.#validateConfiguration();
}
Expand Down Expand Up @@ -973,6 +1002,8 @@ export class FeedClient<T extends QueryValue = any> {
#query: () => Promise<EventSource>;
/** The event feed's client options */
#clientConfiguration: FeedClientConfiguration;
/** A LogHandler instance */
#logger: LogHandler;
/** The last `cursor` value received for the current page */
#lastCursor?: string;
/** A saved copy of the EventSource once received */
Expand Down Expand Up @@ -1001,6 +1032,7 @@ export class FeedClient<T extends QueryValue = any> {

this.#clientConfiguration = clientConfiguration;
this.#lastCursor = clientConfiguration.cursor;
this.#logger = clientConfiguration.logger;

this.#validateConfiguration();
}
Expand All @@ -1024,15 +1056,16 @@ export class FeedClient<T extends QueryValue = any> {

const headers = this.#getHeaders();

const client_timeout_ms: number =
this.#clientConfiguration.client_timeout_buffer_ms +
this.#clientConfiguration.query_timeout_ms;
const method: string = "POST";

const req: HTTPRequest<FeedRequest> = {
headers,
client_timeout_ms:
this.#clientConfiguration.client_timeout_buffer_ms +
this.#clientConfiguration.query_timeout_ms,
data: {
token: this.#eventSource.token,
},
method: "POST",
client_timeout_ms,
method,
data: { token: this.#eventSource.token },
path: FaunaAPIPaths.EVENT_FEED,
};

Expand Down Expand Up @@ -1069,12 +1102,26 @@ export class FeedClient<T extends QueryValue = any> {

const { httpClient } = this.#clientConfiguration;

const request = await this.#nextPageHttpRequest();
const request: HTTPRequest<FeedRequest> = await this.#nextPageHttpRequest();

this.#logger.debug(
"Fauna HTTP %s Request to %s (timeout: %s), headers: %s",
request.method,
this.#clientConfiguration.endpoint.toString(),
request.client_timeout_ms,
JSON.stringify(request.headers),
);
const response = await withRetries(() => httpClient.request(request), {
maxAttempts: this.#clientConfiguration.max_attempts,
maxBackoff: this.#clientConfiguration.max_backoff,
shouldRetry: (error) => error instanceof ThrottlingError,
});
this.#logger.debug(
"Fauna HTTP Response %s from %s, headers: %s",
response.status,
this.#clientConfiguration.endpoint.toString(),
JSON.stringify(response.headers),
);

let body: FeedSuccess<T> | FeedError;

Expand Down
2 changes: 1 addition & 1 deletion src/http-client/http-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export type HTTPRequest<T = QueryRequest> = {
headers: Record<string, string | undefined>;

/** HTTP method to use */
method: "POST";
method: string;

/** The path of the endpoint to call if not using the default */
path?: SupportedFaunaAPIPaths;
Expand Down
37 changes: 19 additions & 18 deletions src/util/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,26 @@ export type LogLevel = (typeof LOG_LEVELS)[keyof typeof LOG_LEVELS];
*/
export function parseDebugLevel(debug_level: string | undefined): LogLevel {
switch (debug_level) {
case LOG_LEVELS.TRACE:
case LOG_LEVELS.DEBUG:
case LOG_LEVELS.INFO:
case LOG_LEVELS.WARN:
case LOG_LEVELS.ERROR:
case LOG_LEVELS.FATAL:
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
return debug_level;
default:
return LOG_LEVELS.OFF;
}
}

export interface LogHandler {
trace(msg?: string, args?: string[]): void;
debug(msg?: string, args?: string[]): void;
info(msg?: string, args?: string[]): void;
warn(msg?: string, args?: string[]): void;
error(msg?: string, args?: string[]): void;
fatal(msg?: string, args?: string[]): void;
trace(msg: string, ...args: any[]): void;
debug(msg: string, ...args: any[]): void;
info(msg: string, ...args: any[]): void;
warn(msg: string, ...args: any[]): void;
error(msg: string, ...args: any[]): void;
fatal(msg: string, ...args: any[]): void;
}

export class ConsoleLogHandler implements LogHandler {
Expand All @@ -47,37 +48,37 @@ export class ConsoleLogHandler implements LogHandler {
this.#level = level;
}

trace(msg?: string, args?: string[]): void {
trace(msg: string, ...args: any[]): void {
if (this.#level >= LOG_LEVELS.TRACE) {
console.trace(msg, args);
}
}

debug(msg?: string, args?: string[]): void {
debug(msg: string, ...args: any[]): void {
if (this.#level >= LOG_LEVELS.DEBUG) {
console.debug(msg, args);
}
}

info(msg?: string, args?: string[]): void {
info(msg: string, ...args: any[]): void {
if (this.#level >= LOG_LEVELS.INFO) {
console.info(msg, args);
}
}

warn(msg?: string, args?: string[]): void {
warn(msg: string, ...args: any[]): void {
if (this.#level >= LOG_LEVELS.WARN) {
console.warn(msg, args);
}
}

error(msg?: string, args?: string[]): void {
error(msg: string, ...args: any[]): void {
if (this.#level >= LOG_LEVELS.ERROR) {
console.error(msg, args);
}
}

fatal(msg?: string, args?: string[]): void {
fatal(msg: string, args?: any[]): void {
if (this.#level >= LOG_LEVELS.FATAL) {
console.error(msg, args);
}
Expand Down

0 comments on commit 9cffc75

Please sign in to comment.