Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(configureable-logger): add support of configurable logger #164

Merged
merged 49 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
1e6ee2c
basic logger implementation
Apr 7, 2024
3ec0fc4
improve design of logger builder
Apr 8, 2024
d4b58d7
check for default configuration
Apr 8, 2024
778820c
added new design for logger
Apr 8, 2024
ea50f60
adding formating changes.
Apr 8, 2024
2e1174d
logger interceptor logic to Api Logger
Apr 8, 2024
b47366b
added core library suggestions
Apr 8, 2024
6bc642a
removed custom logger provider
Apr 8, 2024
8be7003
fixed compilation issue
Apr 8, 2024
f780a03
added changes to fix the import bug
Apr 8, 2024
672e64c
updated structure of params in Api logger
Apr 9, 2024
cd508e2
changes to resolve the latest comments on PR.
Apr 9, 2024
1153007
added changes of Logger Interface
Apr 15, 2024
615e709
added changes for sructured logging
Apr 15, 2024
ccd031d
updated Guid generator function
Apr 15, 2024
4fd56a3
added logging config into api logger
Apr 15, 2024
32294db
style fixes
Apr 15, 2024
b8b7de7
added finalized logging configuration structure
Apr 16, 2024
002f127
fixed style in api logger
Apr 16, 2024
f1e0ed0
Some additional refactoring work
Apr 16, 2024
9635c83
running style check
Apr 16, 2024
4e01486
fix style changes
Apr 16, 2024
61e7a6f
revert the responseValidationError
Apr 16, 2024
653d265
some more refactoring in apiLogger to fix code climate reported issues
Apr 16, 2024
e80d9ba
update refactored code with tests
Apr 17, 2024
7ddb6c5
remove loggingconfigurtion not needed any more
Apr 17, 2024
49f152f
more refactoring
Apr 17, 2024
a03431e
fixed some more quality and duplication issues
Apr 17, 2024
2725d44
reduce more duplication percentage
Apr 17, 2024
7253449
Reolve headers quality checks
Apr 17, 2024
440fbb6
Update requestBuilder.test.ts
MaryamAdnan3 Apr 17, 2024
afc150c
Update apiLogger.test.ts
MaryamAdnan3 Apr 17, 2024
43cbd77
modified customLogger and console logger behavior & added support for…
Apr 17, 2024
f3778ed
Merge branch 'configurable-logger-implementation' of https://github.c…
Apr 17, 2024
8a93670
Expose a different interface for sdk logger options and logger option…
Apr 18, 2024
0a7960c
Implement logging options interfaces and utilities.
thehappybug Apr 18, 2024
e2fabd0
update requesbuilder with feedback, clean more code in APILogger, fix…
Apr 19, 2024
411ce39
Add docblock comments for public methods interfaces
Apr 19, 2024
3ffa3cb
added implementation of whitelist headers and convert apilLogger.test…
Apr 19, 2024
63558a5
disabling code climate for logger classes
Apr 19, 2024
f230a5f
Update requestBuilder.test.ts
MaryamAdnan3 Apr 19, 2024
e34f1f9
remove sdk logging options as its not consumed anymore
Apr 22, 2024
1498596
resolve PR comments
Apr 22, 2024
55ffed1
rename headerstoWhiteList to headerstoWhitelist
Apr 22, 2024
cef07e1
update string template in APILogger to make hardcoded names consisten…
Apr 22, 2024
3783d7f
Update the string template for request and response logging and add a…
Apr 23, 2024
7101735
correct version update of core and core-interfaces
Apr 23, 2024
b0ed637
refactor error handling in RequestBuilder to collect error types and …
Apr 23, 2024
7ca8f6d
resolve PR comments
Apr 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ checks:
enabled: true
exclude_patterns:
- "scripts/"
- "**/core/src/logger/"
- "**/**/test/"
- "**/**/rollup.config.js"
- "**/**/tsconfig.json"
Expand Down
2 changes: 1 addition & 1 deletion packages/core-interfaces/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@apimatic/core-interfaces",
"author": "APIMatic Ltd.",
"version": "0.2.3",
"version": "0.2.4",
"license": "MIT",
"sideEffects": false,
"main": "lib/index.js",
Expand Down
1 change: 1 addition & 0 deletions packages/core-interfaces/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './httpInterceptor';
export * from './httpRequest';
export * from './httpResponse';
export * from './retryConfiguration';
export * from './logging';
131 changes: 131 additions & 0 deletions packages/core-interfaces/src/logging.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { HttpRequest } from './httpRequest';
import { HttpResponse } from './httpResponse';
/**
* Represents an interface for logging API requests and responses.
*/
export interface ApiLoggerInterface {
/**
* Logs the details of an HTTP request.
* @param request The HTTP request to log.
*/
logRequest(request: HttpRequest): void;

/**
* Logs the details of an HTTP response.
* @param response The HTTP response to log.
*/
logResponse(response: HttpResponse): void;
}

/**
* Represents an interface for a generic logger.
*/
export interface LoggerInterface {
/**
* Logs a message with a specified log level and additional parameters.
* @param level The log level of the message.
* @param message The message to log.
* @param params Additional parameters to include in the log message.
*/
log(level: LogLevel, message: string, params: Record<string, any>): void;
}

/**
* Represents options for configuring logging behavior.
*/
export interface LoggingOptions {
/**
* The logger to use for logging messages.
*/
logger: LoggerInterface;

/**
* The log level to determine which messages should be logged.
*/
logLevel: LogLevel;

/**
* Options for logging HTTP requests.
*/
logRequest: HttpRequestLoggingOptions;

/**
* Options for logging HTTP responses.
*/
logResponse: HttpMessageLoggingOptions;

/**
* Indicates whether sensitive headers should be masked in logged messages.
*/
maskSensitiveHeaders: boolean;
}

/**
* Represents options for logging HTTP message details.
*/
export interface HttpMessageLoggingOptions {
/**
* Indicates whether the message body should be logged.
*/
logBody: boolean;

/**
* Indicates whether the message headers should be logged.
*/
logHeaders: boolean;

/**
* Array of headers not to be displayed in logging.
*/
headersToExclude: string[];

/**
* Array of headers to be displayed in logging.
*/
headersToInclude: string[];

/**
* Array of headers which values are non-senstive to display in logging.
*/
headersToWhitelist: string[];
}

/**
* Represents options for logging HTTP request details.
*/
export interface HttpRequestLoggingOptions extends HttpMessageLoggingOptions {
/**
* Indicates whether the request query parameters should be included in the logged URL.
*/
includeQueryInPath: boolean;
}

/**
* Enum representing different log levels.
*/
export enum LogLevel {
/**
* Error log level.
*/
Error = 'error',

/**
* Warning log level.
*/
Warn = 'warn',

/**
* Information log level.
*/
Info = 'info',

/**
* Debug log level.
*/
Debug = 'debug',

/**
* Trace log level.
*/
Trace = 'trace',
}
4 changes: 3 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@apimatic/core",
"author": "APIMatic Ltd.",
"version": "0.10.5",
"version": "0.10.6",
"license": "MIT",
"sideEffects": false,
"main": "lib/index.js",
Expand Down Expand Up @@ -45,6 +45,7 @@
"@size-limit/preset-small-lib": "^7.0.8",
"@types/detect-node": "^2.0.0",
"@types/lodash.flatmap": "^4.5.6",
"@types/lodash.defaultsdeep": "^4.6.9",
"abort-controller": "^3.0.0",
"babel-plugin-annotate-pure-calls": "^0.4.0",
"jest": "^26.4.2",
Expand All @@ -70,6 +71,7 @@
"form-data": "^3.0.0",
"json-ptr": "^3.1.0",
"lodash.flatmap": "^4.5.0",
"lodash.defaultsdeep": "^4.6.1",
"tiny-warning": "^1.0.3",
"tslib": "^2.1.0"
},
Expand Down
77 changes: 57 additions & 20 deletions packages/core/src/http/requestBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
HttpInterceptorInterface,
RequestOptions,
RetryConfiguration,
ApiLoggerInterface,
} from '../coreInterfaces';
import { ArgumentsValidationError } from '../errors/argumentsValidationError';
import { ResponseValidationError } from '../errors/responseValidationError';
Expand Down Expand Up @@ -90,11 +91,17 @@ export type ApiErrorConstructor = new (
message: string
) => any;

export interface ErrorType<ErrorCtorArgs extends any[]> {
statusCode: number | [number, number];
errorConstructor: new (response: HttpContext, ...args: ErrorCtorArgs) => any;
isTemplate?: boolean;
args: ErrorCtorArgs;
}

export interface ApiErrorFactory {
apiErrorCtor: ApiErrorConstructor;
message?: string | undefined;
}

export interface RequestBuilder<BaseUrlParamType, AuthParams> {
deprecated(methodName: string, message?: string): void;
prepareArgs: typeof prepareArgs;
Expand Down Expand Up @@ -205,6 +212,7 @@ export class DefaultRequestBuilder<BaseUrlParamType, AuthParams>
protected _authParams?: AuthParams;
protected _retryOption: RequestRetryOption;
protected _apiErrorFactory: ApiErrorFactory;
protected _errorTypes: Array<ErrorType<any>>;
public prepareArgs: typeof prepareArgs;

constructor(
Expand All @@ -215,16 +223,21 @@ export class DefaultRequestBuilder<BaseUrlParamType, AuthParams>
protected _httpMethod: HttpMethod,
protected _xmlSerializer: XmlSerializerInterface,
protected _retryConfig: RetryConfiguration,
protected _path?: string
protected _path?: string,
protected _apiLogger?: ApiLoggerInterface
) {
this._headers = {};
this._query = [];
this._interceptors = [];
this._errorTypes = [];
this._validateResponse = true;
this._apiErrorFactory = { apiErrorCtor: _apiErrorCtr };
this._addResponseValidator();
this._addAuthentication();
this._addRetryInterceptor();
this._addErrorHandlingInterceptor();
this._addApiLoggerInterceptors();

this._retryOption = RequestRetryOption.Default;
this.prepareArgs = prepareArgs.bind(this);
}
Expand Down Expand Up @@ -427,22 +440,7 @@ export class DefaultRequestBuilder<BaseUrlParamType, AuthParams>
isTemplate?: boolean,
...args: ErrorCtorArgs
): void {
this.interceptResponse((context) => {
const { response } = context;
if (isTemplate && args.length > 0) {
args[0] = updateErrorMessage(args[0], response);
}
if (
(typeof statusCode === 'number' &&
response.statusCode === statusCode) ||
(typeof statusCode !== 'number' &&
response.statusCode >= statusCode[0] &&
response.statusCode <= statusCode[1])
) {
throw new errorConstructor(context, ...args);
}
return context;
});
this._errorTypes.push({ statusCode, errorConstructor, isTemplate, args });
}
public async call(
requestOptions?: RequestOptions
Expand Down Expand Up @@ -582,12 +580,27 @@ export class DefaultRequestBuilder<BaseUrlParamType, AuthParams>
return context;
});
}

private _addApiLoggerInterceptors(): void {
if (this._apiLogger) {
const apiLogger = this._apiLogger;

this.intercept(async (request, options, next) => {
apiLogger.logRequest(request);
const context = await next(request, options);
apiLogger.logResponse(context.response);
return context;
});
}
}

private _addAuthentication() {
this.intercept((...args) => {
const handler = this._authenticationProvider(this._authParams);
return handler(...args);
});
}

private _addRetryInterceptor() {
this.intercept(async (request, options, next) => {
let context: HttpContext | undefined;
Expand Down Expand Up @@ -633,6 +646,28 @@ export class DefaultRequestBuilder<BaseUrlParamType, AuthParams>
return { request, response: context.response };
});
}

private _addErrorHandlingInterceptor() {
this.interceptResponse((context) => {
const { response } = context;
for (const { statusCode, errorConstructor, isTemplate, args } of this
._errorTypes) {
if (
(typeof statusCode === 'number' &&
response.statusCode === statusCode) ||
(typeof statusCode !== 'number' &&
response.statusCode >= statusCode[0] &&
response.statusCode <= statusCode[1])
) {
if (isTemplate && args.length > 0) {
args[0] = updateErrorMessage(args[0], response);
}
throw new errorConstructor(context, ...args);
}
}
return context;
});
}
}

export function createRequestBuilderFactory<BaseUrlParamType, AuthParams>(
Expand All @@ -641,7 +676,8 @@ export function createRequestBuilderFactory<BaseUrlParamType, AuthParams>(
apiErrorConstructor: ApiErrorConstructor,
authenticationProvider: AuthenticatorInterface<AuthParams>,
retryConfig: RetryConfiguration,
xmlSerializer: XmlSerializerInterface = new XmlSerialization()
xmlSerializer: XmlSerializerInterface = new XmlSerialization(),
apiLogger?: ApiLoggerInterface
): RequestBuilderFactory<BaseUrlParamType, AuthParams> {
return (httpMethod, path?) => {
return new DefaultRequestBuilder(
Expand All @@ -652,7 +688,8 @@ export function createRequestBuilderFactory<BaseUrlParamType, AuthParams>(
httpMethod,
xmlSerializer,
retryConfig,
path
path,
apiLogger
);
};
}
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export * from './http/httpInterceptor';
export * from './http/requestBuilder';
export * from './http/pathTemplate';
export { RequestRetryOption } from './http/retryConfiguration';
export * from './logger/apiLogger';
export * from './logger/defaultLogger';
export * from './logger/nullLogger';
export * from './logger/defaultLoggingConfiguration';
export * from './logger/loggingOptions';
export {
indexedPrefix,
unindexedPrefix,
Expand Down
Loading
Loading