@@ -11,6 +11,7 @@ import logging
1111import os
1212from pathlib import Path , PosixPath
1313import shutil
14+ import socket
1415from subprocess import Popen , PIPE , TimeoutExpired , run
1516import tempfile
1617import time
@@ -51,11 +52,34 @@ class Logger:
5152 self .json_output = {"result" : [],
5253 "log" : []}
5354 self .capture = capture
55+ self .socket = None
56+
57+ def connect_socket (self , port : int ):
58+ """Streams log updates via this socket for lightningd notifications.
59+ Used by the reckless-rpc plugin."""
60+ assert not self .socket
61+ self .socket = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
62+ try :
63+ self .socket .connect (('localhost' , port ))
64+ except Exception as e :
65+ logging .warning (f'socket failed to connect with { e } ' )
66+ self .socket = None
5467
5568 def str_esc (self , raw_string : str ) -> str :
5669 assert isinstance (raw_string , str )
5770 return json .dumps (raw_string )[1 :- 1 ]
5871
72+ def push_to_socket (self , to_log : str , prefix : str ):
73+ if not self .socket or self .socket .fileno () <= 0 :
74+ return
75+ try :
76+ self .socket .sendall (f'{ prefix } { to_log } \n ' .encode ('utf8' ))
77+ except Exception as e :
78+ if self .capture :
79+ self .json_output ['log' ].append (f'while feeding log to socket, encountered exception { e } ' )
80+ else :
81+ print (f'while feeding log to socket, encountered exception { e } ' )
82+
5983 def debug (self , to_log : str ):
6084 assert isinstance (to_log , str ) or hasattr (to_log , "__repr__" )
6185 if logging .root .level > logging .DEBUG :
@@ -65,6 +89,8 @@ class Logger:
6589 else :
6690 logging .debug (to_log )
6791
92+ self .push_to_socket (to_log , 'DEBUG: ' )
93+
6894 def info (self , to_log : str ):
6995 assert isinstance (to_log , str ) or hasattr (to_log , "__repr__" )
7096 if logging .root .level > logging .INFO :
@@ -74,6 +100,8 @@ class Logger:
74100 else :
75101 print (to_log )
76102
103+ self .push_to_socket (to_log , 'INFO: ' )
104+
77105 def warning (self , to_log : str ):
78106 assert isinstance (to_log , str ) or hasattr (to_log , "__repr__" )
79107 if logging .root .level > logging .WARNING :
@@ -83,6 +111,8 @@ class Logger:
83111 else :
84112 logging .warning (to_log )
85113
114+ self .push_to_socket (to_log , 'WARNING: ' )
115+
86116 def error (self , to_log : str ):
87117 assert isinstance (to_log , str ) or hasattr (to_log , "__repr__" )
88118 if logging .root .level > logging .ERROR :
@@ -92,6 +122,8 @@ class Logger:
92122 else :
93123 logging .error (to_log )
94124
125+ self .push_to_socket (to_log , 'ERROR: ' )
126+
95127 def add_result (self , result : Union [str , None ]):
96128 assert json .dumps (result ), "result must be json serializable"
97129 self .json_output ["result" ].append (result )
@@ -2432,6 +2464,8 @@ if __name__ == '__main__':
24322464 const = None )
24332465 p .add_argument ('-j' , '--json' , action = StoreTrueIdempotent ,
24342466 help = 'output in json format' )
2467+ p .add_argument ('--logging-port' , action = StoreIdempotent ,
2468+ help = 'lightning-rpc connects to this socket port to ingest log notifications' )
24352469
24362470 args = parser .parse_args ()
24372471 args = process_idempotent_args (args )
@@ -2481,6 +2515,10 @@ if __name__ == '__main__':
24812515 LIGHTNING_CONFIG = args .conf
24822516 RECKLESS_CONFIG = load_config (reckless_dir = str (RECKLESS_DIR ),
24832517 network = NETWORK )
2518+ if args .logging_port :
2519+ log .connect_socket (int (args .logging_port ))
2520+ else :
2521+ log .debug ('logging port argument not provided' )
24842522 GITHUB_COM = 'https://github.com'
24852523 # Used for blackbox testing to avoid hitting github servers
24862524 if 'REDIR_GITHUB' in os .environ :
0 commit comments