From 48d9a2582089b42758ff37e2917d61c9e4eb01a8 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Wed, 26 Nov 2025 14:58:17 -0600 Subject: [PATCH 1/6] Fix that 'closed'->'done' change broke this route --- app/models/user/day_timeline/column.rb | 9 +++++++++ app/views/events/day_timeline/_column.html.erb | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/models/user/day_timeline/column.rb b/app/models/user/day_timeline/column.rb index 0331a83ff..ce87873fa 100644 --- a/app/models/user/day_timeline/column.rb +++ b/app/models/user/day_timeline/column.rb @@ -17,6 +17,15 @@ class User::DayTimeline::Column safe_join(parts, " ") end + def base_title_for_route + case base_title + when "Done" + "closed" + else + base_title.downcase + end + end + def events_by_hour limited_events.group_by { it.created_at.hour } end diff --git a/app/views/events/day_timeline/_column.html.erb b/app/views/events/day_timeline/_column.html.erb index 23bf7e34e..509efd69d 100644 --- a/app/views/events/day_timeline/_column.html.erb +++ b/app/views/events/day_timeline/_column.html.erb @@ -3,7 +3,7 @@ <%= column.title %> <% if column.events_by_hour.any? %> - <%= link_to events_day_timeline_column_path(id: column.base_title.downcase, day: column.day_timeline.day.to_date), class: "events__maximize-button btn btn--circle txt-x-small borderless", data: { turbo_frame: "_top" } do %> + <%= link_to events_day_timeline_column_path(id: column.base_title_for_route, day: column.day_timeline.day.to_date), class: "events__maximize-button btn btn--circle txt-x-small borderless", data: { turbo_frame: "_top" } do %> <%= icon_tag "grid", class: "translucent" %> Expand column <% end %> From 887f100c5086d6bec4933040943ef09c0da67393 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Wed, 26 Nov 2025 21:32:38 -0500 Subject: [PATCH 2/6] Rename bin/gitleaks to gitleaks-audit to prevent script recursion if bin is in user's $PATH --- bin/{gitleaks => gitleaks-audit} | 0 config/ci.rb | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename bin/{gitleaks => gitleaks-audit} (100%) diff --git a/bin/gitleaks b/bin/gitleaks-audit similarity index 100% rename from bin/gitleaks rename to bin/gitleaks-audit diff --git a/config/ci.rb b/config/ci.rb index b7ddab694..f6cbbf953 100644 --- a/config/ci.rb +++ b/config/ci.rb @@ -8,7 +8,7 @@ CI.run do step "Security: Gem audit", "bin/bundler-audit check --update" step "Security: Importmap audit", "bin/importmap audit" step "Security: Brakeman audit", "bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error" - step "Security: Gitleaks audit", "bin/gitleaks" + step "Security: Gitleaks audit", "bin/gitleaks-audit" step "Tests: Rails: SaaS config", "bin/rails test" step "Tests: Rails: OSS config", "OSS_CONFIG=1 bin/rails test" From 0453526bf1b1d38ba232ae70085e2275ea0f3f94 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Thu, 27 Nov 2025 07:07:02 +0100 Subject: [PATCH 3/6] Prevent Fizzy menu from closing on page refreshes https://app.fizzy.do/5986089/cards/3190 --- app/views/my/_menu.html.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/my/_menu.html.erb b/app/views/my/_menu.html.erb index 2b5c1d0ea..31d3d2551 100644 --- a/app/views/my/_menu.html.erb +++ b/app/views/my/_menu.html.erb @@ -14,7 +14,8 @@ controller: "filter navigable-list nav-section-expander", dialog_target: "dialog", navigable_list_focus_on_selection_value: false, - navigable_list_actionable_items_value: true } do %> + navigable_list_actionable_items_value: true, + turbo_permanent: true } do %> <%= turbo_frame_tag "my_menu", src: my_menu_path, loading: :lazy, target: "_top" do %> <% # Passing empty block to avoid double-render %> <%= render("my/menus/jump") { } %> From 2edf79672e56fec4cf2ca32062633f6784ef00f0 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Wed, 26 Nov 2025 13:56:53 -0500 Subject: [PATCH 4/6] Improve AGENTS.md with some loki suggestions Suggested by Claude after I yelled at it when it was using string matching instead of the structured fields. --- AGENTS.md | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index e8d1f5d63..51407a6fb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -152,10 +152,40 @@ Grafana MCP tools provide access to production metrics and logs for performance - `rails_request_total:rate1m:sum_by_controller_action{app="fizzy"}` - Request rates by endpoint - `fizzy_replica_wait_seconds` - Database replica consistency wait times -### Loki Log Labels -Query: `{service_namespace="fizzy", deployment_environment_name="production", service_name="rails"}` +### Loki Log Labels and Query Patterns -Useful fields: `event_duration_ms`, `performance_time_db_ms`, `performance_time_cpu_ms`, `rails_endpoint`, `rails_controller` +**Base label selector:** +```logql +{service_namespace="fizzy", deployment_environment_name="production", service_name="rails"} +``` + +**Useful JSON fields:** `event_duration_ms`, `performance_time_db_ms`, `performance_time_cpu_ms`, `rails_endpoint`, `rails_controller`, `url_path`, `authentication_identity_id`, `http_response_status_code` + +**Query patterns:** +- Filter by fields: `{labels} | field_name = "value"` +- Multiple field filters: `{labels} | field1 = "value1" | field2 = "value2"` +- Reduce returned labels: `{labels} | filters | keep field1,field2,field3` (reduces label payload) +- Minimize log line content: `{labels} | filters | line_format "{{.field_name}}"` (replaces raw log line) +- Combine both for minimal tokens: `{labels} | filters | keep field1,field2 | line_format "{{.field1}}"` +- **Important:** Fields are pre-parsed by the OTel collector. Don't use string search (`|=`) when filtering structured fields +- **Important:** Do NOT use `| json` - it will cause JSONParserErr since fields are already parsed as labels + +**Token management (CRITICAL):** +- Always probe with `limit: 3` first to check response size before running larger queries +- Aggregations return time series (many data points), not single values - can explode token usage +- NEVER use `sum by (field)` - returns a time series per unique value, easily exceeds token limits +- For breakdowns by field: fetch raw logs with `| keep field | line_format "{{.field}}"` and count client-side + +**Aggregations for statistics (use instead of fetching raw logs):** +- `mcp__grafana__query_loki_logs` returns limited results (default 10, max ~100) and large responses get truncated; use aggregations for statistics on large datasets +- Count: `sum(count_over_time({labels} | filters [12h]))` +- Percentiles: `quantile_over_time(0.95, {labels} | filters | unwrap field_name | __error__="" [12h]) by ()` +- Average: `avg_over_time({labels} | filters | unwrap field_name | __error__="" [12h]) by ()` +- Min/Max: `min_over_time(...)` / `max_over_time(...)` +- The `| unwrap field_name | __error__=""` pattern extracts numeric values from pre-parsed labels +- Use `by ()` or wrap in `sum()` to avoid cardinality limits + +**Documentation:** For advanced LogQL syntax (aggregations, pattern matching, etc.), consult https://grafana.com/docs/loki/latest/query/ ### Instrumentation Yabeda-based metrics exported at `:9394/metrics`. Config in `config/initializers/yabeda.rb`. From 5e971f41af3b145900663e20c1b57dd93e21ee83 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Wed, 26 Nov 2025 16:03:02 -0600 Subject: [PATCH 5/6] Set entropy to 1 year so cards don't close before they can play --- app/models/account/seeder.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/account/seeder.rb b/app/models/account/seeder.rb index f7f7cf60b..9858cff6b 100644 --- a/app/models/account/seeder.rb +++ b/app/models/account/seeder.rb @@ -25,6 +25,7 @@ class Account::Seeder # Playground Board # --------------- playground = account.boards.create! name: "Playground", creator: creator, all_access: true + playground.update! auto_postpone_period: 365.days # Cards playground.cards.create! creator: creator, title: "Finally, watch this Fizzy orientation video", status: "published", description: <<~HTML From 29e62ac90ca7e9c049e57b1aaa1aabf88f99f3bb Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Wed, 26 Nov 2025 15:38:26 -0600 Subject: [PATCH 6/6] Fix that board button was leaking to the right of columns See: https://app.fizzy.do/5986089/cards/3148 --- app/assets/stylesheets/header.css | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/stylesheets/header.css b/app/assets/stylesheets/header.css index 59d94a0f3..21553e358 100644 --- a/app/assets/stylesheets/header.css +++ b/app/assets/stylesheets/header.css @@ -42,7 +42,6 @@ font-size: var(--text-x-small); gap: var(--header-gap); inline-size: var(--header-actions-width); - min-inline-size: fit-content; } .header__actions--start {