/lib/observer/src/etop_tr.erl

https://github.com/yuvrajm/otp · Erlang · 130 lines · 86 code · 21 blank · 23 comment · 0 complexity · 154389f0b0894648c9cc8329a48c2d96 MD5 · raw file

  1. %%
  2. %% %CopyrightBegin%
  3. %%
  4. %% Copyright Ericsson AB 2002-2009. All Rights Reserved.
  5. %%
  6. %% The contents of this file are subject to the Erlang Public License,
  7. %% Version 1.1, (the "License"); you may not use this file except in
  8. %% compliance with the License. You should have received a copy of the
  9. %% Erlang Public License along with this software. If not, it can be
  10. %% retrieved online at http://www.erlang.org/.
  11. %%
  12. %% Software distributed under the License is distributed on an "AS IS"
  13. %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  14. %% the License for the specific language governing rights and limitations
  15. %% under the License.
  16. %%
  17. %% %CopyrightEnd%
  18. %%
  19. -module(etop_tr).
  20. -author('siri@erix.ericsson.se').
  21. %%-compile(export_all).
  22. -export([setup_tracer/1,stop_tracer/1,reader/1]).
  23. -import(etop,[getopt/2]).
  24. -include("etop_defs.hrl").
  25. setup_tracer(Config) ->
  26. TraceNode = getopt(node,Config),
  27. RHost = rpc:call(TraceNode, net_adm, localhost, []),
  28. Store = ets:new(?MODULE, [set, public]),
  29. %% We can only trace one process anyway kill the old one.
  30. case erlang:whereis(dbg) of
  31. undefined ->
  32. case rpc:call(TraceNode, erlang, whereis, [dbg]) of
  33. undefined -> fine;
  34. Pid ->
  35. exit(Pid, kill)
  36. end;
  37. Pid ->
  38. exit(Pid,kill)
  39. end,
  40. dbg:tracer(TraceNode,port,dbg:trace_port(ip,{getopt(port,Config),5000})),
  41. dbg:p(all,[running,timestamp]),
  42. T = dbg:get_tracer(TraceNode),
  43. Config#opts{tracer=T,host=RHost,store=Store}.
  44. stop_tracer(_Config) ->
  45. dbg:p(all,clear),
  46. dbg:stop(),
  47. ok.
  48. reader(Config) ->
  49. Host = getopt(host, Config),
  50. Port = getopt(port, Config),
  51. {ok, Sock} = gen_tcp:connect(Host, Port, [{active, false}]),
  52. spawn_link(fun() -> reader_init(Sock,getopt(store,Config),nopid) end).
  53. %%%%%%%%%%%%%% Socket reader %%%%%%%%%%%%%%%%%%%%%%%%%%%
  54. reader_init(Sock, Store, Last) ->
  55. process_flag(priority, high),
  56. reader(Sock, Store, Last).
  57. reader(Sock, Store, Last) ->
  58. Data = get_data(Sock),
  59. New = handle_data(Last, Data, Store),
  60. reader(Sock, Store, New).
  61. handle_data(_, {_, Pid, in, _, Time}, _) ->
  62. {Pid,Time};
  63. handle_data({Pid,Time1}, {_, Pid, out, _, Time2}, Store) ->
  64. Elapsed = elapsed(Time1, Time2),
  65. case ets:member(Store,Pid) of
  66. true -> ets:update_counter(Store, Pid, Elapsed);
  67. false -> ets:insert(Store,{Pid,Elapsed})
  68. end,
  69. nopid;
  70. handle_data(_W, {drop, D}, _) -> %% Error case we are missing data here!
  71. io:format("Erlang top dropped data ~p~n", [D]),
  72. nopid;
  73. handle_data(nopid, {_, _, out, _, _}, _Store) ->
  74. %% ignore - there was probably just a 'drop'
  75. nopid;
  76. handle_data(_, G, _) ->
  77. io:format("Erlang top got garbage ~p~n", [G]),
  78. nopid.
  79. elapsed({Me1, S1, Mi1}, {Me2, S2, Mi2}) ->
  80. Me = (Me2 - Me1) * 1000000,
  81. S = (S2 - S1 + Me) * 1000000,
  82. Mi2 - Mi1 + S.
  83. %%%%%% Socket helpers %%%%
  84. get_data(Sock) ->
  85. [Op | BESiz] = my_ip_read(Sock, 5),
  86. Siz = get_be(BESiz),
  87. case Op of
  88. 0 ->
  89. B = list_to_binary(my_ip_read(Sock, Siz)),
  90. binary_to_term(B);
  91. 1 ->
  92. {drop, Siz};
  93. Else ->
  94. exit({'bad trace tag', Else})
  95. end.
  96. get_be([A,B,C,D]) ->
  97. A * 16777216 + B * 65536 + C * 256 + D.
  98. my_ip_read(Sock,N) ->
  99. case gen_tcp:recv(Sock, N) of
  100. {ok, Data} ->
  101. case length(Data) of
  102. N ->
  103. Data;
  104. X ->
  105. Data ++ my_ip_read(Sock, N - X)
  106. end;
  107. _Else ->
  108. exit(eof)
  109. end.