| 1 |
|
defmodule Agent.Log do |
| 2 |
|
import File, only: [ls: 1, read!: 1, stat!: 1] |
| 3 |
|
import Path, only: [expand: 1, join: 2] |
| 4 |
|
|
| 5 |
|
import String, |
| 6 |
|
only: [trim_trailing: 2, split: 2, ends_with?: 2, starts_with?: 2] |
| 7 |
|
|
| 8 |
|
import List, only: [last: 1] |
| 9 |
|
|
| 10 |
|
import Enum, |
| 11 |
|
only: [ |
| 12 |
|
filter: 2, |
| 13 |
|
sort_by: 2, |
| 14 |
|
map_join: 3, |
| 15 |
|
group_by: 2, |
| 16 |
|
max_by: 2, |
| 17 |
|
flat_map: 2, |
| 18 |
|
map: 2 |
| 19 |
|
] |
| 20 |
|
|
| 21 |
:-( |
def reply(""), do: "" |
| 22 |
|
|
| 23 |
|
def reply(agent) do |
| 24 |
:-( |
expand("~/.elita/sessions") |> ls() |> open(agent) |
| 25 |
|
end |
| 26 |
|
|
| 27 |
|
defp open({:ok, all}, agent) do |
| 28 |
:-( |
dir = expand("~/.elita/sessions") |
| 29 |
:-( |
latest = rank(all, agent, dir) |> last() |
| 30 |
:-( |
wrap(latest, all, dir) |
| 31 |
|
end |
| 32 |
|
|
| 33 |
:-( |
defp open({:error, _}, _agent), do: "" |
| 34 |
|
|
| 35 |
|
defp wrap({f, _t}, all, dir) do |
| 36 |
:-( |
logs(all, id(f), dir) |
| 37 |
|
end |
| 38 |
|
|
| 39 |
:-( |
defp wrap(nil, _all, _dir) do |
| 40 |
|
"" |
| 41 |
|
end |
| 42 |
|
|
| 43 |
|
defp rank(all, agent, dir) do |
| 44 |
:-( |
journal(all) |> filter(&starts_with?(&1, "#{agent}_")) |> time(dir) |
| 45 |
|
end |
| 46 |
|
|
| 47 |
|
defp logs(all, pid, dir) do |
| 48 |
:-( |
journal(all) |> filter(&(id(&1) == pid)) |> merge(dir) |
| 49 |
|
end |
| 50 |
|
|
| 51 |
:-( |
defp journal(files), do: filter(files, &ends_with?(&1, ".log")) |
| 52 |
|
|
| 53 |
|
defp time(files, dir) do |
| 54 |
:-( |
files |> tag(dir) |> sort_by(fn {_f, t} -> t end) |
| 55 |
|
end |
| 56 |
|
|
| 57 |
|
defp merge(files, dir) do |
| 58 |
:-( |
files |> tag(dir) |> settle() |> map_join("", &fetch(dir, &1)) |
| 59 |
|
end |
| 60 |
|
|
| 61 |
|
defp settle(annotated) do |
| 62 |
:-( |
annotated |> group_by(&gather/1) |> sort_by(&peak/1) |> flat_map(&order/1) |
| 63 |
|
end |
| 64 |
|
|
| 65 |
:-( |
defp gather({f, _}), do: id(f) |
| 66 |
|
|
| 67 |
|
defp tag(files, dir) do |
| 68 |
:-( |
files |> map(fn f -> {f, mtime(dir, f)} end) |
| 69 |
|
end |
| 70 |
|
|
| 71 |
|
defp id(file) do |
| 72 |
:-( |
file |> trim_trailing(".log") |> split("_") |> last() |
| 73 |
|
end |
| 74 |
|
|
| 75 |
|
defp peak({_pid, items}) do |
| 76 |
:-( |
items |> max_by(fn {_f, t} -> t end) |> elem(1) |
| 77 |
|
end |
| 78 |
|
|
| 79 |
|
defp order({_pid, items}) do |
| 80 |
:-( |
items |> sort_by(fn {f, t} -> {t, f} end) |> map(fn {f, _} -> f end) |
| 81 |
|
end |
| 82 |
|
|
| 83 |
:-( |
defp mtime(dir, file) do |
| 84 |
:-( |
dir |> join(file) |> stat!() |> Map.get(:mtime) |
| 85 |
|
rescue |
| 86 |
:-( |
File.Error -> 0 |
| 87 |
|
end |
| 88 |
|
|
| 89 |
:-( |
defp fetch(dir, file) do |
| 90 |
:-( |
dir |> join(file) |> read!() |
| 91 |
|
rescue |
| 92 |
:-( |
File.Error -> "" |
| 93 |
|
end |
| 94 |
|
end |