@@ -22,6 +22,8 @@ import {
2222} from '@zwave-js/core'
2323import { createDefaultTransportFormat } from '@zwave-js/core/bindings/log/node'
2424import { JSONTransport } from '@zwave-js/log-transport-json'
25+ import winston from 'winston'
26+ import DailyRotateFile from 'winston-daily-rotate-file'
2527import { isDocker } from './utils'
2628import {
2729 AssociationAddress ,
@@ -2318,14 +2320,8 @@ class ZwaveClient extends TypedEventEmitter<ZwaveClientEventCallbacks> {
23182320
23192321 utils . parseSecurityKeys ( this . cfg , zwaveOptions )
23202322
2321- const logTransport = new JSONTransport ( )
2322- logTransport . format = createDefaultTransportFormat ( true , false )
2323-
2324- zwaveOptions . logConfig . transports = [ logTransport ]
2325-
2326- logTransport . stream . on ( 'data' , ( data ) => {
2327- this . socket . emit ( socketEvents . debug , data . message . toString ( ) )
2328- } )
2323+ // Setup driver logging based on format setting
2324+ this . setupDriverLogging ( zwaveOptions )
23292325
23302326 try {
23312327 if ( shouldUpdateSettings ) {
@@ -6946,6 +6942,97 @@ class ZwaveClient extends TypedEventEmitter<ZwaveClientEventCallbacks> {
69466942 }
69476943 } , 1000 )
69486944 }
6945+
6946+ /**
6947+ * Setup driver logging based on the configured format (text or JSON)
6948+ * Uses the same logFormat setting as the gateway for consistency
6949+ */
6950+ private setupDriverLogging ( zwaveOptions : PartialZWaveOptions ) {
6951+ // Get the log format from gateway settings - this applies to both app and driver logging
6952+ const settings = jsonStore . get ( store . settings )
6953+ const logFormat = settings ?. gateway ?. logFormat || 'text'
6954+
6955+ if ( logFormat === 'json' ) {
6956+ // JSON logging for driver - create custom transports for all outputs
6957+ const transports = [ ]
6958+
6959+ // Custom console transport for JSON output
6960+ const jsonConsoleTransport = new winston . transports . Console ( {
6961+ format : winston . format . combine (
6962+ winston . format . timestamp ( ) ,
6963+ winston . format . json ( )
6964+ )
6965+ } )
6966+ transports . push ( jsonConsoleTransport )
6967+
6968+ // Custom file transport for JSON output (if file logging is enabled)
6969+ // Use DailyRotateFile to maintain symlink functionality and proper date handling
6970+ if ( this . cfg . logToFile ) {
6971+ const fileTransport = new DailyRotateFile ( {
6972+ filename : ZWAVEJS_LOG_FILE ,
6973+ auditFile : ZWAVEJS_LOG_FILE . replace ( '_%DATE%' , '_logrotate' ) . replace ( '.log' , '.json' ) ,
6974+ datePattern : 'YYYY-MM-DD' ,
6975+ createSymlink : true ,
6976+ symlinkName : 'zwavejs_current.log' ,
6977+ zippedArchive : true ,
6978+ maxFiles : `${ this . cfg . maxFiles || 7 } d` ,
6979+ maxSize : '50m' ,
6980+ format : winston . format . combine (
6981+ winston . format . timestamp ( ) ,
6982+ winston . format . json ( )
6983+ )
6984+ } )
6985+ transports . push ( fileTransport )
6986+ }
6987+
6988+ // Custom WebSocket transport for JSON output
6989+ const jsonTransport = new JSONTransport ( )
6990+ jsonTransport . format = winston . format . combine (
6991+ winston . format . timestamp ( ) ,
6992+ winston . format . json ( )
6993+ )
6994+ transports . push ( jsonTransport )
6995+
6996+ // Configure driver to use ONLY our custom transports
6997+ // Set logToFile: true to prevent the driver's internal console transport from being created
6998+ // Set forceConsole: false to ensure no internal console transport
6999+ // Redirect driver's internal file transport to /dev/null to prevent text logs
7000+ zwaveOptions . logConfig = {
7001+ ...zwaveOptions . logConfig ,
7002+ logToFile : true , // This prevents internal console transport creation
7003+ forceConsole : false , // This ensures no internal console transport
7004+ filename : '/dev/null' , // Redirect driver's internal file transport to /dev/null
7005+ transports : transports // Use ONLY our custom transports
7006+ }
7007+
7008+ // Stream JSON logs to WebSocket for debug view
7009+ jsonTransport . stream . on ( 'data' , ( data ) => {
7010+ this . socket . emit ( socketEvents . debug , data . message . toString ( ) )
7011+ } )
7012+
7013+ } else {
7014+ // Text logging for driver (preserve original behavior)
7015+ // Ensure console output by setting forceConsole: true when logToFile: true
7016+ // This matches the original behavior where console logs were visible
7017+ zwaveOptions . logConfig . forceConsole = true
7018+
7019+ // Only add JSONTransport for WebSocket streaming
7020+ const logTransport = new JSONTransport ( )
7021+ logTransport . format = createDefaultTransportFormat ( true , false )
7022+
7023+ // Add JSONTransport to existing transports instead of replacing them
7024+ if ( zwaveOptions . logConfig ?. transports ) {
7025+ zwaveOptions . logConfig . transports . push ( logTransport )
7026+ } else {
7027+ zwaveOptions . logConfig . transports = [ logTransport ]
7028+ }
7029+
7030+ // Stream text logs to WebSocket for debug view
7031+ logTransport . stream . on ( 'data' , ( data ) => {
7032+ this . socket . emit ( socketEvents . debug , data . message . toString ( ) )
7033+ } )
7034+ }
7035+ }
69497036}
69507037
69517038export default ZwaveClient
0 commit comments