1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
## This Source Code Form is subject to the terms of the Mozilla Public
## License, v. 2.0. If a copy of the MPL was not distributed with this
## file, You can obtain one at https://mozilla.org/MPL/2.0/.
##
## Copyright (c) 2007-2020 VMware, Inc. or its affiliates. All rights reserved.
defmodule RabbitMQ.CLI.Diagnostics.Commands.MemoryBreakdownCommand do
alias RabbitMQ.CLI.InformationUnit, as: IU
import RabbitMQ.CLI.Core.Memory
@behaviour RabbitMQ.CLI.CommandBehaviour
def switches(), do: [unit: :string, timeout: :integer]
def aliases(), do: [t: :timeout]
def merge_defaults(args, opts) do
{args, Map.merge(%{unit: "gb"}, opts)}
end
def validate(args, _) when length(args) > 0 do
{:validation_failure, :too_many_args}
end
def validate(_, %{unit: unit}) do
case IU.known_unit?(unit) do
true ->
:ok
false ->
{:validation_failure, "unit '#{unit}' is not supported. Please use one of: bytes, mb, gb"}
end
end
use RabbitMQ.CLI.Core.RequiresRabbitAppRunning
def run([], %{node: node_name, timeout: timeout}) do
:rabbit_misc.rpc_call(node_name, :rabbit_vm, :memory, [], timeout)
end
def output(result, %{formatter: "json"} = _opts) do
{:ok, compute_relative_values(result)}
end
def output(result, %{formatter: "csv"} = _opts) do
flattened =
compute_relative_values(result)
|> Enum.flat_map(fn {k, %{bytes: b, percentage: p}} ->
[{"#{k}.bytes", b}, {"#{k}.percentage", p}]
end)
|> Enum.sort_by(fn {key, _val} -> key end, &>=/2)
headers = Enum.map(flattened, fn {k, _v} -> k end)
values = Enum.map(flattened, fn {_k, v} -> v end)
{:stream, [headers, values]}
end
def output(result, _opts) do
{:ok, compute_relative_values(result)}
end
def help_section(), do: :observability_and_health_checks
def description(), do: "Provides a memory usage breakdown on the target node."
def usage, do: "memory_breakdown [--unit <unit>]"
def usage_additional() do
[
["--unit <bytes | mb | gb>", "byte multiple (bytes, megabytes, gigabytes) to use"],
["--formatter <json | csv | erlang>", "alternative formatter to use, JSON, CSV or Erlang terms"]
]
end
def banner([], %{node: node_name}) do
"Reporting memory breakdown on node #{node_name}..."
end
defmodule Formatter do
alias RabbitMQ.CLI.Formatters.FormatterHelpers
alias RabbitMQ.CLI.InformationUnit, as: IU
@behaviour RabbitMQ.CLI.FormatterBehaviour
def format_output(output, %{unit: unit}) do
Enum.reduce(output, "", fn {key, %{bytes: bytes, percentage: percentage}}, acc ->
u = String.downcase(unit)
acc <> "#{key}: #{IU.convert(bytes, u)} #{u} (#{percentage}%)\n"
end)
end
def format_stream(stream, options) do
Stream.map(
stream,
FormatterHelpers.without_errors_1(fn el ->
format_output(el, options)
end)
)
end
end
def formatter(), do: Formatter
end
|