{"id":3985,"date":"2026-07-30T03:44:06","date_gmt":"2026-07-30T03:44:06","guid":{"rendered":"https:\/\/tucumandevelopers.com\/index.php\/2026\/07\/30\/how-staypresents-logging-works-without-breaking-yours\/"},"modified":"2026-07-30T03:44:06","modified_gmt":"2026-07-30T03:44:06","slug":"how-staypresents-logging-works-without-breaking-yours","status":"publish","type":"post","link":"https:\/\/tucumandevelopers.com\/index.php\/2026\/07\/30\/how-staypresents-logging-works-without-breaking-yours\/","title":{"rendered":"How StayPresent&#8217;s Logging Works (Without Breaking Yours)"},"content":{"rendered":"<div>\n<div><\/div>\n<p>Turn it down in a quiet production environment: <\/p>\n<div>\n<pre><code><span>logging<\/span><span>.<\/span><span>getLogger<\/span><span>(<\/span><span>\"<\/span><span>staypresent<\/span><span>\"<\/span><span>).<\/span><span>setLevel<\/span><span>(<\/span><span>logging<\/span><span>.<\/span><span>WARNING<\/span><span>)<\/span> <\/code><\/pre>\n<div>\n<\/p><\/div>\n<\/p><\/div>\n<p>This setting only affects StayPresent&#8217;s own log output \u2014 it has no effect on your bot&#8217;s separate loggers, and vice versa.<\/p>\n<h2> <a name=\"attaching-your-own-handler\" href=\"#attaching-your-own-handler\"> <\/a> Attaching Your Own Handler <\/h2>\n<p>Since it&#8217;s a real logger object, you can attach additional handlers \u2014 to forward StayPresent&#8217;s events to a file, a monitoring service, or a Discord webhook, for example: <\/p>\n<div>\n<pre><code><span>import<\/span> <span>logging<\/span> <span>file_handler<\/span> <span>=<\/span> <span>logging<\/span><span>.<\/span><span>FileHandler<\/span><span>(<\/span><span>\"<\/span><span>staypresent.log<\/span><span>\"<\/span><span>)<\/span> <span>file_handler<\/span><span>.<\/span><span>setFormatter<\/span><span>(<\/span><span>logging<\/span><span>.<\/span><span>Formatter<\/span><span>(<\/span><span>\"<\/span><span>%(asctime)s %(levelname)s %(message)s<\/span><span>\"<\/span><span>))<\/span> <span>logging<\/span><span>.<\/span><span>getLogger<\/span><span>(<\/span><span>\"<\/span><span>staypresent<\/span><span>\"<\/span><span>).<\/span><span>addHandler<\/span><span>(<\/span><span>file_handler<\/span><span>)<\/span> <\/code><\/pre>\n<div>\n<\/p><\/div>\n<\/p><\/div>\n<p>This adds to StayPresent&#8217;s existing dedicated <code>StreamHandler<\/code> rather than replacing it, so console output and your new handler both receive events unless you explicitly remove the default one.<\/p>\n<h2> <a name=\"logging-during-multibot-runs\" href=\"#logging-during-multibot-runs\"> <\/a> Logging During Multi-Bot Runs <\/h2>\n<p>When running several bots at once, log lines identify which bot they refer to using a label \u2014 normally just the filename (<code>bot[0] 'worker.py'<\/code>), or the dotted module path for <code>bot_module<\/code>-based bots (<code>bot[0] 'mypkg.bot'<\/code>). If two bots share an identical filename, StayPresent automatically switches to logging the full file path for every bot sharing that name, specifically so crash\/restart messages stay distinguishable in the logs rather than becoming ambiguous.<\/p>\n<h2> <a name=\"logging-during-shutdown\" href=\"#logging-during-shutdown\"> <\/a> Logging During Shutdown <\/h2>\n<p>On <code>SIGINT<\/code>\/<code>SIGTERM<\/code>, the shutdown sequence itself is logged \u2014 including whether a previously-installed signal handler is being chained afterward. <code>active_cron_handles()<\/code> is also checked during shutdown, and any pinger still running at that point is logged purely for visibility (it isn&#8217;t stopped or waited on, since cron pingers run on daemon threads that exit automatically with the process).<\/p>\n<h2> <a name=\"full-example\" href=\"#full-example\"> <\/a> Full Example <\/h2>\n<div>\n<pre><code><span>import<\/span> <span>logging<\/span> <span>import<\/span> <span>staypresent<\/span> <span># Turn up StayPresent's own logs for a specific debugging session <\/span><span>logging<\/span><span>.<\/span><span>getLogger<\/span><span>(<\/span><span>\"<\/span><span>staypresent<\/span><span>\"<\/span><span>).<\/span><span>setLevel<\/span><span>(<\/span><span>logging<\/span><span>.<\/span><span>DEBUG<\/span><span>)<\/span> <span># Your bot's own logger, configured completely independently <\/span><span>bot_logger<\/span> <span>=<\/span> <span>logging<\/span><span>.<\/span><span>getLogger<\/span><span>(<\/span><span>\"<\/span><span>mybot<\/span><span>\"<\/span><span>)<\/span> <span>bot_logger<\/span><span>.<\/span><span>setLevel<\/span><span>(<\/span><span>logging<\/span><span>.<\/span><span>INFO<\/span><span>)<\/span> <span>bot_logger<\/span><span>.<\/span><span>addHandler<\/span><span>(<\/span><span>logging<\/span><span>.<\/span><span>StreamHandler<\/span><span>())<\/span> <span>staypresent<\/span><span>.<\/span><span>web<\/span><span>.<\/span><span>json<\/span><span>({<\/span><span>\"<\/span><span>status<\/span><span>\"<\/span><span>:<\/span> <span>\"<\/span><span>running<\/span><span>\"<\/span><span>})<\/span> <span>staypresent<\/span><span>.<\/span><span>run<\/span><span>(<\/span><span>\"<\/span><span>bot.py<\/span><span>\"<\/span><span>)<\/span> <\/code><\/pre>\n<div>\n<\/p><\/div>\n<\/p><\/div>\n<p>Both loggers coexist cleanly \u2014 turning StayPresent&#8217;s level up or down has zero effect on <code>mybot<\/code>&#8216;s own output.<\/p>\n<h2> <a name=\"best-practices\" href=\"#best-practices\"> <\/a> Best Practices <\/h2>\n<ul>\n<li>Turn <code>\"staypresent\"<\/code> up to <code>DEBUG<\/code> temporarily when diagnosing a deployment issue (a bot that won&#8217;t stay up, a crash loop), then back down once resolved.<\/li>\n<li>Attach a <code>FileHandler<\/code> or remote-logging handler to <code>\"staypresent\"<\/code> if you want restart\/crash events specifically forwarded somewhere durable, separate from your bot&#8217;s own application logs.<\/li>\n<li>Don&#8217;t call <code>logging.basicConfig()<\/code> in your own bot script expecting it to also configure StayPresent&#8217;s output \u2014 it won&#8217;t, by design; configure <code>\"staypresent\"<\/code> directly instead.<\/li>\n<\/ul>\n<h2> <a name=\"common-mistakes\" href=\"#common-mistakes\"> <\/a> Common Mistakes <\/h2>\n<ul>\n<li> <strong>Assuming <code>logging.basicConfig()<\/code> in your own code affects StayPresent&#8217;s logs.<\/strong> It doesn&#8217;t \u2014 StayPresent never falls back to root logger configuration, since it never propagates to the root logger at all.<\/li>\n<li> <strong>Setting the level on the wrong logger.<\/strong> <code>logging.getLogger(\"staypresent\")<\/code>, not <code>logging.getLogger()<\/code> (the root logger) or your own bot&#8217;s logger name, controls StayPresent&#8217;s verbosity specifically.<\/li>\n<li> <strong>Expecting bot subprocess output to appear through the <code>\"staypresent\"<\/code> logger.<\/strong> Your bot runs as a separate subprocess with its own stdout\/stderr \u2014 <code>\"staypresent\"<\/code> logs StayPresent&#8217;s own orchestration events, not your bot&#8217;s internal application logs.<\/li>\n<\/ul>\n<h2> <a name=\"faqs\" href=\"#faqs\"> <\/a> FAQs <\/h2>\n<p><strong>Does StayPresent ever call <code>logging.basicConfig()<\/code>?<\/strong><br \/> No, never \u2014 this is a deliberate design choice specifically to avoid interfering with logging you&#8217;ve already configured elsewhere in your application.<\/p>\n<p><strong>Can I completely silence StayPresent&#8217;s logs?<\/strong><br \/> Yes \u2014 set the level above <code>CRITICAL<\/code>, or remove\/replace its handlers directly if you want full control over its output destination.<\/p>\n<p><strong>Does the logging level affect what StayPresent actually does?<\/strong><br \/> No \u2014 logging is purely observational. Crash recovery, restarts, and shutdown behavior all happen the same way regardless of what level <code>\"staypresent\"<\/code> is set to.<\/p>\n<h2> <a name=\"conclusion\" href=\"#conclusion\"> <\/a> Conclusion <\/h2>\n<p><strong>Python isolated logging<\/strong> is a small design detail that saves real debugging time \u2014 StayPresent&#8217;s dedicated <code>\"staypresent\"<\/code> logger means you can turn its verbosity up or down, attach your own handlers, and trust that none of it touches the logging you&#8217;ve already built for your bot&#8217;s own code. <\/p>\n<div>\n<pre><code>pip <span>install <\/span>staypresent[prod] <\/code><\/pre>\n<div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/div>\n<\/div>\n<\/div>\n<p>Fuente: <a href=\"https:\/\/dev.to\/codenamew\/how-staypresents-logging-works-without-breaking-yours-307b\">Art\u00edculo original<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Turn it down in a quiet production environment: logging.getLogger(&#8220;staypresent&#8221;).setLevel(logging.WARNING) This setting only affects StayPresent&#8217;s own log output \u2014 it has no effect on your bot&#8217;s separate loggers, and vice versa. Attaching Your Own Handler Since it&#8217;s a real logger object, you can attach additional handlers \u2014 to forward StayPresent&#8217;s events to a file, a monitoring [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3984,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[41],"tags":[],"class_list":["post-3985","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devto"],"jetpack_publicize_connections":[],"_links":{"self":[{"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/posts\/3985","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/comments?post=3985"}],"version-history":[{"count":0,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/posts\/3985\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/media\/3984"}],"wp:attachment":[{"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/media?parent=3985"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/categories?post=3985"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tucumandevelopers.com\/index.php\/wp-json\/wp\/v2\/tags?post=3985"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}