@@ -37,6 +37,7 @@ def __init__(self, env=None, cwd=None):
3737 else :
3838 self ._env .pop (k , None )
3939
40+ self .log_file_creation_failed = False
4041 self ._configure_logging ()
4142 enabled = self ._env .get ("_APPMAP" , "false" )
4243 self ._enabled = enabled is None or enabled .lower () != "false"
@@ -133,6 +134,21 @@ def display_params(self):
133134 def getLogger (self , name ) -> trace_logger .TraceLogger :
134135 return cast (trace_logger .TraceLogger , logging .getLogger (name ))
135136
137+ def determine_log_file (self ):
138+ log_file = "appmap.log"
139+
140+ # Try creating the log file in the current directory
141+ try :
142+ with open (log_file , 'a' , encoding = 'UTF8' ):
143+ pass
144+ except IOError :
145+ # The circumstances in which creation is going to fail
146+ # are also those in which the user doesn't care whether
147+ # there's a log file (e.g. when starting a REPL).
148+ return None
149+ return log_file
150+
151+
136152 def _configure_logging (self ):
137153 trace_logger .install ()
138154
@@ -179,13 +195,19 @@ def _configure_logging(self):
179195 log_level = self .get ("APPMAP_LOG_LEVEL" , "info" ).upper ()
180196 loggers = config_dict ["loggers" ]
181197 loggers ["appmap" ]["level" ] = loggers ["_appmap" ]["level" ] = log_level
198+
199+ log_file = self .determine_log_file ()
200+ # Use NullHandler if log_file is None to avoid complicating the configuration
201+ # with the absence of the "default" handler.
182202 config_dict ["handlers" ] = {
183203 "default" : {
184204 "class" : "logging.handlers.RotatingFileHandler" ,
185205 "formatter" : "default" ,
186- "filename" : "appmap.log" ,
206+ "filename" : log_file ,
187207 "maxBytes" : 50 * 1024 * 1024 ,
188208 "backupCount" : 1 ,
209+ } if log_file is not None else {
210+ "class" : "logging.NullHandler"
189211 },
190212 "stderr" : {
191213 "class" : "logging.StreamHandler" ,
@@ -194,6 +216,7 @@ def _configure_logging(self):
194216 "stream" : "ext://sys.stderr" ,
195217 },
196218 }
219+ self .log_file_creation_failed = log_file is None
197220
198221 if log_config is not None :
199222 name , level = log_config .split ("=" , 2 )
@@ -213,3 +236,7 @@ def initialize(**kwargs):
213236 Env .reset (** kwargs )
214237 logger = logging .getLogger (__name__ )
215238 logger .info ("appmap enabled: %s" , Env .current .enabled )
239+ if Env .current .log_file_creation_failed :
240+ # Writing to stderr makes the REPL fail in vscode-python.
241+ # https://github.com/microsoft/vscode-python/blob/c71c85ebf3749d5fac76899feefb21ee321a4b5b/src/client/common/process/rawProcessApis.ts#L268-L269
242+ logger .info ("appmap.log cannot be created" )
0 commit comments