Skip to content

Bugfix: Add debug option to log response headers#219

Open
asein-sinch wants to merge 14 commits into
v1.5-nextfrom
Bugfix_Add-debug-option-to-log-response-headers
Open

Bugfix: Add debug option to log response headers#219
asein-sinch wants to merge 14 commits into
v1.5-nextfrom
Bugfix_Add-debug-option-to-log-response-headers

Conversation

@asein-sinch

@asein-sinch asein-sinch commented Dec 2, 2025

Copy link
Copy Markdown
Collaborator

How to enable debug logs:

import winston from 'winston';
const winstonLogger = winston.createLogger({
  level: 'debug',
  transports: [new winston.transports.Console()],
  format: winston.format.logstash(),
});

new SinchClient({ projectId, keyId, keySecret, logger:  winstonLogger});

Debug logs:

[Sinch SDK][Debug][AvailableRegionsApi][ListAvailableRegions][401]
HTTP method: GET
URL: https://numbers.api.sinch.com/v1/projects/37b62a7b-0177-429a-bb0b-e10f848de0b8/availableRegions?types=LOCAL&types=MOBILE
Response Headers:  Headers {
  [Symbol(map)]: [Object: null prototype] {
    'www-authenticate': [
      'Bearer error="invalid_token", error_description="Jwt expired at 2023-10-02T14:57:08Z", error_uri="https://tools.ietf.org/html/rfc6750#section-3.1"'
    ],
    'cache-control': [ 'no-cache, no-store, max-age=0, must-revalidate' ],
    pragma: [ 'no-cache' ],
    expires: [ '0' ],
    'x-content-type-options': [ 'nosniff' ],
    'strict-transport-security': [ 'max-age=31536000 ; includeSubDomains' ],
    'x-frame-options': [ 'DENY' ],
    'x-xss-protection': [ '0' ],
    'referrer-policy': [ 'no-referrer' ],
    'x-envoy-upstream-service-time': [ '2' ],
    date: [ 'Tue, 02 Dec 2025 22:25:38 GMT' ],
    server: [ 'istio-envoy' ],
    connection: [ 'close' ],
    'content-length': [ '0' ]
  }
}


private debug(context: ResponsePluginContext) {
if (context.requestOptions.logHeadersOnError && !context.response?.ok) {
console.debug(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should think about supporting also for this SDK a logger interface.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added logger

context.response?.headers,
if (!context.response?.ok) {
this.logger.debug(
`[Sinch SDK][Debug][${context.apiName}][${context.operationId}][${context.response?.status}]\nHTTP method: ${context.requestOptions.method}\nURL: ${context.url}\nResponse Headers: ${this.formatHeaders(context.response?.headers)}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about having the logger itself adding these formatting information ?

  • this.logger: will know "it is" SDK -> it will add it when emitting log
  • this.logger.debug: logger.debug function will know it is debug level then it will be added when emitting log

PROS:

  • all calls to logger will be prefixed by same ... prefix
  • all calls to logger./debug/info/..will have same prefix regarding log level
  • all logs will have same pattern [Sinch SDK][level] and no human error to forgot them services will call logger function

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@asein-sinch asein-sinch requested a review from JPPortier December 3, 2025 18:35
Comment thread packages/sdk-client/src/logger/logger.ts
asein-sinch and others added 4 commits June 11, 2026 10:27
Use global console for SinchLogger fallbacks so tests can spy on warnings, and drop unused OAuth2 token request logger after v1.5-next error handling.
@Hurus111 Hurus111 force-pushed the Bugfix_Add-debug-option-to-log-response-headers branch from fe7b383 to 71c6593 Compare June 11, 2026 08:52
@Hurus111 Hurus111 changed the base branch from v1.2 to v1.5-next June 11, 2026 09:01
@Hurus111 Hurus111 requested a review from JPPortier June 12, 2026 07:27
this.lazyClient.getApiClient();
} catch (error) {
console.error('Impossible to assign the new credentials to the SMS API');
new SinchLogger(this.lazyClient.sharedConfig.logger ?? console).error(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we are assuming we have to send a log onto console even if configuration could have been, by purpose of SDK user, to NOT have any logger (multliple times)

What do you think :

  • either we assume there is, by contract, a logger defined
  • test if null/undefined and do not log anything

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed 🟡
Removed all ?? console fallbacks; call sites use resolveLogger(...). logger: null → silent NOOP_LOGGER.
packages/sms/src/rest/v1/sms-domain-api.ts (and all other *-service.ts / *-domain-api.ts)

Comment thread packages/sdk-core/src/sinch-client.ts Outdated
* @param {SinchClientParameters} params - The object containing the Sinch credentials.
*/
constructor(params: SinchClientParameters) {
if (!params.logger) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment about using or not a default logger.
What if for any purpose an end user do not want any log ? (thinking about a logging call causing an issue)
It won't be possible.
We could have distinction between null VS undefined to provide

  • null -> a dummy logger not logging anything
  • undefined -> a default logger based onto init of SinchLogger

And, by contract we could remove all validation against not defined logger. e.g.: https://github.com/sinch/sinch-sdk-node/pull/219/changes#diff-85a0299065d0f2bd71e5151e1983edb3447d2d9770692d9f8ac007467246bc20R69

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed 🟡

  • null -> silent
  • undefined -> default console

packages/sdk-core/src/sinch-client.ts resolved once via resolveLogger() in SinchClient and each Service constructor.

): PluginRunner<V | Record<string, unknown>, V> {
return {
transform: (res: V) => {
this.debug(context);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔
Not a big fan to have a dependency onto logger/SinchLogger here.
Finally: it is "just" a container.

We could think about who should be responsible of logging.
Here, not sure a "simple" container should log itself something.
It is an exception response. Why not having transport layer performing the log itself and removing dependency onto any logger here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed 🟡
Logger removed from ExceptionResponse. Failed HTTP debug logging moved to ApiFetchClient.
packages/sdk-client/src/client/api-fetch-client.ts

Comment on lines +1 to +6
export interface Logger {
debug(message: string, ...meta: any[]): void;
info(message: string, ...meta: any[]): void;
warn(message: string, ...meta: any[]): void;
error(message: string, ...meta: any[]): void;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could imagine, for performance/memory consumption purpose having interface defining a callback called by logger when the message will be really send.
Then; it will avoid to format message before calling logger which will finally decide to not log anything because of required severity is not reached.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done 🟢
Logger methods now accept either a plain string or a callback () => string. The SDK builds the message only when the logger actually emits it.

...SupportedMailgunRegion,
};

export interface LoggerParameters {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strictly speaking; this is nor defining "logger parameters" but the logger itself

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed 🟡
Renamed to WithLogger

@Hurus111 Hurus111 requested a review from JPPortier June 15, 2026 14:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants