216 lines
12 KiB
Plaintext
216 lines
12 KiB
Plaintext
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
|
<div class="sm:flex sm:items-center">
|
|
<div class="sm:flex-auto">
|
|
<h1 class="text-2xl font-semibold text-slate-900">Telegram Bot Audit Logs</h1>
|
|
<p class="mt-2 text-sm text-slate-700">
|
|
Comprehensive audit trail of all Telegram bot interactions and performance metrics.
|
|
</p>
|
|
</div>
|
|
<div class="mt-4 sm:ml-16 sm:mt-0 sm:flex-none">
|
|
<div class="text-sm text-slate-600">
|
|
Showing <%= @telegram_bot_logs.count %> of <%= @telegram_bot_logs.total_count %> logs
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Filter Form -->
|
|
<div class="mt-6 bg-white shadow sm:rounded-lg">
|
|
<div class="px-4 py-4 border-b border-slate-200">
|
|
<h3 class="text-lg font-medium text-slate-900">Filters</h3>
|
|
<%= form_with url: telegram_bot_logs_path, method: :get, local: true, class: "mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4" do |f| %>
|
|
<!-- User ID Filter -->
|
|
<div>
|
|
<%= f.label :telegram_user_id, "Telegram User ID", class: "block text-sm font-medium text-slate-700" %>
|
|
<%= f.number_field :telegram_user_id,
|
|
value: @filter_params[:telegram_user_id],
|
|
class: "mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm",
|
|
placeholder: "Enter user ID" %>
|
|
</div>
|
|
<!-- Status Filter -->
|
|
<div>
|
|
<%= f.label :status, "Status", class: "block text-sm font-medium text-slate-700" %>
|
|
<%= f.select :status,
|
|
options_for_select([["All Statuses", ""]] + @status_options.map { |s| [s.humanize, s] }, @filter_params[:status]),
|
|
{},
|
|
{ class: "mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm" } %>
|
|
</div>
|
|
<!-- Date Range Filters -->
|
|
<div>
|
|
<%= f.label :start_date, "Start Date", class: "block text-sm font-medium text-slate-700" %>
|
|
<%= f.date_field :start_date,
|
|
value: @filter_params[:start_date],
|
|
class: "mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm" %>
|
|
</div>
|
|
<div>
|
|
<%= f.label :end_date, "End Date", class: "block text-sm font-medium text-slate-700" %>
|
|
<%= f.date_field :end_date,
|
|
value: @filter_params[:end_date],
|
|
class: "mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm" %>
|
|
</div>
|
|
<!-- Results Count Filters -->
|
|
<div>
|
|
<%= f.label :min_results, "Min Results", class: "block text-sm font-medium text-slate-700" %>
|
|
<%= f.number_field :min_results,
|
|
value: @filter_params[:min_results],
|
|
min: 0,
|
|
class: "mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm",
|
|
placeholder: "Min results" %>
|
|
</div>
|
|
<div>
|
|
<%= f.label :max_results, "Max Results", class: "block text-sm font-medium text-slate-700" %>
|
|
<%= f.number_field :max_results,
|
|
value: @filter_params[:max_results],
|
|
min: 0,
|
|
class: "mt-1 block w-full rounded-md border-slate-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-sm",
|
|
placeholder: "Max results" %>
|
|
</div>
|
|
<!-- Performance Filter -->
|
|
<div class="flex items-center">
|
|
<%= f.check_box :slow_requests,
|
|
{ checked: @filter_params[:slow_requests] == "true", class: "h-4 w-4 rounded border-slate-300 text-blue-600 focus:ring-blue-500" },
|
|
"true", "" %>
|
|
<%= f.label :slow_requests, "Show slow requests only", class: "ml-2 block text-sm text-slate-700" %>
|
|
</div>
|
|
<!-- Action Buttons -->
|
|
<div class="flex items-end gap-2">
|
|
<%= f.submit "Apply Filters", class: "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded text-sm" %>
|
|
<%= link_to "Clear", telegram_bot_logs_path, class: "bg-slate-500 hover:bg-slate-700 text-white font-bold py-2 px-4 rounded text-sm" %>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
<!-- Logs Table -->
|
|
<% if @telegram_bot_logs.any? %>
|
|
<div class="mt-6 overflow-hidden bg-white shadow sm:rounded-lg">
|
|
<div class="p-3 sm:p-4">
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-slate-300">
|
|
<thead>
|
|
<tr>
|
|
<th class="pb-2 text-left text-sm font-semibold text-slate-900">User</th>
|
|
<th class="pb-2 text-left text-sm font-semibold text-slate-900">Status</th>
|
|
<th class="pb-2 text-left text-sm font-semibold text-slate-900">Results</th>
|
|
<th class="pb-2 text-left text-sm font-semibold text-slate-900">Performance</th>
|
|
<th class="pb-2 text-left text-sm font-semibold text-slate-900">Timestamp</th>
|
|
<th class="relative pb-2"><span class="sr-only">Actions</span></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-slate-200">
|
|
<% @telegram_bot_logs.each do |log| %>
|
|
<tr class="hover:bg-slate-50">
|
|
<td class="py-3 pr-4 text-sm">
|
|
<div class="font-medium text-slate-900 truncate max-w-32">
|
|
<%= log.user_display_name %>
|
|
</div>
|
|
<div class="text-slate-500 text-xs">
|
|
ID: <%= log.telegram_user_id %>
|
|
</div>
|
|
</td>
|
|
<td class="py-3 pr-4 text-sm">
|
|
<% status_color = case log.status
|
|
when "success"
|
|
"bg-green-100 text-green-800"
|
|
when "error"
|
|
"bg-red-100 text-red-800"
|
|
when "no_results"
|
|
"bg-yellow-100 text-yellow-800"
|
|
when "invalid_image"
|
|
"bg-orange-100 text-orange-800"
|
|
else
|
|
"bg-slate-100 text-slate-800"
|
|
end %>
|
|
<span class="<%= status_color %> inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium">
|
|
<%= log.status.humanize %>
|
|
</span>
|
|
</td>
|
|
<td class="py-3 pr-4 text-sm text-slate-500">
|
|
<div class="font-medium text-slate-900">
|
|
<%= log.search_results_count %>
|
|
</div>
|
|
<% if log.search_results_count > 0 %>
|
|
<div class="text-xs text-green-600">
|
|
matches found
|
|
</div>
|
|
<% else %>
|
|
<div class="text-xs text-slate-400">
|
|
no matches
|
|
</div>
|
|
<% end %>
|
|
</td>
|
|
<td class="py-3 pr-4 text-sm text-slate-500">
|
|
<% if log.has_performance_metrics? %>
|
|
<div class="text-xs space-y-1">
|
|
<div class="flex justify-between">
|
|
<span class="text-blue-600">Download:</span>
|
|
<span class="font-mono"><%= sprintf("%.3f", log.download_time) %>s</span>
|
|
</div>
|
|
<% if log.image_processing_time.present? %>
|
|
<div class="flex justify-between">
|
|
<span class="text-purple-600">Process:</span>
|
|
<span class="font-mono"><%= sprintf("%.3f", log.image_processing_time) %>s</span>
|
|
</div>
|
|
<% end %>
|
|
<div class="flex justify-between">
|
|
<span class="text-yellow-600">Fingerprint:</span>
|
|
<span class="font-mono"><%= sprintf("%.3f", log.fingerprint_computation_time) %>s</span>
|
|
</div>
|
|
<div class="flex justify-between">
|
|
<span class="text-green-600">Search:</span>
|
|
<span class="font-mono"><%= sprintf("%.3f", log.search_computation_time) %>s</span>
|
|
</div>
|
|
<div class="flex justify-between font-medium border-t pt-1">
|
|
<span>Total:</span>
|
|
<span class="font-mono
|
|
<%= log.total_request_time && log.total_request_time > 1.0 ? 'text-red-600' : 'text-slate-700' %>">
|
|
<%= log.total_request_time ? sprintf("%.3f", log.total_request_time) : 'N/A' %>s
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<% else %>
|
|
<span class="text-slate-400 text-xs">No metrics</span>
|
|
<% end %>
|
|
</td>
|
|
<td class="py-3 pr-4 text-sm text-slate-500">
|
|
<div class="text-xs">
|
|
<%= log.request_timestamp.strftime("%m/%d/%Y") %>
|
|
</div>
|
|
<div class="text-xs font-mono">
|
|
<%= log.request_timestamp.strftime("%H:%M:%S") %>
|
|
</div>
|
|
<div class="text-xs text-slate-400">
|
|
<%= time_ago_in_words(log.request_timestamp) %> ago
|
|
</div>
|
|
</td>
|
|
<td class="py-3 text-right text-sm font-medium">
|
|
<%= link_to "View", telegram_bot_log_path(log),
|
|
class: "text-blue-600 hover:text-blue-800 font-medium" %>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Pagination -->
|
|
<% if @telegram_bot_logs.respond_to?(:current_page) %>
|
|
<%= render "shared/pagination_controls", collection: @telegram_bot_logs %>
|
|
<% end %>
|
|
<% else %>
|
|
<div class="mt-6 bg-white shadow sm:rounded-lg">
|
|
<div class="px-4 py-6 text-center">
|
|
<div class="mx-auto h-12 w-12 text-slate-400">
|
|
<svg fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-12 h-12">
|
|
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12h3.75M9 15h3.75M9 18h3.75m3-3v-6a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6a2.25 2.25 0 002.25 2.25h10.5A2.25 2.25 0 0019.5 15z" />
|
|
</svg>
|
|
</div>
|
|
<h3 class="mt-2 text-sm font-semibold text-slate-900">No logs found</h3>
|
|
<p class="mt-1 text-sm text-slate-500">No Telegram bot logs match your current filters.</p>
|
|
<div class="mt-6">
|
|
<%= link_to "Clear filters", telegram_bot_logs_path,
|
|
class: "inline-flex items-center rounded-md bg-blue-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600" %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|