diff --git a/app/assets/stylesheets/application.tailwind.css b/app/assets/stylesheets/application.tailwind.css index 619be96a..05fb6bae 100644 --- a/app/assets/stylesheets/application.tailwind.css +++ b/app/assets/stylesheets/application.tailwind.css @@ -43,3 +43,11 @@ 100% 10px; background-attachment: local, local, scroll, scroll; } + +.log-entry-table-header-cell { + @apply border-b border-slate-200 bg-slate-50 px-2 py-1 text-xs font-medium uppercase tracking-wider text-slate-500; +} + +.log-entry-table-row-cell { + @apply flex items-center border-b border-slate-200 px-2 py-1 text-sm group-hover:bg-slate-50; +} diff --git a/app/controllers/log_entries_controller.rb b/app/controllers/log_entries_controller.rb index c5dbf12c..2b0e1cbb 100644 --- a/app/controllers/log_entries_controller.rb +++ b/app/controllers/log_entries_controller.rb @@ -76,7 +76,7 @@ class LogEntriesController < ApplicationController HttpLogEntry.includes( :caused_by_entry, :triggered_entries, - response: :base, + :response, ).find(params[:id]) end end diff --git a/app/views/log_entries/index.html.erb b/app/views/log_entries/index.html.erb index a40c6179..4001c996 100644 --- a/app/views/log_entries/index.html.erb +++ b/app/views/log_entries/index.html.erb @@ -36,67 +36,68 @@ <% end %> <%= render partial: "shared/pagination_controls", locals: { collection: @log_entries } %> -
-
-
ID
-
Size
-
Time
-
Status
-
URI
-
-
Type
-
Response
+
+
+
ID
+
Size
+
Time
+
Status
+
URI
+
+
Type
+
Resp
-
<% @log_entries.each do |hle| %> -
-
- <%= link_to hle.id, log_entry_path(hle.id), class: "text-blue-600 hover:text-blue-800" %> +
+
+ <%= link_to hle.id, log_entry_path(hle.id), class: "text-blue-600 hover:text-blue-800 font-medium" %>
-
- <%= HexUtil.humansize(hle.response.size) %> +
+ <%= HexUtil.humansize(hle.response_size) %>
-
+
<%= time_ago_in_words(hle.created_at, include_seconds: true) %> ago
-
- +
+ <%= hle.status_code %>
-
+
<% iterative_parts = path_iterative_parts(hle.uri_path) %> -
- - <%= hle.uri_scheme %>://<%= hle.uri_host %> +
+ + <%= hle.uri_scheme %>://<%= hle.uri_host %> <%- iterative_parts.each_with_index do |(part, up_to), index| -%> <% uri_and_up_to = hle.uri_host + up_to %> " - >/<%= part %> + >/<%= part %> <%- end -%> <%- if hle.uri_query -%> <% query_parsed = URI.decode_www_form(hle.uri_query).to_h %> - - <%= "?#{hle.uri_query}" %> - <%- end -%> + + ?<%= hle.uri_query %> + + <%- end -%>
-
- <%= link_to hle.uri.to_s, class: "text-blue-600 hover:text-blue-800", target: "_blank", rel: "noreferrer" do %> - <%= render partial: "shared/icons/external_link", locals: { class_name: "w-4 h-4 inline" } %> +
+ <%= link_to hle.uri.to_s, class: "text-blue-600 hover:text-blue-800 transition-colors", target: "_blank", rel: "noreferrer" do %> + <%= render partial: "shared/icons/external_link", locals: { class_name: "w-4 h-4" } %> <% end %>
-
- <%= hle.content_type %> +
+ + <%= hle.content_type %> +
-
+
<%= hle.response_time_ms %>ms
-
<% end %>
diff --git a/app/views/log_entries/show.html.erb b/app/views/log_entries/show.html.erb index 13d22e38..51c2aa17 100644 --- a/app/views/log_entries/show.html.erb +++ b/app/views/log_entries/show.html.erb @@ -17,16 +17,43 @@ <% end %>
-
-
+
+
<%= link_to log_entries_path, class: "px-4 py-2 text-sm font-medium text-slate-700 bg-white border border-slate-300 rounded-md hover:bg-slate-50" do %> Log Entries <% end %> + +
-
+
URL
@@ -61,11 +88,7 @@ ><%= rtms == -1 ? "Response time not recorded" : "#{rtms}ms" %> - <%= HexUtil.humansize(@log_entry.response.size) %> - (<%= HexUtil.humansize(@log_entry.response.bytes_stored) %> - stored) + <%= HexUtil.humansize(@log_entry.response.size_bytes) %> Performed by <%= @log_entry.performed_by %> @@ -88,17 +111,6 @@
<% end %>
- <% if @log_entry.response.base %> -
Base Entry
-
- <% base_hle = HttpLogEntry.find_by(response: @log_entry.response.base) %> - <% if base_hle %> - <%= render partial: "log_entry_table_row_mini", locals: { entry: base_hle } %> - <% else %> - HLE not found... - <% end %> -
- <% end %> <% if @log_entry.caused_by_entry %>
Caused By
diff --git a/app/views/log_entries/stats.html.erb b/app/views/log_entries/stats.html.erb index 57c93fd2..abb3cf45 100644 --- a/app/views/log_entries/stats.html.erb +++ b/app/views/log_entries/stats.html.erb @@ -1,121 +1,216 @@ <% content_for :head do %> <% end %> - -
-

Http Request Log Stats

-
+
+

HTTP Request Log Stats

+
<%= link_to "Back to Index", log_entries_path, - class: "text-blue-600 hover:text-blue-800" %> + class: "text-blue-600 hover:text-blue-800 transition-colors" %>
-
- -
-
- <% [10.seconds, 30.seconds, 1.minute, 5.minutes, 30.minutes].each do |time_window| %> - <% if @time_window == time_window %> - - <%= if time_window < 1.minute - pluralize(time_window.seconds, "second") - else - time_ago_in_words(time_window.ago) - end %> - - <% else %> - <%= link_to( - ( - if time_window < 1.minute +
+
+ <% [10.seconds, 30.seconds, 1.minute, 5.minutes, 30.minutes].each do |time_window| %> + <% if @time_window == time_window %> + + <%= if time_window < 1.minute pluralize(time_window.seconds, "second") else time_ago_in_words(time_window.ago) - end - ), - stats_log_entries_path(seconds: time_window.in_seconds), - class: "text-blue-600 hover:text-blue-800 hover:bg-blue-50 px-2 py-1 rounded", - ) %> + end %> + + <% else %> + <%= link_to( + ( + if time_window < 1.minute + pluralize(time_window.seconds, "second") + else + time_ago_in_words(time_window.ago) + end + ), + stats_log_entries_path(seconds: time_window.in_seconds), + class: "rounded-full px-3 py-1 text-sm text-blue-600 hover:text-blue-800 hover:bg-blue-50 transition-colors", + ) %> + <% end %> <% end %> - <% end %> -
- -
- <%= @last_window_count %> requests in last - <%= if @time_window < 1.minute - pluralize(@time_window.seconds, "second") - else - time_ago_in_words(@time_window.ago) - end %> - - (<%= (@last_window_count.to_f / @time_window.in_seconds).round(1) %>/sec) - -
- -
- <%= HexUtil.humansize(@last_window_bytes) %> bytes transferred • - <%= HexUtil.humansize(@last_window_bytes / @time_window.in_seconds) %>/sec -
-
- -
-

By content type

-
-
-
Content Type
-
Requests
-
Transferred
-
- <% @content_type_counts - .sort_by { |_ignore, stats| -stats[:count] } - .each do |content_type, stats| %> -
-
<%= content_type %>
-
<%= stats[:count] %>
-
- <%= HexUtil.humansize(stats[:bytes]) %> -
+
+
+ <%= @last_window_count %> requests + + in last + <%= if @time_window < 1.minute + pluralize(@time_window.seconds, "second") + else + time_ago_in_words(@time_window.ago) + end %> + +
+
+ <%= (@last_window_count.to_f / @time_window.in_seconds).round(1) %> requests/sec +
+
+ <%= HexUtil.humansize(@last_window_bytes) %> transferred • + <%= HexUtil.humansize(@last_window_bytes / @time_window.in_seconds) %>/sec
-
- <% end %> -
-
- -
-

By domain

-
-
-
Domain
-
Requests
-
Transferred
-
- <% @by_domain_counts - .sort_by { |_ignore, stats| -stats[:bytes] } - .each do |domain, stats| %> -
-
<%= domain %>
-
<%= stats[:count] %>
-
- <%= HexUtil.humansize(stats[:bytes]) %> +
+
+

By Content Type

+
+
+
+
Content Type
+
Requests
+
Transferred
+ <% @content_type_counts + .sort_by { |_ignore, stats| -stats[:count] } + .each do |content_type, stats| %> +
+
<%= content_type %>
+
<%= stats[:count] %>
+
+ <%= HexUtil.humansize(stats[:bytes]) %> +
+
+ <% end %>
-
- <% end %> +
+
+
+

By Domain

+
+
+
+
Domain
+
Requests
+
Transferred
+
+ <% @by_domain_counts + .sort_by { |_ignore, stats| -stats[:bytes] } + .each do |domain, stats| %> +
+
<%= domain %>
+
<%= stats[:count] %>
+
+ <%= HexUtil.humansize(stats[:bytes]) %> +
+
+ <% end %> +
+
+ diff --git a/config/initializers/prometheus_exporter.rb b/config/initializers/prometheus_exporter.rb index 468eba7e..4c54a357 100644 --- a/config/initializers/prometheus_exporter.rb +++ b/config/initializers/prometheus_exporter.rb @@ -10,7 +10,9 @@ START_PROMETHEUS_EXPORTER = # always start in sever mode Rails.const_defined?("Server") || # always start in worker mode - (Rails.env == "worker"), + (Rails.env == "worker") || + # ran with args when in server mode, but no top level task + (ARGV.any? && Rake.application.top_level_tasks.empty?), T::Boolean, ) diff --git a/spec/controllers/log_entries_controller_spec.rb b/spec/controllers/log_entries_controller_spec.rb index 5a588af3..b9a74050 100644 --- a/spec/controllers/log_entries_controller_spec.rb +++ b/spec/controllers/log_entries_controller_spec.rb @@ -2,6 +2,7 @@ require "rails_helper" RSpec.describe LogEntriesController, type: :controller do + render_views let(:user) { create(:user, :admin) } context "when user is not signed in" do @@ -18,24 +19,59 @@ RSpec.describe LogEntriesController, type: :controller do expect(response).to redirect_to(new_user_session_path) end end + + describe "GET #show" do + it "redirects to sign in" do + get :show, params: { id: 1 } + expect(response).to redirect_to(new_user_session_path) + end + end end context "when user is signed in" do before { sign_in user } describe "GET #index" do - it "returns filtered log entries" do + it "renders the index template with filtered log entries" do get :index, params: { filter: "example.com/test" } expect(response).to be_successful + expect(response).to render_template(:index) + end + + it "shows existing log entries matching the filter" do + log_entry = + create( + :http_log_entry, + uri_host: "example.com", + uri_path: "/test", + uri_scheme: "https", + ) + + get :index, params: { filter: "example.com/test" } + + expect(response).to be_successful + expect(assigns(:log_entries)).to include(log_entry) end end describe "GET #stats" do - it "returns statistics in the specified time window" do + it "renders the stats template with time window data" do get :stats, params: { seconds: 3600 } expect(response).to be_successful + expect(response).to render_template(:stats) expect(assigns(:time_window)).to eq 3600.seconds end end + + describe "GET #show" do + let(:log_entry) { create(:http_log_entry) } + + it "renders the show template with the requested log entry" do + get :show, params: { id: log_entry.id } + expect(response).to be_successful + expect(response).to render_template(:show) + expect(assigns(:log_entry)).to eq(log_entry) + end + end end end diff --git a/tmp/pids/.keep b/tmp/pids/.keep deleted file mode 100644 index e69de29b..00000000 diff --git a/tmp/storage/.keep b/tmp/storage/.keep deleted file mode 100644 index e69de29b..00000000