|
| 1 | +import { HeadingWithAnchor } from '@/components/heading-with-anchor'; |
| 2 | +import { CodeBlock } from '@/components/code-block'; |
| 3 | +import { Callout } from '@/components/ui/callout'; |
| 4 | +import { EditPageLink } from '@/components/edit-page-link'; |
| 5 | + |
| 6 | +export default function LoggingDocsPage() { |
| 7 | + return ( |
| 8 | + <div className="space-y-6"> |
| 9 | + <HeadingWithAnchor id="logging-to-stdout" level={1}> |
| 10 | + Logging to STDOUT (12‑Factor) |
| 11 | + </HeadingWithAnchor> |
| 12 | + <p className="text-lg text-neutral-600 dark:text-neutral-400"> |
| 13 | + LogStruct embraces{' '} |
| 14 | + <a |
| 15 | + className="underline" |
| 16 | + href="https://12factor.net/logs" |
| 17 | + target="_blank" |
| 18 | + rel="noreferrer" |
| 19 | + > |
| 20 | + The Twelve‑Factor App |
| 21 | + </a>{' '} |
| 22 | + approach to logs: write events as unbuffered lines to{' '} |
| 23 | + <code>STDOUT</code> and let the environment aggregate, ship, and store |
| 24 | + them. This section explains how Rails logs by default, how LogStruct |
| 25 | + integrates, and what to configure for a predictable developer |
| 26 | + experience. |
| 27 | + </p> |
| 28 | + |
| 29 | + <HeadingWithAnchor id="rails-defaults" level={2}> |
| 30 | + Rails Defaults vs. LogStruct |
| 31 | + </HeadingWithAnchor> |
| 32 | + <ul className="list-disc list-inside space-y-2 text-neutral-600 dark:text-neutral-400"> |
| 33 | + <li> |
| 34 | + <b>Rails (development):</b> writes to <code>log/development.log</code>{' '} |
| 35 | + by default; the server console shows Puma boot lines, not application |
| 36 | + logs. |
| 37 | + </li> |
| 38 | + <li> |
| 39 | + <b>Rails (test):</b> most test runners capture logs; default logger |
| 40 | + often writes to a file. |
| 41 | + </li> |
| 42 | + <li> |
| 43 | + <b>Rails (production):</b> many deploy targets set{' '} |
| 44 | + <code>RAILS_LOG_TO_STDOUT=1</code>, so logs go to STDOUT. |
| 45 | + </li> |
| 46 | + <li> |
| 47 | + <b>LogStruct:</b> when enabled, replaces the logger with |
| 48 | + SemanticLogger and emits JSON to STDOUT in test/production by default. |
| 49 | + In development, you can opt‑in to the same JSON to avoid surprises. |
| 50 | + </li> |
| 51 | + </ul> |
| 52 | + |
| 53 | + <HeadingWithAnchor id="dev-parity" level={2}> |
| 54 | + Make Development Match Test/Production |
| 55 | + </HeadingWithAnchor> |
| 56 | + <p className="text-neutral-600 dark:text-neutral-400"> |
| 57 | + Opt‑in locally so development behaves like test/production: |
| 58 | + </p> |
| 59 | + <CodeBlock language="bash"> |
| 60 | + {`# One-off |
| 61 | +LOGSTRUCT_ENABLED=true RAILS_LOG_TO_STDOUT=1 rails s |
| 62 | +
|
| 63 | +# Or set in your shell env for the session |
| 64 | +export LOGSTRUCT_ENABLED=true |
| 65 | +export RAILS_LOG_TO_STDOUT=1 |
| 66 | +rails s`} |
| 67 | + </CodeBlock> |
| 68 | + <Callout className="mt-4"> |
| 69 | + You can also force STDOUT + debug in development via code (useful for |
| 70 | + teams): |
| 71 | + </Callout> |
| 72 | + <CodeBlock language="ruby"> |
| 73 | + {`# config/environments/development.rb (or in your application template) |
| 74 | +config.log_level = :debug |
| 75 | +logger = ActiveSupport::Logger.new($stdout) |
| 76 | +logger.formatter = config.log_formatter |
| 77 | +config.logger = ActiveSupport::TaggedLogging.new(logger)`} |
| 78 | + </CodeBlock> |
| 79 | + |
| 80 | + <HeadingWithAnchor id="dotenv-rails" level={2}> |
| 81 | + Dotenv‑Rails and Early Boot Logs |
| 82 | + </HeadingWithAnchor> |
| 83 | + <p className="text-neutral-600 dark:text-neutral-400"> |
| 84 | + Some libraries (e.g., <code>dotenv-rails</code>) log very early during |
| 85 | + boot. LogStruct subscribes to those notifications immediately and |
| 86 | + buffers structured logs. After your initializers run, LogStruct decides |
| 87 | + which set to emit: |
| 88 | + </p> |
| 89 | + <ul className="list-disc list-inside space-y-2 text-neutral-600 dark:text-neutral-400"> |
| 90 | + <li> |
| 91 | + <b>Enabled:</b> Emit structured JSON logs (for example, a dotenv{' '} |
| 92 | + <em>update</em> event) and suppress original replay. |
| 93 | + </li> |
| 94 | + <li> |
| 95 | + <b>Disabled:</b> Emit original <code>[dotenv]</code> lines and discard |
| 96 | + the structured buffer. |
| 97 | + </li> |
| 98 | + </ul> |
| 99 | + <Callout type="warning" className="mt-2"> |
| 100 | + When you run a <code>rails runner</code> inside your test suite, it |
| 101 | + inherits <code>RAILS_ENV=test</code>. Dotenv may have already loaded{' '} |
| 102 | + <code>.env.test</code>, so nested runs might only show a single “Loaded |
| 103 | + …” line (no “Set …” update). |
| 104 | + </Callout> |
| 105 | + |
| 106 | + <HeadingWithAnchor id="production-recommendations" level={2}> |
| 107 | + Production Recommendations |
| 108 | + </HeadingWithAnchor> |
| 109 | + <ul className="list-disc list-inside space-y-2 text-neutral-600 dark:text-neutral-400"> |
| 110 | + <li> |
| 111 | + Ensure <code>RAILS_LOG_TO_STDOUT=1</code> (many platforms set this by |
| 112 | + default). |
| 113 | + </li> |
| 114 | + <li> |
| 115 | + Keep LogStruct enabled in production (default) to emit structured JSON |
| 116 | + for all integrations. |
| 117 | + </li> |
| 118 | + <li> |
| 119 | + Ship logs to your log aggregation system (e.g., CloudWatch, ELK, |
| 120 | + Datadog) as line‑delimited JSON. |
| 121 | + </li> |
| 122 | + </ul> |
| 123 | + |
| 124 | + <HeadingWithAnchor id="quick-diagnostics" level={2}> |
| 125 | + Quick Diagnostics |
| 126 | + </HeadingWithAnchor> |
| 127 | + <CodeBlock language="bash"> |
| 128 | + {`# Verify structured boot logs (dotenv) in test env |
| 129 | +LOGSTRUCT_ENABLED=true RAILS_LOG_TO_STDOUT=1 DISABLE_SPRING=1 RAILS_ENV=test \ |
| 130 | + rails runner 'puts LogStruct.enabled?' |
| 131 | +
|
| 132 | +# Verify original dotenv lines when disabled |
| 133 | +LOGSTRUCT_ENABLED=false RAILS_LOG_TO_STDOUT=1 DISABLE_SPRING=1 RAILS_ENV=development \ |
| 134 | + rails runner 'puts LogStruct.enabled?'`} |
| 135 | + </CodeBlock> |
| 136 | + |
| 137 | + <EditPageLink /> |
| 138 | + </div> |
| 139 | + ); |
| 140 | +} |
0 commit comments