Skip to content

Commit 6b26c57

Browse files
committed
[#373] gRPC Logger
1 parent c654eaa commit 6b26c57

File tree

7 files changed

+89
-15
lines changed

7 files changed

+89
-15
lines changed

lib/client/grpc-data-sender.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const { logError } = require('./grpc-errors')
2525
const StreamDeadlineOptionsBuilder = require('./stream-deadline-options-builder')
2626
const GrpcReadableStreamBuilder = require('./grpc-readable-stream-builder')
2727
const UnaryDeadlineOptionsBuilder = require('./unary-deadline-options-builder')
28+
const { LogBuilder } = require('../utils/log/log-builder')
2829

2930
// AgentInfoSender.java
3031
// refresh daily
@@ -38,6 +39,7 @@ class GrpcDataSender {
3839
this.collectorTcpPort = collectorTcpPort
3940
this.collectorStatPort = collectorStatPort
4041
this.collectorSpanPort = collectorSpanPort
42+
this.logger = log.getLogger(LogBuilder.buildGrpcLog())
4143

4244
this.unaryDeadlineOptionsBuilder = new UnaryDeadlineOptionsBuilder()
4345
this.initializeClients()
@@ -256,7 +258,7 @@ class GrpcDataSender {
256258
this.spanStream.push(pSpanChunk)
257259
} catch (e) {
258260
if (e && e.stack) {
259-
log.error(`sendSpanChunk(spanChunk) Error: ${e.stack}`)
261+
this.logger.error(`sendSpanChunk(spanChunk) Error: ${e.stack}`)
260262
}
261263
}
262264
}
@@ -271,7 +273,7 @@ class GrpcDataSender {
271273
this.statStream.push(pStatMessage)
272274
} catch (e) {
273275
if (e && e.stack) {
274-
log.error('sendStat(stat) Error: ', e)
276+
this.logger.error('sendStat(stat) Error: ', e)
275277
}
276278
}
277279
}
@@ -282,8 +284,8 @@ class GrpcDataSender {
282284
}
283285

284286
const pCmdMessage = CommandType.supportedServicesCommandMessage()
285-
if (log.isDebug()) {
286-
log.debug(`sendControlHandshake pCmdMessage: `, pCmdMessage.toObject())
287+
if (this.logger.isDebug()) {
288+
this.logger.debug(`sendControlHandshake pCmdMessage: `, pCmdMessage.toObject())
287289
}
288290
this.commandStream.push(pCmdMessage)
289291
}
@@ -361,7 +363,7 @@ class GrpcDataSender {
361363
let options = this.unaryDeadlineOptionsBuilder.build()
362364
this.profilerClient.commandEcho(commandEchoResponse, options, (err, response) => {
363365
if (err) {
364-
log.error(err)
366+
this.logger.error(err)
365367
}
366368
if (callback) {
367369
callback(err, response)

lib/client/grpc-errors.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,26 @@
88

99
const grpc = require('@grpc/grpc-js')
1010
const log = require('../utils/log/logger')
11+
const { LogBuilder } = require('../utils/log/log-builder')
1112

13+
let logger = null
1214
function logError(message, error) {
1315
if (!error) {
1416
return
1517
}
1618

19+
if (!logger) {
20+
logger = log.getLogger(LogBuilder.buildGrpcLog())
21+
}
22+
1723
if (isCancelledError(error)) {
18-
log.error(`Pinpoint Collector has been shut down : ${message}`)
24+
logger.error(`Pinpoint Collector has been shut down : ${message}`)
1925
} else if (isUnavailableError(error)) {
20-
log.error(`Pinpoint Collector is gRPC connection unavailable : ${message}`)
26+
logger.error(`Pinpoint Collector is gRPC connection unavailable : ${message}`)
2127
} else if (isDeadlineExceededError(error)) {
22-
log.error(`gRPC Stream deadline exceeded : ${message}`, error)
28+
logger.error(`gRPC Stream deadline exceeded : ${message}`, error)
2329
} else {
24-
log.error(message, error)
30+
logger.error(message, error)
2531
}
2632
}
2733

lib/client/grpc-readable-stream.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
const { Transform } = require('node:stream')
1010
const log = require('../utils/log/logger')
1111
const { logError } = require('./grpc-errors')
12+
const { LogBuilder } = require('../utils/log/log-builder')
1213

1314
const maxAttempts = 3
1415
const initialBackoff = 1000
@@ -20,6 +21,7 @@ class GrpcReadableStream {
2021
this.readableStream = this.makeReadableStream()
2122
this.name = options.name ?? ''
2223
this.pipeWritableStream()
24+
this.logger = log.getLogger(LogBuilder.buildGrpcLog())
2325
}
2426

2527
makeReadableStream() {
@@ -95,7 +97,7 @@ class GrpcReadableStream {
9597
this.writableStream = writableStream
9698
} catch (error) {
9799
if(error?.message !== 'Channel has been shut down') {
98-
log.error('error in pipeWritableStream', error)
100+
this.logger.error('error in pipeWritableStream', error)
99101
}
100102
this.lazyPipeWritableStream(retryCount + 1)
101103
}

lib/client/grpc-writable-stream-builder.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
const { logError } = require('./grpc-errors')
1010
const ExponentialBackoffRetryBuilder = require('./exponential-backoff-retry-builder')
1111
const log = require('../utils/log/logger')
12+
const { LogBuilder } = require('../utils/log/log-builder')
1213

1314
class GrpcWritableStream {
1415
constructor(makeWritableStream) {
@@ -21,6 +22,7 @@ class GrpcWritableStream {
2122
}).setRetryCallback(() => {
2223
this.connect()
2324
}).build()
25+
this.logger = log.getLogger(LogBuilder.buildGrpcLog())
2426
}
2527

2628
connect() {
@@ -43,7 +45,7 @@ class GrpcWritableStream {
4345

4446
if (error) {
4547
if (error.code === 13) {
46-
log.warn('Warning: Collector returned 13 INTERNAL error. Too much Span data may be sent. Try increasing PINPOINT_SAMPLING_RATE to reduce traffic. https://github.com/pinpoint-apm/pinpoint-node-agent/issues/317')
48+
this.logger.warn('Warning: Collector returned 13 INTERNAL error. Too much Span data may be sent. Try increasing PINPOINT_SAMPLING_RATE to reduce traffic. https://github.com/pinpoint-apm/pinpoint-node-agent/issues/317')
4749
}
4850
logError('clientService callback in GrpcWritableStreamBuilder', error)
4951
this.backoffRetry.retry()

lib/utils/log/log-builder.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ class Log {
5353
}
5454

5555
class LogBuilder {
56+
static buildGrpcLog() {
57+
return new LogBuilder('grpcLogger').build()
58+
}
59+
5660
static createDefaultLogBuilder() {
5761
return new LogBuilder('default-logger')
5862
}
@@ -154,5 +158,6 @@ class LogBuilder {
154158

155159
module.exports = {
156160
LogBuilder,
157-
LogLevel
161+
LogLevel,
162+
Log
158163
}

lib/utils/log/logger.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
'use strict'
88

99
const loglevel = require('loglevel')
10-
const { LogBuilder, LogLevel: Level } = require('./log-builder')
10+
const { LogBuilder, LogLevel: Level, Log } = require('./log-builder')
1111

1212
class Logging {
1313
constructor(loglevel, log) {
@@ -105,11 +105,15 @@ class Logger extends Logging {
105105
}
106106

107107
getLogger(log) {
108-
if (typeof log?.getName !== 'function') {
108+
if (!(log instanceof Log) && typeof log !== 'string') {
109109
return this
110110
}
111111

112-
const logName = log.getName()
112+
if (typeof log === 'string' && !this.loggers.has(log)) {
113+
return this
114+
}
115+
116+
const logName = log.getName?.() ?? (typeof log === 'string' ? log : LogBuilder.createDefaultLogBuilder().build().getName())
113117
if (!this.loggers.has(logName)) {
114118
this.loggers.set(logName, new ChildLogger(this.loglevel.getLogger(logName), log))
115119
}

test/utils/log/logger.test.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,4 +474,57 @@ test('PINPOINT_LOGGER_LEVELS environment variable log levels', (t) => {
474474
t.ok(noLevelAppenderMessages2[2].includes('NO-LEVEL-APPENDER2 INFO: info message'), 'NO-LEVEL appender 2 should receive info message from grpc logger')
475475
t.ok(noLevelAppenderMessages2[3].includes('NO-LEVEL-APPENDER2 WARN: warn message'), 'NO-LEVEL appender 2 should receive warn message from grpc logger')
476476
t.ok(noLevelAppenderMessages2[4].includes('NO-LEVEL-APPENDER2 ERROR: error message'), 'NO-LEVEL appender 2 should receive error message from grpc logger')
477+
})
478+
479+
test('getLogger with string parameter should return existing logger', (t) => {
480+
t.plan(4)
481+
482+
// Create a logger with LogBuilder first
483+
const logName = 'test-string-logger'
484+
const originalLogger = log.getLogger(new LogBuilder(logName).logLevelDebug().build())
485+
486+
// Get logger with string parameter - should return the existing logger
487+
const stringLogger = log.getLogger(logName)
488+
489+
t.equal(stringLogger, originalLogger, 'getLogger with string should return the same instance')
490+
t.equal(stringLogger.name, logName, 'Logger name should match')
491+
492+
// Test with another logger to ensure it works for multiple loggers
493+
const logName2 = 'test-string-logger-2'
494+
const originalLogger2 = log.getLogger(new LogBuilder(logName2).logLevelInfo().build())
495+
const stringLogger2 = log.getLogger(logName2)
496+
497+
t.equal(stringLogger2, originalLogger2, 'getLogger with string should return the same instance for second logger')
498+
t.equal(stringLogger2.name, logName2, 'Second logger name should match')
499+
})
500+
501+
test('getLogger with string parameter for non-existing logger', (t) => {
502+
t.plan(2)
503+
504+
// Try to get a logger that doesn't exist with string parameter
505+
const nonExistentLogName = 'non-existent-logger'
506+
const logger = log.getLogger(nonExistentLogName)
507+
508+
t.ok(logger, 'Logger should be created even if it did not exist before')
509+
t.equal(logger.name, 'default-logger', 'Logger should have default name since it was created without LogBuilder')
510+
})
511+
512+
test('getLogger caching behavior with string and LogBuilder', (t) => {
513+
t.plan(3)
514+
515+
const logName = 'cache-test-logger'
516+
517+
// First, get logger with string (non-existing)
518+
const firstLogger = log.getLogger(logName)
519+
520+
// Then, get logger with LogBuilder with same name
521+
const secondLogger = log.getLogger(new LogBuilder(logName).logLevelWarn().build())
522+
523+
// Then, get logger with string again
524+
const thirdLogger = log.getLogger(logName)
525+
526+
// All should be the same instance due to caching
527+
t.notEqual(firstLogger, secondLogger, 'Logger is different instances when no created with LogBuilder first')
528+
t.equal(secondLogger, thirdLogger, 'Logger obtained again with string should be the same instance')
529+
t.equal(firstLogger.name, 'default-logger', 'Logger is not created with LogBuilder first has default name')
477530
})

0 commit comments

Comments
 (0)