Skip to content

Commit 493aa0c

Browse files
committed
Updated default behavior for when JSON logging is enabled - humans get readable logs, machines get JSON (including test suites on CI to catch bugs early)
1 parent 0326656 commit 493aa0c

File tree

18 files changed

+422
-169
lines changed

18 files changed

+422
-169
lines changed

.cspell/project-words.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ gettime
2121
goodjob
2222
Healthcheck
2323
Honeybadger
24+
regen
2425
hotwire
2526
hrefs
2627
instrumenter

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.1.2] - 2025-10-03
9+
10+
Better default policy for when JSON logs are enabled: machines get JSON, humans get readable logs.
11+
Enable LogStruct for production servers or when running tests on CI.
12+
Keep dev-friendly logging on local machines or when running interactive commands on production servers.
13+
814
## [0.1.1] - 2025-09-29
915

1016
Added dotenv-rails integration. Many other fixes and improvements.

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
logstruct (0.1.1)
4+
logstruct (0.1.2)
55
lograge (>= 0.11)
66
rails (>= 7.0)
77
semantic_logger (~> 4.15)

README.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ We support all your other favorite gems too, like Sidekiq, Sentry, and Shrine. (
66

77
## Features
88

9-
- JSON logging enabled by default in production and test environments
9+
- JSON logging enabled by default for server processes in production and test environments, and for CI test runs (automatically disabled for console, local tests, and other Rake tasks)
1010
- ActionMailer integration for email delivery logging
1111
- ActiveJob integration for job execution logging
1212
- Sidekiq integration for background job logging
@@ -58,11 +58,16 @@ Once initialized (and enabled), the gem automatically includes its modules into
5858
- Rails `config.filter_parameters` are merged into LogStruct's filters and then cleared (to avoid double filtering). Configure sensitive keys via `LogStruct.config.filters`.
5959
- When `RAILS_LOG_TO_STDOUT` is set, we log to STDOUT only. Otherwise, we log to STDOUT by default without adding a file appender to avoid duplicate logs.
6060

61-
### Development behavior
61+
### Default behavior by process type
6262

63-
- Disabled by default in development. Enable explicitly via `LOGSTRUCT_ENABLED=true` or `LogStruct.configure { |c| c.enabled = true }`.
64-
- When enabled in development, LogStruct now defaults to production‑style JSON output so you can preview exactly what will be shipped in prod.
65-
- You can opt back into the colorful human formatter with:
63+
- **Server processes** (`rails server`): JSON logging is enabled by default in production and test environments
64+
- **CI test runs** (`rails test` when `CI=true`): JSON logging is enabled by default to catch production bugs in your automated tests
65+
- **Local test runs** (`rails test` locally): JSON logging is disabled by default, providing human-readable logs for debugging
66+
- **Console** (`rails console`): JSON logging is disabled by default in all environments, providing human-readable logs instead
67+
- **Other Rake tasks** (`rake db:migrate`, etc.): JSON logging is disabled by default in production, providing human-readable logs instead
68+
- **Development environment**: Disabled by default for all process types. Enable explicitly via `LOGSTRUCT_ENABLED=true` or `LogStruct.configure { |c| c.enabled = true }`.
69+
70+
When enabled in development, LogStruct defaults to production‑style JSON output so you can preview exactly what will be shipped in prod. You can opt back into the colorful human formatter with:
6671

6772
```ruby
6873
LogStruct.configure do |c|
@@ -71,6 +76,8 @@ LogStruct.configure do |c|
7176
end
7277
```
7378

79+
To force JSON logs in console, local test runs, or other Rake tasks (e.g., for debugging), set `LOGSTRUCT_ENABLED=true` in your environment.
80+
7481
## Documentation
7582

7683
Please see the [documentation](https://logstruct.com/docs) for more details. (All code examples are type-checked and tested, and it's harder to keep a README up to date.)

docs/app/docs/configuration/page.tsx

Lines changed: 74 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,48 +31,84 @@ export default function ConfigurationPage() {
3131
<HeadingWithAnchor id="enabling-logstruct">
3232
Enabling LogStruct
3333
</HeadingWithAnchor>
34-
<p className="text-neutral-600 dark:text-neutral-400 mb-4">
35-
LogStruct can be enabled or disabled in the following ways:
34+
35+
<p className="text-neutral-600 dark:text-neutral-300 mb-4">
36+
LogStruct follows a simple philosophy:{' '}
37+
<strong>machines get JSON, humans get readable logs</strong>. By
38+
default:
3639
</p>
3740

38-
<ul className="list-disc list-inside space-y-2 text-neutral-600 dark:text-neutral-400">
41+
<ul className="list-disc list-outside ml-6 space-y-2 text-neutral-600 dark:text-neutral-300 mb-6">
42+
<li>
43+
<strong>Production servers</strong> → JSON logs (for parsing and
44+
analysis)
45+
</li>
46+
<li>
47+
<strong>CI test runs</strong> → JSON logs (to catch production bugs)
48+
</li>
3949
<li>
40-
LogStruct will be <strong>enabled</strong> if the{' '}
41-
<strong>
42-
<code>LOGSTRUCT_ENABLED</code>
43-
</strong>{' '}
44-
environment variable is set to <code>&quot;true&quot;</code>,
45-
<code>&quot;yes&quot;</code>, <code>&quot;1&quot;</code>, etc.
50+
<strong>Local development</strong> → Human-readable logs (disabled by
51+
default)
4652
</li>
4753
<li>
48-
LogStruct will be <strong>disabled</strong> if{' '}
49-
<strong>
50-
<code>LOGSTRUCT_ENABLED</code>
51-
</strong>{' '}
52-
is set to any other value.
54+
<strong>Rails console</strong> → Human-readable logs (always)
5355
</li>
5456
<li>
55-
If{' '}
56-
<strong>
57-
<code>LOGSTRUCT_ENABLED</code>
58-
</strong>{' '}
59-
is undefined, LogStruct will be <strong>enabled</strong> if the
60-
current Rails environment is listed in{' '}
61-
<code>config.enabled_environments</code>.
57+
<strong>Rake tasks</strong> → Human-readable logs
6258
</li>
6359
<li>
64-
Finally, you can manually set <code>config.enabled</code> in an
65-
initializer. This will override all other configuration methods.
60+
<strong>Local test runs</strong> → Human-readable logs (for debugging)
6661
</li>
6762
</ul>
6863

69-
<p>
70-
First, we check if <code>config.enabled_environments</code> includes the
71-
current Rails environment. If it does, we use that value. Otherwise, we
72-
check the <code>LOGSTRUCT_ENABLED</code> environment variable. If that
73-
is not set, we fall back to <code>config.enabled</code>.
64+
<HeadingWithAnchor id="overriding-defaults" level={3}>
65+
Overriding the Defaults
66+
</HeadingWithAnchor>
67+
68+
<p className="text-neutral-600 dark:text-neutral-300 mb-4">
69+
You can override this behavior in several ways, with the following
70+
precedence (highest to lowest):
7471
</p>
7572

73+
<ol className="list-decimal list-outside ml-6 space-y-3 text-neutral-600 dark:text-neutral-300 mb-6">
74+
<li>
75+
<strong>Environment variable override</strong>
76+
<br />
77+
Set <code>LOGSTRUCT_ENABLED=true</code> to force JSON logs, or{' '}
78+
<code>LOGSTRUCT_ENABLED=false</code> to disable completely.
79+
<div className="mt-2">
80+
<CodeBlock language="bash">
81+
{`# Force JSON logs in console for debugging\nLOGSTRUCT_ENABLED=true rails console\n\n# Force JSON logs in local tests\nLOGSTRUCT_ENABLED=true rails test`}
82+
</CodeBlock>
83+
</div>
84+
</li>
85+
<li>
86+
<strong>Initializer configuration</strong>
87+
<br />
88+
Manually set <code>config.enabled = true</code> in your initializer to
89+
enable in all development processes.
90+
<div className="mt-2">
91+
<CodeBlock language="ruby">
92+
{`LogStruct.configure do |c|\n c.enabled = true\nend`}
93+
</CodeBlock>
94+
</div>
95+
</li>
96+
<li>
97+
<strong>Environment list</strong>
98+
<br />
99+
Modify <code>config.enabled_environments</code> to change which
100+
environments have JSON logs by default (currently{' '}
101+
<code>[:test, :production]</code>).
102+
</li>
103+
</ol>
104+
105+
<Callout type="info">
106+
The <code>CI</code> environment variable is automatically detected by
107+
most CI systems (GitHub Actions, GitLab CI, CircleCI, Travis, etc.). If
108+
your CI doesn&apos;t set it, add <code>CI=true</code> to your CI
109+
configuration.
110+
</Callout>
111+
76112
<HeadingWithAnchor id="environment-configuration">
77113
Environment Configuration
78114
</HeadingWithAnchor>
@@ -118,6 +154,16 @@ end`}
118154
<code>config.enabled_environments</code>.
119155
</Callout>
120156

157+
<Callout type="info">
158+
To force JSON logs in console, local test runs, or other Rake tasks
159+
(e.g., for debugging or inspecting the exact JSON output), set{' '}
160+
<code>LOGSTRUCT_ENABLED=true</code> when running the command:
161+
<br />
162+
<code>LOGSTRUCT_ENABLED=true rails console</code>
163+
<br />
164+
<code>LOGSTRUCT_ENABLED=true rails test</code>
165+
</Callout>
166+
121167
<HeadingWithAnchor id="integration-configuration">
122168
Integration Configuration
123169
</HeadingWithAnchor>

docs/app/docs/getting-started/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ export default function GettingStartedPage() {
2828
</p>
2929
<CodeBlock language="bash">bundle install</CodeBlock>
3030

31-
<p className="text-neutral-600 dark:text-neutral-400 mt-6">
32-
{`LogStruct is now installed and will automatically enable JSON structured logging in the test and production environments.`}
31+
<p className="text-neutral-600 dark:text-neutral-300 mt-6">
32+
{`LogStruct is now installed and will automatically enable JSON structured logging for server processes in the test and production environments, and for CI test runs. Console, local tests, and other Rake tasks will use human-readable logs by default.`}
3333
</p>
3434

3535
<HeadingWithAnchor id="basic-configuration" level={2}>

docs/app/docs/page.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ export default function DocsPage() {
2222
</HeadingWithAnchor>
2323
<ul className="list-disc list-inside space-y-2 text-neutral-600 dark:text-neutral-300">
2424
<li>
25-
JSON logging enabled by default in production and test environments.
25+
JSON logging enabled by default for server processes in production and
26+
test environments, and for CI test runs (automatically disabled for
27+
console, local tests, and other Rake tasks).
2628
</li>
2729
<li>
2830
Sets up <a href="https://github.com/roidrage/lograge">Lograge</a> for

lefthook.yml

Lines changed: 75 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -3,84 +3,89 @@ colors: true
33
pre-commit:
44
parallel: true
55

6-
jobs:
7-
# Checks group - runs in parallel
8-
- group:
9-
parallel: true
10-
jobs:
11-
- name: sorbet
12-
glob: '*.{rb,rbi}'
13-
run: scripts/typecheck.sh
6+
commands:
7+
sorbet:
8+
glob: '*.{rb,rbi}'
9+
run: scripts/typecheck.sh
10+
11+
typescript:
12+
glob: 'docs/**/*.{ts,tsx,js,jsx}'
13+
run: cd docs && pnpm exec tsc --noEmit
1414

15-
- name: typescript
16-
glob: 'docs/**/*.{ts,tsx,js,jsx}'
17-
run: cd docs && pnpm exec tsc --noEmit
15+
typescript-export:
16+
glob: '{schemas/log_sources/**/*,lib/log_struct/enums.rb,lib/log_struct/enums/*.rb,tools/codegen/**/*.rb,scripts/generate_structs.rb}'
17+
run: scripts/generate_structs.rb
1818

19-
- name: typescript-export
20-
glob: '{schemas/log_sources/**/*,lib/log_struct/enums.rb,lib/log_struct/enums/*.rb,tools/codegen/**/*.rb,scripts/generate_structs.rb}'
21-
run: scripts/generate_structs.rb
19+
codegen-sync:
20+
glob: '{schemas/log_sources/**/*,tools/codegen/templates/**/*,tools/codegen/**/*.rb,scripts/generate_structs.rb}'
21+
run: scripts/check_generated.sh
2222

23-
- name: codegen-sync
24-
glob: '{schemas/log_sources/**/*,tools/codegen/templates/**/*,tools/codegen/**/*.rb,scripts/generate_structs.rb}'
25-
run: scripts/check_generated.sh
23+
cspell:
24+
glob: '*.{rb,md,yml,yaml,txt,ts,tsx,js,jsx}'
25+
run: scripts/spellcheck.sh
2626

27-
- name: cspell
28-
glob: '*.{rb,md,yml,yaml,txt,ts,tsx,js,jsx}'
29-
run: scripts/spellcheck.sh
27+
changelog:
28+
glob: 'lib/log_struct/version.rb'
29+
run: ruby scripts/check_changelog_version.rb
3030

31-
- name: eslint
32-
glob: 'docs/**/*.{ts,tsx,js,jsx}'
33-
run: cd docs && pnpm run lint
31+
eslint:
32+
glob: 'docs/**/*.{ts,tsx,js,jsx}'
33+
run: cd docs && pnpm run lint
3434

35-
- name: typescript-tests
36-
glob: 'docs/**/*.{ts,tsx}'
37-
run: cd docs && pnpm test
35+
typescript-tests:
36+
glob: 'docs/**/*.{ts,tsx}'
37+
run: cd docs && pnpm test
3838

39-
- name: ruby-tests
40-
glob: '{lib,test}/**/*.rb'
41-
run: scripts/test.rb
39+
ruby-tests:
40+
glob: '{lib,test}/**/*.rb'
41+
run: scripts/test.rb
4242

43-
# Fixes group - runs sequentially to avoid git conflicts
44-
- group:
45-
parallel: false
46-
jobs:
47-
- name: bundle-install
48-
glob: '{Gemfile,Gemfile.lock,lib/log_struct/version.rb}'
49-
run: |
50-
echo "Detected Gemfile/version change; running bundle install..."
51-
bundle install
52-
if [[ -f Gemfile.lock ]]; then
53-
git add Gemfile.lock
54-
fi
55-
stage_fixed: true
43+
bundle-install:
44+
glob: '{Gemfile,Gemfile.lock,lib/log_struct/version.rb}'
45+
run: |
46+
echo "Detected Gemfile/version change; running bundle install..."
47+
bundle install
48+
if [[ -f Gemfile.lock ]]; then
49+
git add Gemfile.lock
50+
fi
51+
stage_fixed: true
5652

57-
- name: fix-whitespace
58-
run: |
59-
for file in {staged_files}; do
60-
if [[ -f "$file" ]]; then
61-
# Remove trailing whitespace (portable sed usage)
62-
if [[ "$OSTYPE" == "darwin"* ]]; then
63-
sed -i '' 's/[[:space:]]*$//' "$file"
64-
else
65-
sed -i 's/[[:space:]]*$//' "$file"
66-
fi
67-
# Ensure file ends with newline
68-
if [[ -s "$file" ]] && [[ $(tail -c1 "$file" | wc -l) -eq 0 ]]; then
69-
echo >> "$file"
70-
fi
71-
fi
72-
done
73-
file_types:
74-
- text
75-
exclude: '**/.*'
76-
stage_fixed: true
53+
fix-whitespace:
54+
run: |
55+
for file in {staged_files}; do
56+
if [[ -f "$file" ]]; then
57+
# Remove trailing whitespace (portable sed usage)
58+
if [[ "$OSTYPE" == "darwin"* ]]; then
59+
sed -i '' 's/[[:space:]]*$//' "$file"
60+
else
61+
sed -i 's/[[:space:]]*$//' "$file"
62+
fi
63+
# Ensure file ends with newline
64+
if [[ -s "$file" ]] && [[ $(tail -c1 "$file" | wc -l) -eq 0 ]]; then
65+
echo >> "$file"
66+
fi
67+
fi
68+
done
69+
file_types:
70+
- text
71+
exclude: '**/.*'
72+
stage_fixed: true
7773

78-
- name: prettier
79-
glob: '*.{js,jsx,ts,tsx,json,yml,yaml,md}'
80-
run: scripts/prettier.sh --write {staged_files}
81-
stage_fixed: true
74+
prettier:
75+
glob: '*.{js,jsx,ts,tsx,json,yml,yaml,md}'
76+
run: scripts/prettier.sh --write {staged_files}
77+
stage_fixed: true
8278

83-
- name: rubocop
84-
glob: '*.rb'
85-
run: bin/rubocop -A {staged_files}
86-
stage_fixed: true
79+
rubocop:
80+
glob: '*.rb'
81+
run: bin/rubocop -A {staged_files}
82+
stage_fixed: true
83+
84+
post-commit:
85+
parallel: false
86+
jobs:
87+
- name: create-release-tag
88+
run: |
89+
if git show --pretty='' --name-only HEAD -- lib/log_struct/version.rb | grep -q 'lib/log_struct/version.rb'; then
90+
./scripts/create_release_tag.sh
91+
fi

0 commit comments

Comments
 (0)