Skip to content

Commit 96a6f26

Browse files
committed
use last field of the path
1 parent b2d8125 commit 96a6f26

File tree

4 files changed

+141
-214
lines changed

4 files changed

+141
-214
lines changed

lib/logflare_web/live/search_live/log_event_components.ex

Lines changed: 16 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ defmodule LogflareWeb.SearchLive.LogEventComponents do
88
import LogflareWeb.ModalLiveHelpers
99

1010
alias Logflare.DateTimeUtils
11-
alias Logflare.Lql
1211
alias Logflare.Sources.Source
1312
alias Logflare.Lql
1413
alias Phoenix.LiveView.JS
@@ -32,14 +31,7 @@ defmodule LogflareWeb.SearchLive.LogEventComponents do
3231
<.log_event :for={log <- @search_op_log_events.rows} timezone={@search_timezone} log_event={log} select_fields={build_select_fields(@search_op)}>
3332
{log.body["event_message"]}
3433
<:actions phx-no-format>
35-
<.link phx-click="show_modal"
36-
phx-value-event-id={log.id}
37-
class="tw-text-[0.65rem]"
38-
phx-value-log-event-timestamp={log.body["timestamp"]}
39-
phx-value-lql={@querystring}
40-
>
41-
<span>view2</span>
42-
</.link>
34+
<div class={if(Enum.any?(@select_fields), do: "tw-ml-[13rem] tw-pb-1.5", else: "tw-inline")}>
4335
<.modal_link
4436
component={LogflareWeb.Search.LogEventViewerComponent}
4537
class="tw-text-[0.65rem]"
@@ -59,7 +51,7 @@ defmodule LogflareWeb.SearchLive.LogEventComponents do
5951
modal_id={:log_event_context_viewer}
6052
title="View Event Context"
6153
phx-value-log-event-id={log.id}
62-
phx-value-source-id={@search_op.source.id}
54+
phx-value-source-id={@search_op.source.id}
6355
phx-value-log-event-timestamp={log.body["timestamp"]}
6456
phx-value-timezone={@search_timezone}
6557
phx-value-querystring={@querystring}
@@ -72,83 +64,23 @@ defmodule LogflareWeb.SearchLive.LogEventComponents do
7264
phx-click={
7365
JS.dispatch("logflare:copy-to-clipboard",
7466
detail: %{
75-
text: "#{LogflareWeb.SearchLive.LogEventComponents.formatted_timestamp(log, assigns[:search_timezone])} #{log.body["event_message"]}"
67+
text: formatted_for_clipboard(log, @search_op)
7668
}
7769
)
7870
}
7971
data-toggle="tooltip"
8072
data-placement="top"
8173
title="Copy to clipboard"
8274
>copy</.link>
83-
<.log_event_permalink log_event_id={log.id} timestamp={log.body["timestamp"]} source={@search_op.source} lql={@querystring} class="tw-text-[0.65rem] group-hover:tw-visible tw-invisible" />
75+
<.log_event_permalink log_event_id={log.id} timestamp={log.body["timestamp"]} source={@search_op.source} lql={lql_with_recommended_fields(@search_op.lql_rules, log, @search_op.source)} class="tw-text-[0.65rem] group-hover:tw-visible tw-invisible" />
76+
</div>
8477
</:actions>
8578
</.log_event>
8679
</ul>
8780
</div>
8881
"""
8982
end
9083

91-
attr :log, :any, required: true
92-
attr :recommended_query, :any, required: true
93-
attr :tailing?, :boolean, default: false
94-
attr :source, :any, required: true
95-
attr :search_timezone, :string, required: true
96-
attr :querystring, :string, required: true
97-
98-
def logs_list_actions(assigns) do
99-
~H"""
100-
<%= live_modal_show_link(
101-
component: LogflareWeb.Search.LogEventViewerComponent,
102-
class: "tw-text-[0.65rem]",
103-
modal_id: :log_event_viewer,
104-
title: "Log Event",
105-
phx_value_log_event_id: @log.id,
106-
phx_value_log_event_timestamp: @log.body["timestamp"],
107-
phx_value_lql: @recommended_query
108-
) do %>
109-
<span>view</span>
110-
<% end %>
111-
<%= live_modal_show_link(
112-
component: LogflareWeb.SearchLive.EventContextComponent,
113-
click: JS.push("soft_pause"),
114-
close:
115-
if(@tailing?,
116-
do:
117-
JS.push("soft_play", target: "#source-logs-search-control")
118-
|> JS.push("close"),
119-
else: nil
120-
),
121-
class: "tw-text-[0.65rem]",
122-
modal_id: :log_event_context_viewer,
123-
title: "View Event Context",
124-
phx_value_log_event_id: @log.id,
125-
phx_value_source_id: @source.id,
126-
phx_value_log_event_timestamp: @log.body["timestamp"],
127-
phx_value_timezone: @search_timezone,
128-
phx_value_querystring: @querystring
129-
) do %>
130-
<span>context</span>
131-
<% end %>
132-
133-
<.link
134-
class="tw-text-[0.65rem] group-hover:tw-visible tw-invisible"
135-
phx-click={
136-
JS.dispatch("logflare:copy-to-clipboard",
137-
detail: %{
138-
text: "#{formatted_timestamp(@log, @search_timezone)} #{@log.body["event_message"]}"
139-
}
140-
)
141-
}
142-
data-toggle="tooltip"
143-
data-placement="top"
144-
title="Copy to clipboard"
145-
>
146-
copy
147-
</.link>
148-
<.log_event_permalink log_event_id={@log.id} timestamp={@log.body["timestamp"]} source={@source} lql={@recommended_query} class="tw-text-[0.65rem] group-hover:tw-visible tw-invisible" />
149-
"""
150-
end
151-
15284
@spec lql_with_recommended_fields(Lql.Rules.lql_rules(), Logflare.LogEvent.t(), Source.t()) ::
15385
String.t()
15486
def lql_with_recommended_fields(lql_rules, event, source) do
@@ -262,7 +194,7 @@ defmodule LogflareWeb.SearchLive.LogEventComponents do
262194
<%= for field <- @select_fields do %>
263195
<div class="tw-text-neutral-200 tw-flex tw-leading-6">
264196
<div class="tw-w-[13rem] tw-text-right ">
265-
<span class="tw-w-fit tw-px-1 tw-py-0.5 tw-bg-neutral-500/50 tw-text-white tw-mr-2">{field.display}</span>
197+
<span class="tw-whitespace-nowrap tw-w-fit tw-px-1 tw-py-0.5 tw-bg-neutral-600 tw-text-white tw-mr-2">{truncate_display(field.display)}</span>
266198
</div>
267199
<span class="tw-text-white">{get_field_value(@log_event.body, field.key)}</span>
268200
</div>
@@ -290,7 +222,8 @@ defmodule LogflareWeb.SearchLive.LogEventComponents do
290222
|> Enum.map(fn
291223
%{path: path, alias: nil} ->
292224
key = String.replace(path, ".", "_")
293-
%{display: path, key: key}
225+
display = path |> String.split(".") |> List.last()
226+
%{display: display, key: key}
294227

295228
%{path: _path, alias: alias} ->
296229
%{display: alias, key: alias}
@@ -299,4 +232,12 @@ defmodule LogflareWeb.SearchLive.LogEventComponents do
299232
end
300233

301234
defp build_select_fields(_), do: []
235+
236+
defp truncate_display(display) when is_binary(display) do
237+
if String.length(display) > 23 do
238+
(String.slice(display, 0, 23) <> "&hellip;") |> raw()
239+
else
240+
display
241+
end
242+
end
302243
end

test/logflare_web/live/search_live/log_event_components_test.exs

Lines changed: 124 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,129 @@
11
defmodule LogflareWeb.SearchLive.LogEventComponentsTest do
2-
use LogflareWeb.ConnCase, async: true
2+
use LogflareWeb.ConnCase, async: false
33

44
import Phoenix.LiveViewTest
55
import Phoenix.Component
66

7+
alias Logflare.Lql
8+
alias Logflare.Sources.Source
79
alias LogflareWeb.SearchLive.LogEventComponents
810

11+
@default_attrs %{
12+
search_op_log_events: nil,
13+
last_query_completed_at: nil,
14+
loading: false,
15+
search_timezone: "Etc/UTC",
16+
tailing?: false,
17+
querystring: "",
18+
lql_rules: [],
19+
source: nil,
20+
search_op: nil
21+
}
22+
23+
defmodule TestLive do
24+
use LogflareWeb, :live_view
25+
26+
def render(assigns) do
27+
~H"""
28+
<div>
29+
<LogEventComponents.results_list
30+
search_op_log_events={@search_op_log_events}
31+
search_op={@search_op}
32+
last_query_completed_at={@last_query_completed_at}
33+
loading={@loading}
34+
search_timezone={@search_timezone}
35+
tailing?={@tailing?}
36+
querystring={@querystring}
37+
/>
38+
</div>
39+
"""
40+
end
41+
42+
def mount(_params, session, socket) do
43+
{:ok,
44+
assign(socket,
45+
search_op_log_events: session["search_op_log_events"],
46+
search_op: session["search_op"],
47+
last_query_completed_at: session["last_query_completed_at"],
48+
loading: session["loading"],
49+
search_timezone: session["search_timezone"],
50+
tailing?: session["tailing?"],
51+
querystring: session["querystring"]
52+
)}
53+
end
54+
end
55+
56+
describe "results_list/1" do
57+
setup do
58+
user = insert(:user)
59+
60+
source =
61+
insert(:source,
62+
user: user,
63+
suggested_keys: "m.user_id",
64+
bigquery_clustering_fields: "session_id"
65+
)
66+
67+
search_op_log_events = %{
68+
rows: [
69+
build(:log_event, message: "Log message 1", metadata: %{user_id: 123}, source: source)
70+
]
71+
}
72+
73+
{:ok, lql_rules} =
74+
Lql.decode(
75+
"c:count(*) c:group_by(t::minute)",
76+
Source.BigQuery.SchemaBuilder.initial_table_schema()
77+
)
78+
79+
[
80+
source: source,
81+
search_op_log_events: search_op_log_events,
82+
lql_rules: lql_rules
83+
]
84+
end
85+
86+
test "renders log events list", %{
87+
source: source,
88+
search_op_log_events: search_op_log_events,
89+
lql_rules: lql_rules
90+
} do
91+
html =
92+
render_component(&LogEventComponents.results_list/1, %{
93+
@default_attrs
94+
| search_op: %{source: source, lql_rules: lql_rules, search_timezone: "Etc/UTC"},
95+
search_op_log_events: search_op_log_events
96+
})
97+
98+
assert html =~ "Log message 1"
99+
end
100+
101+
test "renders loading state", %{source: source, lql_rules: lql_rules} do
102+
html =
103+
render_component(&LogEventComponents.results_list/1, %{
104+
@default_attrs
105+
| loading: true,
106+
search_op: %{source: source, lql_rules: lql_rules, search_timezone: "Etc/UTC"},
107+
search_op_log_events: %{rows: []}
108+
})
109+
110+
assert html =~ ~r|id="logs-list" class="(.*)blurred"|
111+
end
112+
113+
test "renders empty state when no log events", %{source: source, lql_rules: lql_rules} do
114+
html =
115+
render_component(&LogEventComponents.results_list/1, %{
116+
@default_attrs
117+
| search_op: %{source: source, lql_rules: lql_rules, search_timezone: "Etc/UTC"},
118+
loading: false,
119+
search_op_log_events: nil
120+
})
121+
122+
# Assert logs list ul is NOT rendered when search_op_log_events is nil
123+
refute html =~ ~s|id="logs-list"|
124+
end
125+
end
126+
9127
describe "selected_fields/1" do
10128
test "renders selected fields with display names and values" do
11129
log_event =
@@ -31,11 +149,11 @@ defmodule LogflareWeb.SearchLive.LogEventComponentsTest do
31149
<LogEventComponents.selected_fields log_event={@log_event} select_fields={@select_fields} />
32150
""")
33151

34-
assert html =~ "metadata.user_id:"
152+
assert html =~ "user_id"
35153
assert html =~ "user_123"
36-
assert html =~ "metadata.store.city:"
154+
assert html =~ "city"
37155
assert html =~ "San Francisco"
38-
assert html =~ "food:"
156+
assert html =~ "food"
39157
assert html =~ "Pizza"
40158
end
41159

@@ -56,7 +174,7 @@ defmodule LogflareWeb.SearchLive.LogEventComponentsTest do
56174
<LogEventComponents.selected_fields log_event={@log_event} select_fields={@select_fields} />
57175
""")
58176

59-
assert html =~ "metadata.user_id:"
177+
assert html =~ "metadata.user_id"
60178
assert html =~ "null"
61179
end
62180
end
@@ -86,7 +204,7 @@ defmodule LogflareWeb.SearchLive.LogEventComponentsTest do
86204
assert LogEventComponents.formatted_for_clipboard(log_event, search_op) =~ """
87205
Fri Feb 13 2009 15:31:30-08:00 User login successful
88206
89-
metadata.user_id: user_123
207+
user_id: user_123
90208
91209
city: San Francisco
92210

0 commit comments

Comments
 (0)