293
292
pre(pretty_format(Info))].
295
294
%%%-----------------------------------------------------------------
296
%%% Make table with summary of process information
297
procs_summary(Sorted,ProcsSummary,TW,SharedHeap) ->
298
Heading = "Process Information",
301
procs_summary_body(Heading,ProcsSummary,TW,Sorted,SharedHeap))).
303
procs_summary_body(Heading,[],TW,_Sorted,_SharedHeap) ->
306
"No processes were found\n"];
307
procs_summary_body(Heading,ProcsSummary,TW,Sorted,SharedHeap) ->
315
[heading(Heading,"processes"),
318
"BORDER=4 CELLPADDING=4",
320
[summary_table_head("pid","Pid",Sorted),
321
summary_table_head("name_func","Name/Spawned as",Sorted),
322
summary_table_head("state","State",Sorted),
323
summary_table_head("reds","Reductions",Sorted),
324
summary_table_head("mem",MemHeading,Sorted),
325
summary_table_head("msg_q_len","MsgQ Length",Sorted)]) |
326
lists:map(fun(Proc) -> procs_summary_table(Proc) end,ProcsSummary)])].
328
summary_table_head(Sorted,Text,Sorted) ->
329
%% Mark the sorted column (bigger and italic)
330
th(font("SIZE=\"+1\"",em(href("./sort_procs?sort="++Sorted,Text))));
331
summary_table_head(SortOn,Text,_Sorted) ->
332
th(href("./sort_procs?sort="++SortOn,Text)).
334
procs_summary_table(Proc) ->
335
#proc{pid=Pid,name=Name,state=State,
336
reds=Reds,stack_heap=Mem0,msg_q_len=MsgQLen}=Proc,
339
_ -> integer_to_list(Mem0)
342
[td(href(["./proc_details?pid=",Pid],Pid)),
345
td("ALIGN=right",integer_to_list(Reds)),
346
td("ALIGN=right",Mem),
347
td("ALIGN=right",integer_to_list(MsgQLen))]).
349
%%%-----------------------------------------------------------------
350
295
%%% Print details for one process
351
296
proc_details(Pid,Proc,TW,SharedHeap) ->
592
537
href("javascript:history.go(-1)","BACK")].
594
539
%%%-----------------------------------------------------------------
595
%%% Print table of ports
596
ports(Heading,Ports,TW) ->
597
header(Heading,body(ports_body(Heading,Ports,TW))).
540
%%% Print info for one port
541
port(Heading,Port,TW) ->
542
header(Heading,body(port_body(Heading,Port,TW))).
599
ports_body(Heading,[],TW) ->
602
"No ports were found\n"];
603
ports_body(Heading,Ports,TW) ->
544
port_body(Heading,Port,TW) ->
604
545
[heading(Heading,"ports"),
607
548
"BORDER=4 CELLPADDING=4",
614
lists:map(fun(Port) -> ports_table(Port) end, Ports)])].
549
[tr([th(Head) || Head <- port_table_head()]), ports_table(Port)])].
617
#port{id=Id,slot=Slot,connected=Connected,links=Links,
618
controls=Controls}=Port,
621
td("ALIGHT=right",Slot),
622
td(href_proc_port(Connected)),
623
td(href_proc_port(Links)),
626
551
%%%-----------------------------------------------------------------
627
%%% Print table of ETS tables
628
ets_tables(Heading,EtsTables,InternalEts,TW) ->
629
header(Heading,body(ets_tables_body(Heading,EtsTables,InternalEts,TW))).
552
%%% Print table of internal ETS tables
553
internal_ets_tables(InternalEts,TW) ->
554
Heading = "Internal ETS tables",
555
header(Heading,body(internal_ets_tables_body(Heading,InternalEts,TW))).
631
ets_tables_body(Heading,[],InternalEts,TW) ->
557
internal_ets_tables_body(Heading,[],TW) ->
634
"No ETS tables were found\n" |
635
internal_ets_tables_table(InternalEts)];
636
ets_tables_body(Heading,EtsTables,InternalEts,TW) ->
637
[heading(Heading,"ets_tables"),
560
"No internal ETS tables were found\n"];
561
internal_ets_tables_body(Heading,InternalEts,TW) ->
562
[heading(Heading,"internal_ets_tables"),
640
565
"BORDER=4 CELLPADDING=4",
649
th("Memory (bytes)")]) |
650
lists:map(fun(EtsTable) -> ets_tables_table(EtsTable) end,
652
internal_ets_tables_table(InternalEts)].
654
ets_tables_table(EtsTable) ->
655
#ets_table{pid=Pid,slot=Slot,id=Id,name=Name,type=Type,
656
buckets=Buckets,size=Size,memory=Memory} = EtsTable,
658
[td(href_proc_port(Pid)),
663
td("ALIGN=right",Buckets),
664
td("ALIGN=right",Size),
665
td("ALIGN=right",Memory)]).
667
internal_ets_tables_table(InternalEtsTables) ->
668
[h2("Internal ETS tables"),
670
"BORDER=4 CELLPADDING=4",
672
567
[th("Description"),
825
693
_ -> font("COLOR=\"#FF0000\"",["ERROR: ",Error,"\n"])
827
%%%-----------------------------------------------------------------
828
%%% Print loaded modules information
829
loaded_mods({CC,OC,LM},TW) ->
830
Heading = "Loaded Modules Information",
831
header(Heading,body(loaded_mods_body(Heading,CC,OC,LM,TW))).
833
loaded_mods_body(Heading,"unknown","unknown",[],TW) ->
836
"No loaded modules information was found\n"];
837
loaded_mods_body(Heading,CC,OC,LM,TW) ->
838
[heading(Heading,"loaded_modules"),
840
p([b("Current code: "),CC," bytes",br(),
841
b("Old code: "),OC," bytes"]),
843
"BORDER=4 CELLPADDING=4",
845
th("Current size (bytes)"),
846
th("Old size (bytes)")]) |
847
lists:map(fun(Mod) -> loaded_mods_table(Mod) end,LM)])].
849
loaded_mods_table(#loaded_mod{mod=Mod,current_size=CS,old_size=OS}) ->
850
tr([td(href(["loaded_mod_details?mod=",Mod],Mod)),
851
td("ALIGN=right",CS),
852
td("ALIGN=right",OS)]).
855
696
%%%-----------------------------------------------------------------
856
697
%%% Print detailed information about one module
882
723
%%%-----------------------------------------------------------------
883
%%% Print table of funs
885
Heading = "Fun Information",
886
header(Heading,body(funs_body(Heading,Funs,TW))).
888
funs_body(Heading,[],TW) ->
891
"No Fun information was found\n"];
892
funs_body(Heading,Funs,TW) ->
893
[heading(Heading,"funs"),
896
"BORDER=4 CELLPADDING=4",
902
th("Native_address"),
904
lists:map(fun(Fun) -> funs_table(Fun) end, Funs)])].
907
#fu{module=Module,uniq=Uniq,index=Index,address=Address,
908
native_address=NativeAddress,refc=Refc}=Fu,
911
td("ALIGN=right",Uniq),
912
td("ALIGN=right",Index),
915
td("ALIGN=right",Refc)]).
917
%%%-----------------------------------------------------------------
919
atoms(Atoms,Num,TW) ->
725
atoms(SessionId,TW,Num,FirstChunk) ->
920
726
Heading = "Atoms",
921
header(Heading,body(atoms_body(Heading,Atoms,Num,TW))).
923
atoms_body(Heading,[],Num,TW) ->
926
"No atoms were found in log",br(),
927
"Total number of atoms in node was ", Num, br()];
928
atoms_body(Heading,Atoms,Num,TW) ->
929
[heading(Heading,"atoms"),
931
"Total number of atoms in node was ", Num,
933
"The last created atom is shown first",
937
n_first({n_lines,Start,N,What,Lines,Pos}) ->
938
NextHref = next_href(N,What,Pos,Start),
939
[What," number ",integer_to_list(Start),"-",integer_to_list(Start+N-1),
944
n_first({n_lines,_Start,_N,_What,Lines}) ->
947
%%%-----------------------------------------------------------------
948
%%% Print next N lines of "something"
950
header(element(4,NLines),body(next_body(NLines,TW))).
952
next_body({n_lines,Start,N,What,Lines,Pos},TW) ->
953
PrefHref = prev_href(),
954
NextHref = next_href(N,What,Pos,Start),
956
What," number ",integer_to_list(Start),"-",integer_to_list(Start+N-1),
965
next_body({n_lines,Start,N,What,Lines},TW) ->
966
PrefHref = prev_href(),
968
What," number ",integer_to_list(Start),"-",integer_to_list(Start+N-1),
976
href("javascript:history.back()",["Previous"]).
978
next_href(N,What,Pos,Start) ->
979
href(["./next?pos=",integer_to_list(Pos),
980
"&num=",integer_to_list(N),
981
"&start=",integer_to_list(Start+N),
729
deliver_first(SessionId,[start_html_page(Heading),
732
"No atoms were found in log",br(),
733
"Total number of atoms in node was ", Num,
736
deliver_first(SessionId,[start_html_page(Heading),
737
heading(Heading,"atoms"),
739
"Total number of atoms in node was ", Num,
741
"The last created atom is shown first",
744
atoms_chunk(SessionId,FirstChunk)
747
atoms_chunk(SessionId,done) ->
748
deliver(SessionId,[stop_pre(),stop_html_page()]);
749
atoms_chunk(SessionId,Atoms) ->
750
deliver(SessionId,Atoms).
985
752
%%%-----------------------------------------------------------------
986
753
%%% Print memory information
1122
890
lists:map(fun(IndexTable) -> index_tables_table(IndexTable) end,
1123
891
IndexTables)])].
1125
893
index_tables_table(IndexTable) ->
1126
#index_table{name=Name,size=Size,limit=Limit,used=Used,rate=Rate} =
894
#index_table{name=Name,size=Size,limit=Limit,used=Used,
895
rate=Rate,entries=Entries} = IndexTable,
1130
898
td("ALIGN=right",Size),
1131
899
td("ALIGN=right",Limit),
1132
900
td("ALIGN=right",Used),
1133
td("ALIGN=right",Rate)]).
901
td("ALIGN=right",Rate),
902
td("ALIGN=right",Entries)]).
1135
904
%%%-----------------------------------------------------------------
1136
905
%%% Internal library
906
start_html_page(Title) ->
909
only_html_header(Title),
916
only_http_header() ->
917
["Pragma:no-cache\r\n",
918
"Content-type: text/html\r\n\r\n"].
920
only_html_header(Title) ->
921
only_html_header(Title,"").
922
only_html_header(Title,JavaScript) ->
924
"<TITLE>", Title, "</TITLE>\n",
933
"<BODY BGCOLOR=\"#FFFFFF\">\n".
1138
938
header("","",Body).
1139
939
header(Title,Body) ->
1140
940
header(Title,"",Body).
1141
941
header(Title,JavaScript,Body) ->
1142
["Pragma:no-cache\r\n",
1143
"Content-type: text/html\r\n\r\n",
1144
943
html_header(Title,JavaScript,Body)].
1146
945
html_header(Title,JavaScript,Body) ->
1149
"<TITLE>", Title, "</TITLE>\n",
947
only_html_header(Title,JavaScript),
1156
["<BODY BGCOLOR=\"#FFFFFF\">\n",
1160
956
frameset(Args,Frames) ->
1161
957
["<FRAMESET ",Args,">\n", Frames, "\n</FRAMESET>\n"].
1163
959
["<FRAME ",Args, ">\n"].
961
start_visible_table() ->
962
start_table("BORDER=\"4\" CELLPADDING=\"4\"").
963
start_visible_table(ColTitles) ->
964
[start_visible_table(),
965
tr([th(ColTitle) || ColTitle <- ColTitles])].
968
["<TABLE ", Args, ">\n"].
1165
972
table(Args,Text) ->
1166
["<TABLE ", Args, ">\n", Text, "\n</TABLE>\n"].
973
[start_table(Args), Text, stop_table()].
1168
975
["<TR>\n", Text, "\n</TR>\n"].
1169
976
tr(Args,Text) ->
1429
1238
replace_insrt(T,Insrt,[H|Acc]);
1430
1239
replace_insrt([],[],Acc) ->
1242
%%%-----------------------------------------------------------------
1243
%%% Create a page with one table by delivering chunk by chunk to
1244
%%% inets. crashdump_viewer first calls chunk_page/5 once, then
1245
%%% chunk/3 multiple times until all data is delivered.
1246
chunk_page(processes,SessionId,TW,{Sorted,SharedHeap},FirstChunk) ->
1247
Columns = procs_summary_table_head(Sorted,SharedHeap),
1248
chunk_page(SessionId, "Process Information", TW, FirstChunk,
1249
"processes", Columns, fun procs_summary_table/1);
1250
chunk_page(ports,SessionId,TW,_,FirstChunk) ->
1251
chunk_page(SessionId, "Port Information", TW, FirstChunk,
1252
"ports", port_table_head(), fun ports_table/1);
1253
chunk_page(ets_tables,SessionId,TW,Heading,FirstChunk) ->
1262
chunk_page(SessionId, Heading, TW, FirstChunk,
1263
"ets_tables", Columns, fun ets_tables_table/1);
1264
chunk_page(timers,SessionId,TW,Heading,FirstChunk) ->
1265
chunk_page(SessionId, Heading, TW, FirstChunk, "timers",
1266
["Owner","Message","Time left"], fun timers_table/1);
1267
chunk_page(loaded_mods,SessionId,TW,{CC,OC},FirstChunk) ->
1268
TotalsInfo = p([b("Current code: "),CC," bytes",br(),
1269
b("Old code: "),OC," bytes"]),
1270
Columns = ["Module","Current size (bytes)","Old size (bytes)"],
1271
chunk_page(SessionId, "Loaded Modules Information", TW, FirstChunk,
1272
"loaded_modules", TotalsInfo,Columns, fun loaded_mods_table/1);
1273
chunk_page(funs,SessionId, TW, _, FirstChunk) ->
1274
Columns = ["Module",
1280
chunk_page(SessionId, "Fun Information", TW, FirstChunk,
1281
"funs", Columns, fun funs_table/1).
1283
chunk_page(SessionId,Heading,TW,FirstChunk,Type,TableColumns,TableFun) ->
1284
chunk_page(SessionId,Heading,TW,FirstChunk,Type,[],TableColumns,TableFun).
1285
chunk_page(SessionId,Heading,TW,done,Type,_TotalsInfo,_TableColumns,_TableFun) ->
1286
no_info_found(SessionId,Heading,TW,Type);
1287
chunk_page(SessionId,Heading,TW,FirstChunk,Type,TotalsInfo,TableColumns,TableFun) ->
1288
deliver_first(SessionId,[start_html_page(Heading),
1289
heading(Heading,Type),
1292
start_visible_table(TableColumns)]),
1293
chunk(SessionId,FirstChunk,TableFun),
1296
no_info_found(SessionId, Heading, TW, Type) ->
1297
Info = ["No ", Type, " were found\n"],
1298
deliver_first(SessionId,[start_html_page(Heading),
1304
chunk(SessionId, done, _TableFun) ->
1305
deliver(SessionId,[stop_table(),stop_html_page()]);
1306
chunk(SessionId, Items, TableFun) ->
1307
deliver(SessionId, [lists:map(TableFun, Items),
1308
stop_table(), %! Will produce an empty table at the end
1309
start_visible_table()]). % of the page :(
1311
%%%-----------------------------------------------------------------
1312
%%% Deliver part of a page to inets
1313
%%% The first part, which includes the HTTP header, must always be
1314
%%% delivered as a string (i.e. no binaries). The rest of the page is
1315
%%% better delivered as binaries in order to avoid data copying.
1316
deliver_first(SessionId,String) ->
1317
mod_esi:deliver(SessionId,String).
1318
deliver(SessionId,IoList) ->
1319
mod_esi:deliver(SessionId,[list_to_binary(IoList)]).
1322
%%%-----------------------------------------------------------------
1323
%%% Page specific stuff for chunk pages
1324
procs_summary_table_head(Sorted,SharedHeap) ->
1331
[procs_summary_table_head("pid","Pid",Sorted),
1332
procs_summary_table_head("name_func","Name/Spawned as",Sorted),
1333
procs_summary_table_head("state","State",Sorted),
1334
procs_summary_table_head("reds","Reductions",Sorted),
1335
procs_summary_table_head("mem",MemHeading,Sorted),
1336
procs_summary_table_head("msg_q_len","MsgQ Length",Sorted)].
1338
procs_summary_table_head(_,Text,no_sort) ->
1340
procs_summary_table_head(Sorted,Text,Sorted) ->
1341
%% Mark the sorted column (bigger and italic)
1342
font("SIZE=\"+1\"",em(href("./sort_procs?sort="++Sorted,Text)));
1343
procs_summary_table_head(SortOn,Text,_Sorted) ->
1344
href("./sort_procs?sort="++SortOn,Text).
1346
procs_summary_table(Proc) ->
1347
#proc{pid=Pid,name=Name,state=State,
1348
reds=Reds,stack_heap=Mem0,msg_q_len=MsgQLen}=Proc,
1351
_ -> integer_to_list(Mem0)
1354
[td(href(["./proc_details?pid=",Pid],Pid)),
1357
td("ALIGN=right",integer_to_list(Reds)),
1358
td("ALIGN=right",Mem),
1359
td("ALIGN=right",integer_to_list(MsgQLen))]).
1361
port_table_head() ->
1362
["Id","Slot","Connected","Links","Name","Monitors","Controls"].
1364
ports_table(Port) ->
1365
#port{id=Id,slot=Slot,connected=Connected,links=Links,name=Name,
1366
monitors=Monitors,controls=Controls}=Port,
1369
td("ALIGN=right",Slot),
1370
td(href_proc_port(Connected)),
1371
td(href_proc_port(Links)),
1373
td(href_proc_port(Monitors)),
1376
ets_tables_table(EtsTable) ->
1377
#ets_table{pid=Pid,slot=Slot,id=Id,name=Name,type=Type,
1378
buckets=Buckets,size=Size,memory=Memory} = EtsTable,
1380
[td(href_proc_port(Pid)),
1385
td("ALIGN=right",Buckets),
1386
td("ALIGN=right",Size),
1387
td("ALIGN=right",Memory)]).
1389
timers_table(Timer) ->
1390
#timer{pid=Pid,msg=Msg,time=Time}=Timer,
1392
[td(href_proc_port(Pid)),
1394
td("ALIGN=right",Time)]).
1396
loaded_mods_table(#loaded_mod{mod=Mod,current_size=CS,old_size=OS}) ->
1397
tr([td(href(["loaded_mod_details?mod=",Mod],Mod)),
1398
td("ALIGN=right",CS),
1399
td("ALIGN=right",OS)]).
1402
#fu{module=Module,uniq=Uniq,index=Index,address=Address,
1403
native_address=NativeAddress,refc=Refc}=Fu,
1406
td("ALIGN=right",Uniq),
1407
td("ALIGN=right",Index),
1410
td("ALIGN=right",Refc)]).