Skip to content

Commit 5bdb39c

Browse files
committed
Fix default logger issue - remove console as default, add logger param support
1 parent d810c3b commit 5bdb39c

4 files changed

Lines changed: 98 additions & 9 deletions

File tree

src/amqp-base-client.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export abstract class AMQPBaseClient {
2626
frameMax: number
2727
heartbeat: number
2828
onerror: (error: AMQPError) => void
29-
logger: Logger | null | undefined = console
29+
logger: Logger | undefined
3030
/** Used for string -> arraybuffer when publishing */
3131
readonly textEncoder: InstanceType<typeof TextEncoder> = new TextEncoder()
3232
// Buffer pool for publishes, let multiple microtasks publish at the same time but save on allocations
@@ -35,8 +35,9 @@ export abstract class AMQPBaseClient {
3535
/**
3636
* @param name - name of the connection, set in client properties
3737
* @param platform - used in client properties
38+
* @param logger - optional logger instance, defaults to undefined (no logging)
3839
*/
39-
constructor(vhost: string, username: string, password: string, name?: string, platform?: string, frameMax = 8192, heartbeat = 0, channelMax = 0) {
40+
constructor(vhost: string, username: string, password: string, name?: string, platform?: string, frameMax = 8192, heartbeat = 0, channelMax = 0, logger?: Logger | null) {
4041
this.vhost = vhost
4142
this.username = username
4243
this.password = ""
@@ -46,6 +47,7 @@ export abstract class AMQPBaseClient {
4647
})
4748
if (name) this.name = name // connection name
4849
if (platform) this.platform = platform
50+
this.logger = logger || undefined
4951
this.channels = [new AMQPChannel(this, 0)]
5052
this.onerror = (error: AMQPError) => this.logger?.error("amqp-client connection closed", error.message)
5153
if (frameMax < 8192) throw new Error("frameMax must be 8192 or larger")
@@ -318,7 +320,7 @@ export abstract class AMQPBaseClient {
318320
break
319321
}
320322
case 71: { // update-secret-ok
321-
console.info("AMQP connection update secret ok")
323+
this.logger?.info("AMQP connection update secret ok")
322324
this.onUpdateSecretOk?.()
323325
delete this.onUpdateSecretOk
324326
break

src/amqp-socket-client.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { AMQPBaseClient } from './amqp-base-client.js'
22
import { AMQPError } from './amqp-error.js'
33
import type { AMQPTlsOptions } from './amqp-tls-options.js'
4+
import type { Logger } from './types.js'
45
import { AMQPView } from './amqp-view.js'
56
import { Buffer } from 'buffer'
67
import * as net from 'net'
@@ -22,8 +23,10 @@ export class AMQPClient extends AMQPBaseClient {
2223

2324
/**
2425
* @param url - uri to the server, example: amqp://user:passwd@localhost:5672/vhost
26+
* @param tlsOptions - optional TLS options
27+
* @param logger - optional logger instance, defaults to null (no logging)
2528
*/
26-
constructor(url: string, tlsOptions?: AMQPTlsOptions) {
29+
constructor(url: string, tlsOptions?: AMQPTlsOptions, logger?: Logger | null) {
2730
const u = new URL(url)
2831
const vhost = decodeURIComponent(u.pathname.slice(1)) || "/"
2932
const username = decodeURIComponent(u.username) || "guest"
@@ -33,7 +36,7 @@ export class AMQPClient extends AMQPBaseClient {
3336
const heartbeat = parseInt(u.searchParams.get("heartbeat") || "0")
3437
const channelMax = parseInt(u.searchParams.get("channelMax") || "0")
3538
const platform = `${process.release.name} ${process.version} ${process.platform} ${process.arch}`
36-
super(vhost, username, password, name, platform, frameMax, heartbeat, channelMax)
39+
super(vhost, username, password, name, platform, frameMax, heartbeat, channelMax, logger)
3740
this.tls = u.protocol === "amqps:"
3841
this.tlsOptions = tlsOptions
3942
this.host = u.hostname || "localhost"

src/amqp-websocket-client.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { AMQPChannel } from './amqp-channel.js'
55
import { AMQPConsumer } from './amqp-consumer.js'
66
import { AMQPMessage } from './amqp-message.js'
77
import { AMQPQueue } from './amqp-queue.js'
8+
import type { Logger } from './types.js'
89

910
interface AMQPWebSocketInit {
1011
url: string
@@ -14,6 +15,7 @@ interface AMQPWebSocketInit {
1415
name?: string
1516
frameMax?: number
1617
heartbeat?: number
18+
logger?: Logger | null
1719
}
1820

1921
/**
@@ -28,20 +30,22 @@ export class AMQPWebSocketClient extends AMQPBaseClient {
2830

2931
/**
3032
* @param url to the websocket endpoint, example: wss://server/ws/amqp
33+
* @param logger - optional logger instance, defaults to null (no logging)
3134
*/
32-
constructor(url: string, vhost?: string, username?: string, password?: string, name?: string, frameMax?: number, heartbeat?: number);
35+
constructor(url: string, vhost?: string, username?: string, password?: string, name?: string, frameMax?: number, heartbeat?: number, logger?: Logger | null);
3336
constructor(init: AMQPWebSocketInit);
34-
constructor(url: string | AMQPWebSocketInit, vhost = "/", username = "guest", password = "guest", name?: string, frameMax = 8192, heartbeat = 0) {
37+
constructor(url: string | AMQPWebSocketInit, vhost = "/", username = "guest", password = "guest", name?: string, frameMax = 8192, heartbeat = 0, logger?: Logger | null) {
3538
if (typeof url === 'object') {
3639
vhost = url.vhost ?? vhost
3740
username = url.username ?? username
3841
password = url.password ?? password
3942
name = url.name ?? name
4043
frameMax = url.frameMax ?? frameMax
4144
heartbeat = url.heartbeat ?? heartbeat
45+
logger = url.logger ?? logger
4246
url = url.url
4347
}
44-
super(vhost, username, password, name, AMQPWebSocketClient.platform(), frameMax, heartbeat)
48+
super(vhost, username, password, name, AMQPWebSocketClient.platform(), frameMax, heartbeat, 0, logger)
4549
this.url = url
4650
this.frameBuffer = new Uint8Array(frameMax)
4751
}

test/test.ts

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { assert, expect, test, beforeEach, vi } from "vitest";
22
import { AMQPClient } from '../src/amqp-socket-client.js';
3+
import { AMQPWebSocketClient } from '../src/amqp-websocket-client.js';
34
import { AMQPMessage } from '../src/amqp-message.js';
45
import type { AMQPError } from "../src/amqp-error.js";
56

@@ -750,5 +751,84 @@ test('can bind queues in parallel', async () => {
750751
q.bind('test-exchange', 'quux:*'),
751752
])
752753

753-
await expect(Promise.resolve('success')).resolves.toBe('success')
754+
// Verify the test completed successfully - parallel binds worked without hanging
755+
expect(q.name).toBe('test-queue')
756+
})
757+
758+
test('should have no logger by default', () => {
759+
const amqp = getNewClient()
760+
expect(amqp.logger).toBeUndefined()
761+
})
762+
763+
test('should accept logger in AMQPClient constructor', () => {
764+
const mockLogger = {
765+
debug: vi.fn(),
766+
info: vi.fn(),
767+
warn: vi.fn(),
768+
error: vi.fn()
769+
}
770+
771+
const amqp = new AMQPClient("amqp://127.0.0.1", undefined, mockLogger)
772+
expect(amqp.logger).toBe(mockLogger)
773+
})
774+
775+
test('should accept logger in AMQPWebSocketClient constructor', () => {
776+
const mockLogger = {
777+
debug: vi.fn(),
778+
info: vi.fn(),
779+
warn: vi.fn(),
780+
error: vi.fn()
781+
}
782+
783+
const client = new AMQPWebSocketClient("wss://example.com/ws", undefined, undefined, undefined, undefined, undefined, undefined, mockLogger)
784+
expect(client.logger).toBe(mockLogger)
785+
})
786+
787+
test('should accept logger via AMQPWebSocketClient init object', () => {
788+
const mockLogger = {
789+
debug: vi.fn(),
790+
info: vi.fn(),
791+
warn: vi.fn(),
792+
error: vi.fn()
793+
}
794+
795+
const client = new AMQPWebSocketClient({
796+
url: "wss://example.com/ws",
797+
logger: mockLogger
798+
})
799+
expect(client.logger).toBe(mockLogger)
800+
})
801+
802+
test('should not log when logger is null', () => {
803+
const amqp = getNewClient()
804+
805+
// This should not throw even with null logger
806+
expect(() => {
807+
amqp.logger?.error("test message")
808+
amqp.logger?.warn("test message")
809+
amqp.logger?.info("test message")
810+
amqp.logger?.debug("test message")
811+
}).not.toThrow()
812+
})
813+
814+
test('should use provided logger when available', () => {
815+
const mockLogger = {
816+
debug: vi.fn(),
817+
info: vi.fn(),
818+
warn: vi.fn(),
819+
error: vi.fn()
820+
}
821+
822+
const amqp = new AMQPClient("amqp://127.0.0.1", undefined, mockLogger)
823+
824+
// Call logger methods directly (simulating how they're used in the code)
825+
amqp.logger?.error("error message")
826+
amqp.logger?.warn("warn message")
827+
amqp.logger?.info("info message")
828+
amqp.logger?.debug("debug message")
829+
830+
expect(mockLogger.error).toHaveBeenCalledWith("error message")
831+
expect(mockLogger.warn).toHaveBeenCalledWith("warn message")
832+
expect(mockLogger.info).toHaveBeenCalledWith("info message")
833+
expect(mockLogger.debug).toHaveBeenCalledWith("debug message")
754834
})

0 commit comments

Comments
 (0)