Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
0850-observer-etop-Calculate-field-width-with-a...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0850-observer-etop-Calculate-field-width-with-available-c.patch of Package erlang
From 1a4bfb2153b9bfcd9c923e25ed697ebf64000d0e Mon Sep 17 00:00:00 2001 From: Per Andersson <avtobiff@foo.nu> Date: Wed, 29 Dec 2021 16:14:00 +0100 Subject: [PATCH] observer/etop: Calculate field width with available columns The field widths are calculated depending on what the underlying io driver reports as max column width. The fields are allowed to use the column width they need if they column budget allows it. The field widths are deducted in priority order and if there is space left the calculated width is used otherwise the default field width is used. If the underlying io driver can't give any column width, the default column width budget of 89 characters is used. This is the legacy hard coded width, plus two spaces between reductions, memory, and msgq fields. Fixes #5080 Signed-off-by: Per Andersson <avtobiff@foo.nu> --- lib/observer/src/etop_txt.erl | 161 ++++++++++++++++++++++++++++++---- 1 file changed, 143 insertions(+), 18 deletions(-) diff --git a/lib/observer/src/etop_txt.erl b/lib/observer/src/etop_txt.erl index cd3ec62c13..81680e9df8 100644 --- a/lib/observer/src/etop_txt.erl +++ b/lib/observer/src/etop_txt.erl @@ -27,6 +27,16 @@ -include("etop.hrl"). -include("etop_defs.hrl"). +-define(DEFAULT_WIDTH, 89). + +-record(field_widths, {cols :: pos_integer(), + used_cols :: pos_integer(), + init_func :: pos_integer(), + reds :: pos_integer(), + mem :: pos_integer(), + msgq :: pos_integer(), + curr_func :: pos_integer()}). + -import(etop,[loadinfo/2,meminfo/2]). stop(Pid) -> Pid ! stop. @@ -49,8 +59,9 @@ do_update(Prev,Config) -> do_update(Fd,Info,Prev,Config) -> {Cpu,NProcs,RQ,Clock} = loadinfo(Info,Prev), + FieldWidths = calc_field_widths(Info#etop_info.procinfo), io:nl(Fd), - writedoubleline(Fd), + writedoubleline(Fd, FieldWidths), case Info#etop_info.memi of undefined -> io:fwrite(Fd, " ~-72w~10s~n" @@ -69,21 +80,124 @@ do_update(Fd,Info,Prev,Config) -> RQ,Atom,Ets]) end, io:nl(Fd), - writepinfo_header(Fd), - writesingleline(Fd), - writepinfo(Fd,Info#etop_info.procinfo,modifier(Fd)), - writedoubleline(Fd), + writepinfo_header(Fd, FieldWidths), + writesingleline(Fd, FieldWidths), + writepinfo(Fd, Info#etop_info.procinfo, modifier(Fd), FieldWidths), + writedoubleline(Fd, FieldWidths), io:nl(Fd), Info. -writepinfo_header(Fd) -> - io:fwrite(Fd,"Pid Name or Initial Func Time Reds Memory MsgQ Current Function~n",[]). -writesingleline(Fd) -> - io:fwrite(Fd,"----------------------------------------------------------------------------------------~n",[]). -writedoubleline(Fd) -> - io:fwrite(Fd,"========================================================================================~n",[]). - +calc_field_widths(ProcInfoL) -> + Cols = case io:columns() of + {ok, IoCols} -> max(IoCols, ?DEFAULT_WIDTH); + {error, enotsup} -> ?DEFAULT_WIDTH + end, + + %% There is a priority with the field calculation since it's done + %% sequential with all fields deducted with their default values from + %% start. If any field eventually exceed the column budget, the rest of the + %% columns will get their default widths. + + %% Calculate columns left. NOTE: The extra spaces between reds/mem/msgq. + %% Subsequent calculations adds default width then deducts calculated width. + %% See proc_format/2 for fields format. + %% Columns: pid, init_func, time, reds, mem, msgq, curr_func. + ColsLeft0 = Cols - 15 - 20 - 8 - 8 - 1 - 8 - 1 - 8 - 20, + + RedsWidth = get_width(reds, ProcInfoL, ColsLeft0), + + ColsLeft1 = ColsLeft0 + 8 - RedsWidth, + + MemWidth = get_width(mem, ProcInfoL, ColsLeft1), + + ColsLeft2 = ColsLeft1 + 8 - MemWidth, + + MsgQWidth= get_width(msgq, ProcInfoL, ColsLeft2), + + ColsLeft3 = ColsLeft2 + 8 - MsgQWidth, + + %% Use the rest for initial and current function fields + if ColsLeft3 > 0 -> + %% compensate field start width for rounding + FieldSize = 19 + round((ColsLeft3 - 1) / 2), + InitFuncWidth = FieldSize, + CurrFuncWidth = FieldSize; + true -> + InitFuncWidth = 20, + CurrFuncWidth = 20 + end, + + %% Extra space between reds/mem, extra space due to rounding + UsedCols = + 15 + InitFuncWidth + 8 + RedsWidth + 1 + MemWidth + 1 + + MsgQWidth + CurrFuncWidth + 1, + + #field_widths{cols = Cols, + used_cols = UsedCols, + init_func = InitFuncWidth, + reds = RedsWidth, + mem = MemWidth, + msgq = MsgQWidth, + curr_func = CurrFuncWidth}. + + +get_width(reds, ProcInfoL, ColsLeft) -> + get_width(4, ProcInfoL, ColsLeft); +get_width(mem, ProcInfoL, ColsLeft) -> + get_width(3, ProcInfoL, ColsLeft); +get_width(msgq, ProcInfoL, ColsLeft) -> + get_width(8, ProcInfoL, ColsLeft); + +%% Get the maximum width of the field at place N in #sysinfo{}. +%% Calculate the maximum width by taking the maximum width (by taking common +%% logarithm of largest number) then check if is larger than 8 and that it +%% fits the column budget, if so return that value; otherwise return 8. +get_width(N, ProcInfoL, ColsLeft) -> + MaxNum = lists:foldr(fun(Info, Acc) + when element(N, Info) > Acc -> + element(N, Info); + (_, Acc) -> + Acc + end, + 0, + ProcInfoL), + + MaxWidth = + if MaxNum > 0 -> round(math:log10(MaxNum)) + 1; + true -> 1 %% logarithm defined in R_n, n > 0. + end, + + if MaxWidth > 8 andalso ColsLeft - MaxWidth > 0 -> + MaxWidth; + true -> + 8 + end. + + +writepinfo_header(Fd, #field_widths{init_func = InitFunc, reds = Reds, + mem = Mem, msgq = MsgQ}) -> + %% Add spaces between variable width columns. + Header = + "Pid Name or Initial Func" + ++ lists:duplicate(max(InitFunc - 16, 4), $\s) ++ + "Time" + ++ lists:duplicate(max(Reds - 4, 4), $\s) ++ + "Reds" + ++ lists:duplicate(max(Mem - 5, 3), $\s) ++ + "Memory" + ++ lists:duplicate(max(MsgQ - 3, 5), $\s) ++ + "MsgQ Current Function\n", + + io:fwrite(Fd, Header, []). + +writesingleline(Fd, FieldWidths) -> writedupline(Fd, $-, FieldWidths). +writedoubleline(Fd, FieldWidths) -> writedupline(Fd, $=, FieldWidths). + +writedupline(Fd, Char, #field_widths{used_cols = UsedCols}) -> + Line = lists:duplicate(UsedCols, Char) ++ "\n", + io:fwrite(Fd, Line, []). + writepinfo(Fd,[#etop_proc_info{pid=Pid, mem=Mem, reds=Reds, @@ -92,22 +206,33 @@ writepinfo(Fd,[#etop_proc_info{pid=Pid, cf=MFA, mq=MQ} |T], - Modifier) -> - io:fwrite(Fd,proc_format(Modifier), + Modifier, FieldWidths) -> + io:fwrite(Fd,proc_format(Modifier, FieldWidths), [Pid,to_string(Name,Modifier),Time,Reds,Mem,MQ, to_string(MFA,Modifier)]), - writepinfo(Fd,T,Modifier); -writepinfo(_Fd,[],_) -> + writepinfo(Fd,T,Modifier, FieldWidths); +writepinfo(_Fd,[],_,_) -> ok. -proc_format(Modifier) -> - "~-15w~-20"++Modifier++"s~8w~8w~8w~8w ~-20"++Modifier++"s~n". +proc_format(Modifier, #field_widths{init_func = InitFunc, reds = Reds, + mem = Mem, msgq = MsgQ, + curr_func = CurrFunc}) -> + "~-15w" + "~-" ++ i2l(InitFunc) ++ Modifier ++ "s" + "~8w" + "~" ++ i2l(Reds) ++ "w " + "~" ++ i2l(Mem) ++"w " + "~" ++ i2l(MsgQ) ++ "w " + "~-" ++ i2l(CurrFunc) ++ Modifier ++ "s~n". + to_string({M,F,A},Modifier) -> io_lib:format("~w:~"++Modifier++"w/~w",[M,F,A]); to_string(Other,Modifier) -> io_lib:format("~"++Modifier++"w",[Other]). +i2l(I) -> integer_to_list(I). + modifier(Device) -> case encoding(Device) of latin1 -> ""; -- 2.31.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor