aboutsummaryrefslogblamecommitdiffstats
path: root/lib/et/doc/src/et_architecture.xml
blob: 44e262db968fe5daffb04359497c79859a72a450 (plain) (tree)
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554








































































































































































































































































































































































































































































































































































                                                                                              
<?xml version="1.0" encoding="latin1" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">

<chapter>
  <header>
    <copyright>
      <year>2002</year><year>2009</year>
      <holder>Ericsson AB. All Rights Reserved.</holder>
    </copyright>
    <legalnotice>
      The contents of this file are subject to the Erlang Public License,
      Version 1.1, (the "License"); you may not use this file except in
      compliance with the License. You should have received a copy of the
      Erlang Public License along with this software. If not, it can be
      retrieved online at http://www.erlang.org/.
    
      Software distributed under the License is distributed on an "AS IS"
      basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
      the License for the specific language governing rights and limitations
      under the License.
    
    </legalnotice>

    <title>Usage</title>
    <prepared>H&aring;kan Mattsson</prepared>
    <responsible>H&aring;kan Mattsson</responsible>
    <docno></docno>
    <approved>H&aring;kan Mattsson</approved>
    <checked></checked>
    <date></date>
    <rev>%VSN%</rev>
    <file>et_architecture.xml</file>
  </header>

  <section>
    <title>Overview</title>
    <p>The two major components of the Event Tracer (ET)
      tool is a graphical sequence chart viewer (<c>et_viewer</c>)
      and its backing storage (<c>et_collector</c>). One collector
      may be used as backing storage for several simultaneous
      viewers where each one may display a different view of
      the same trace data.</p>
    <p>The interface between the collector and its viewers
      is public in order to enable other types of viewers.
      However in the following text we will focus on usage
      of the <c>et_viewer</c>.</p>
    <p>The main start function is <c>et_viewer:start/1</c>.
      It will by default start both an <c>et_collector</c> and
      an <c>et_viewer</c>:</p>
    <p></p>
    <code type="none"><![CDATA[
         % erl -pa et/examples
         Erlang (BEAM) emulator version 2002.10.08 [source]

         Eshell V2002.10.08  (abort with ^G)
         1> {ok, Viewer} = et_viewer:start([]).
         {ok,<0.31.0>}
    ]]></code>
    <p>A viewer gets trace events from its collector
      by polling it regularly for more events to display.
      Trace events are for example reported to the collector with
      <c>et_collector:report_event/6</c>:</p>
    <code type="none"><![CDATA[
         2> Collector = et_viewer:get_collector_pid(Viewer).
         <0.30.0>
         3> et_collector:report_event(Collector, 60, my_shell, mnesia_tm, start_outer, 
                                      "Start outer transaction"),
         3> et_collector:report_event(Collector, 40, mnesia_tm, my_shell, new_tid, 
                                      "New transaction id is 4711"),
         3> et_collector:report_event(Collector, 20, my_shell, mnesia_locker, try_write_lock,
                                      "Acquire write lock for {my_tab, key}"),
         3> et_collector:report_event(Collector, 10, mnesia_locker, my_shell, granted, 
                                      "You got the write lock for {my_tab, key}"),
         3> et_collector:report_event(Collector, 60, my_shell, do_commit, 
                                      "Perform  transaction commit"),
         3> et_collector:report_event(Collector, 40, my_shell, mnesia_locker, release_tid, 
                                      "Release all locks for transaction 4711"),
         3> et_collector:report_event(Collector, 60, my_shell, mnesia_tm, delete_transaction, 
                                      "End of outer transaction"),
         3> et_collector:report_event(Collector, 20, my_shell, end_outer, 
                                      "Transaction returned {atomic, ok}").
         {ok,{table_handle,<0.30.0>,11,trace_ts,#Fun<et_collector.0.83904657>}}
         4>        
    ]]></code>
    <p>This is a simulation of the process events caused by a Mnesia
      transaction that writes a record in a local table:</p>
    <code type="none">
         mnesia:transaction(fun() -> mnesia:write({my_tab, key, val}) end).
    </code>
    <p>At this stage when we have a couple of events, it is time to
      show how it looks like in the graphical interface of
      <c>et_viewer</c>:</p>
    <p></p>
    <image file="sim_trans.gif">
      <icaption>A simulated Mnesia transaction which writes one record</icaption>
    </image>
    <p>In the sequence chart, the actors (which symbolically has performed the
      traced event) are shown as named vertical bars. The order of the
      actors may be altered by dragging (hold mouse button 1 pressed during
      the operation) the name tag of an actor and drop it elsewhere:</p>
    <image file="sim_trans_move_actor.gif">
      <icaption>Two actors has switched places</icaption>
    </image>
    <p>An event may be an action performed by one single actor (blue
      text label) or it may involve two actors and is then depicted as an
      arrow directed from one actor to another (red text label). Details of
      an event can be shown by clicking (press and release the mouse button 1)
      on the event label text or on the arrow:</p>
    <p></p>
    <image file="sim_trans_write_lock.gif">
      <icaption>Details of a write lock message</icaption>
    </image>
  </section>

  <section>
    <title>Filters and dictionary</title>
    <p>The Event Tracer (ET) uses named filters in various
      contexts. An Event Trace filter is an <c>Erlang fun</c>
      that takes some trace data as input and returns a possibly
      modified version of it:
      </p>
    <p></p>
    <code type="none">
         filter(TraceData) -> true | {true, NewEvent} | false

         TraceData = NewEvent | term()
         NewEvent  = record(event)
    </code>
    <p>The interface of the filter function is the same as the the
      filter functions for the good old <c>lists:zf/2</c>. If the filter
      returns <c>false</c> it means that the <c>TraceData</c> should be
      dropped. <c>{true, NewEvent}</c> means that the <c>TraceData</c>
      should be replaced with <c>NewEvent</c>. And <c>true</c> means that the
      <c>TraceData</c> data already is an event record and that it
      should be kept as it is.
      </p>
    <p>The first filter that the trace data is exposed for is
      the collector filter. When a trace event is reported with
      <c>et_collector:report/2</c> (or <c>et_collector:report_event/5,6</c>)
      the first thing that
      happens, is that a message is sent to the collector process
      to fetch a handle that contains some useful stuff, such as
      the collector filter fun and an ets table identifier.
      Then the collector filter fun is applied and if it returns
      <c>true</c> (or <c>{true, NewEvent}</c>), the event will
      be stored in an ets table. As an optimization, subsequent
      calls to <c>et_collector:report</c>-functions can use the handle
      directly instead of the collector pid.
      </p>
    <p>The collector filter (that is the filter named
      <c>collector</c>) is a little bit special, as its input
      may be any Erlang term and is not limited to take an event
      record as the other filter functions. 
      </p>
    <p>The collector manages a key/value based dictionary, where
      the filters are stored. Updates of the dictionary is
      propagated to all subscribing processes. When a viewer is
      started it is registered as a subscriber of dictionary updates.
      </p>
    <p>In a viewer there is only one filter that is active
      and all trace events that the viewer gets from the
      collector will pass thru that filter. By writing clever
      filters it is possible to customize how the events
      looks like in the viewer. The following filter replaces
      the actor names <c>mnesia_tm</c> and <c>mnesia_locker</c>
      and leaves everything else in the record as it was:
      </p>
    <p></p>
    <codeinclude file="../../examples/et_demo.erl" tag="%mgr_actors" type="erl"></codeinclude>
    <p>If we now add the filter to the running collector:
      </p>
    <p></p>
    <code type="none"><![CDATA[
        4> Fun = fun(E) -> et_demo:mgr_actors(E) end.
        #Fun<erl_eval.5.123085357>
        5> et_collector:dict_insert(Collector, {filter, mgr_actors}, Fun).
        ok
        6>
    ]]></code>
    <p>you will see that the <c>Filter</c> menu in all viewers have
      got a new entry called <c>mgr_actors</c>. Select it, and a new
      viewer window will pop up:</p>
    <p></p>
    <image file="sim_trans_mgr_actors.gif">
      <icaption>The same trace data in a different view</icaption>
    </image>
    <p>In order to see the nitty gritty details of an event
      you may click on the event in order to start a contents
      viewer for that event. In the contents viewer there is
      also a filter menu in order to enable inspection of the
      event from other views than the one selected in the viewer.
      A click on the <c>new_tid</c> event will cause a contents
      viewer window to pop up, showing the event in the 
      <c>mgr_actors</c> view:</p>
    <p></p>
    <image file="sim_trans_contents_viewer_mgr_actors.gif">
      <icaption>The trace event in the mgr_actors view</icaption>
    </image>
    <p>Select the <c>collector</c> entry in the <c>Filters</c>
      menu and a new contents viewer window will pop up
      showing the same trace event in the collectors view:</p>
    <p></p>
    <image file="sim_trans_contents_viewer_collector.gif">
      <icaption>The same trace event in the collectors view</icaption>
    </image>
  </section>

  <section>
    <title>Trace clients</title>
    <p>As you have seen it is possible to use the
      <c>et_collector:report</c>-functions explicitly. By using those functions
      you can write your own trace client that reads trace data from any
      source stored in any format and just feed the collector with it. You
      may replace the default collector filter with a filter that converts
      new exciting trace data formats to event-records or you may convert it
      to an event-record before you invoke <c>et_collector:report/2</c> and
      then rely on the default collector filter to handle the new
      format.</p>
    <p>There are also existing functions in the API that reads from
      various sources and calls <c>et_collector:report/2</c>:</p>
    <list type="bulleted">
      <item>
        <p>The trace events that are hosted by the collector may be 
          stored to file and later be loaded by selecting <c>save</c>
          and <c>load</c> entries in the viewers <c>File</c>-menu or
          via the <c>et_collector</c> API.</p>
      </item>
      <item>
        <p>It is also possible to perform live tracing of a running
          system by making use of the built-in trace support in
          the Erlang emulator. These Erlang traces can be directed
          to files or to ports. See the reference manual for
          <c>erlang:trace/4</c>, <c>erlang:trace_pattern/3</c>,
          <c>dbg</c> and <c>ttb</c> for more info.</p>
        <p>There are also corresponding trace client types that can
          read the Erlang trace data format from such files or ports.
          The <c>et_collector:start_trace_client/3</c> function makes
          use of these Erlang trace clients and redirects the trace
          data to the collector.</p>
        <p>The default collector filter converts the Erlang trace data
          format into event-records.If you want to perform this
          differently you can of course write your own collector
          filter from scratch. But it may probably save you some
          efforts if you first apply the default filter in 
          <c>et_selector:parse_event/2</c> before you apply your
          own conversions of its output.</p>
      </item>
    </list>
  </section>

  <section>
    <title>Global tracing and phone home</title>
    <p>Setting up an Erlang tracer on a set of nodes and connecting
      trace clients to the ports of these tracers is not intuitive. In order
      to make this it easier the Event Tracer as a notion of global
      tracing. When used, the <c>et_collector</c> process will monitor
      Erlang nodes and when one connects, an Erlang tracer will
      automatically be started on the other node. A corresponding trace
      client will also be started on the collector node in order to
      automatically forward the trace events to the collector. Set the
      boolean parameter <c>trace_global</c> to <c>true</c> for either the
      <c>et_collector</c> or <c>et_viewer</c> in order to activate the
      global tracing. There is no restriction on how many concurrent
      (anonymous) collectors you can have, but you can only have one global
      collector as its name is registered in <c>global</c>.</p>
    <p>In order to further simplify the tracing you can make use of the
      <c>et:report_event/4,5</c> (or its equivalents
      <c>et:phone_home/4,5</c> :-). These functions are intended to be
      invoked from other applications when there are interesting events,
      in your application that needs to be highlighted. The functions are 
      extremely light weight as they do nothing besides returning an atom.
      These functions are
      specifically designed to be traced for. As the caller explicitly
      provides the values for the event-record fields, the default collector
      filter is able to automatically provide a customized event-record
      without any user defined filter functions.</p>
    <p>In normal operation the <c>et:report_event/4,5</c> calls are
      almost for free. When tracing is needed you can either activate
      tracing on these functions explicitly. Or you can combine the usage of
      <c>trace_global</c> with the usage of <c>trace_pattern</c>. When set,
      the <c>trace_pattern</c> will automatically be activated on all
      connected nodes. </p>
    <p>One nice thing with the <c>trace_pattern</c> is that it provides
      a very simple way of minimizing the amount of generated trace data by
      allowing you to explicitly control the detail level of the tracing. As
      you may have seen the <c>et_viewer</c> have a slider called
      <c>"Detail Level"</c> that allows you to control the detail level of the
      trace events displayed in the viewer. On the other hand if you set a
      low detail level in the <c>trace_pattern</c>, lots of the trace data
      will never be generated and thus not sent over the socket to the trace
      client and stored in the collector.</p>
  </section>

  <section>
    <title>Viewer window</title>
    <p>Almost all functionality available in the <c>et_viewer</c> is
      also available via shortcuts. Which key that has the same
      effect as selecting a menu entry is shown enclosed in
      parentheses.  For example pressing the key <c>r</c> is
      equivalent to selecting the menu entry
      <c>Viewer->Refresh</c>.
      </p>
    <p>File menu:</p>
    <list type="bulleted">
      <item>
        <p>Close Collector and all Viewers - Close the collector
          and all viewers connected to that collector.</p>
      </item>
      <item>
        <p>Close other Viewers, but keep Collector - Keep this viewer
          and its collector, but close all other viewers connected
          to this collector.</p>
      </item>
      <item>
        <p>Close this Viewer, but keep Collector - Close this viewer,
          but all other viewers and the collector.</p>
      </item>
      <item>
        <p>Save Collector to file - Save all events stored in the
          collector to file.</p>
      </item>
      <item>
        <p>Load Collector from file - Load the collector with
          events from a file.</p>
      </item>
    </list>
    <p>Viewer menu:</p>
    <list type="bulleted">
      <item>
        <p>First - Scroll <c>this</c> viewer to the first collector
          event.</p>
      </item>
      <item>
        <p>Prev - Scroll <c>this</c> viewer one "page" backwards.
          Normally this means that the first event displayed in the
          viewer will be the last one and the previous <c>max_events</c>
          events will be read from the collector.</p>
      </item>
      <item>
        <p>Next - Scroll <c>this</c> viewer one "page" forward.
          Normally this means that the last event displayed in the
          viewer will be the first one and <c>max_events</c> more
          events will be read from the collector.</p>
      </item>
      <item>
        <p>Last -  Scroll <c>this</c> viewer to the last collector event.</p>
      </item>
      <item>
        <p>Refresh - Clear <c>this</c> viewer and re-read its events
          from the collector.</p>
      </item>
      <item>
        <p>Up 5 - Scroll 5 events backwards.</p>
      </item>
      <item>
        <p>Down 5 - Scroll 5 events forward.</p>
      </item>
      <item>
        <p>Abort search. Display all. - Switch the display mode to
          show all events regardless of any ongoing searches.
          Abort the searches.</p>
      </item>
    </list>
    <p>Collector menu:</p>
    <list type="bulleted">
      <item>
        <p>First - Scroll <c>all</c> viewers to the first collector
          event.</p>
      </item>
      <item>
        <p>Prev - Scroll <c>all</c> viewers one "page" backwards.
          Normally this means that the first event displayed in the
          viewer will be the last one and the previous <c>max_events</c>
          events will be read from the collector.</p>
      </item>
      <item>
        <p>Next - Scroll <c>all</c> viewers one "page" forward.
          Normally this means that the last event displayed in the
          viewer will be the first one and <c>max_events</c> more
          events will be read from the collector.</p>
      </item>
      <item>
        <p>Last -  Scroll <c>all</c> viewers to the last collector event.</p>
      </item>
      <item>
        <p>Refresh - Clear <c>all</c> viewers and re-read their
          events from the collector.</p>
      </item>
    </list>
    <p>Filters menu:</p>
    <list type="bulleted">
      <item>
        <p>ActiveFilter (=) - Start a new viewer window with the 
          same active filter and scale as the current one.</p>
      </item>
      <item>
        <p>ActiveFilter (+) - Start a new viewer window with 
          the same active filter but a larger scale than the
          current one.</p>
      </item>
      <item>
        <p>ActiveFilter (-) - Start a new viewer window with 
          the same active filter but a smaller scale than the
          current one.</p>
      </item>
      <item>
        <p>collector (0) - Start a new viewer with the collector
          filter as active filter.</p>
      </item>
      <item>
        <p>AnotherFilter (2) - If more filters are inserted into
          the dictionary, these will turn up here as entries
          in the <c>Filters</c> menu. The second filter will be
          number 2, the next one number 3 etc. The names are sorted.</p>
      </item>
    </list>
    <p>Slider and radio buttons:</p>
    <list type="bulleted">
      <item>
        <p>Freeze - When true, this means that the viewer
          will not read more events from the collector
          until set to false.</p>
      </item>
      <item>
        <p>Hide From=To - When true, this means that the viewer
          will hide all events where the from-actor equals
          to its to-actor.</p>
      </item>
      <item>
        <p>Hide Unknown - When true, this means that the viewer
          will hide all events where either of the from-actor or
          to-actor is <c>UNKNOWN</c>.</p>
      </item>
      <item>
        <p>Detail level - This slider controls the resolution
          of the viewer. Only events with a detail level <c>smaller</c>
          than the selected one (default=100=max) are displayed.</p>
      </item>
    </list>
    <p>Other features:</p>
    <list type="bulleted">
      <item>
        <p>Display details of an event - Click on the event name
          and a new window will pop up, displaying the contents
          of an event.</p>
      </item>
      <item>
        <p>Toggle actor search - Normally the viewer will be in a
          display mode where all events are shown. By clicking
          on an actor name the tool will switch display mode
          to only show events with selected actors.
          </p>
        <p>Click on an actor and only events with that actor
          will be displayed. Click on another actor to include
          that actor to the selected ones. Clicking on an already
          selected actor will remove it from the collections of
          selected actors. When the collection of selected actors
          becomes empty the normal mode where all actors are shown
          will be entered again.</p>
        <p>Abort actor search with the <c>a</c> key or with the
          <c>Viewer->Abort search</c> menu choice.
          </p>
      </item>
      <item>
        <p>Move actor - Drag and drop an actor by first clicking on 
          the actor name, keeping the button pressed while moving
          the cursor to a new location and release the button where
          the actor should be moved to.</p>
      </item>
    </list>
  </section>

  <section>
    <title>Configuration</title>
    <p>The event-records in the ets-table are ordered by their timestamp.
      Which timestamp that should be used is controlled via the
      <c>event_order</c> parameter. Default is <c>trace_ts</c> which means
      the time when the trace data was generated. <c>event_ts</c> means
      the time when the trace data was parsed (transformed into an
      event-record).</p>
  </section>

  <section>
    <title>Contents viewer window</title>
    <p>File menu:</p>
    <list type="bulleted">
      <item>
        <p>Close - Close this window.</p>
      </item>
      <item>
        <p>Save - Save the contents of this window to file.</p>
      </item>
    </list>
    <p>Filters menu:</p>
    <list type="bulleted">
      <item>
        <p>ActiveFilter - Start a new contents viewer window
          with the same active filter.</p>
      </item>
      <item>
        <p>AnotherFilter (2) - If more filters are inserted into
          the dictionary, these will turn up here as entries
          in the <c>Filters</c> menu. The second filter will be
          number 2, the next one number 3 etc. The names are sorted.</p>
      </item>
    </list>
    <p>Hide menu:</p>
    <list type="bulleted">
      <item>
        <p>Hide actor in viewer - Known actors are shown as a 
          named vertical bars in the viewer window. By hiding the
          actor, its vertical bar will be removed and the viewer
          will be refreshed.</p>
        <p>Hiding the actor is only useful if the <c>max_actors</c>
          threshold has been reached, as it then will imply that
          the "hidden" actor will be displayed as if it were <c>"UNKNOWN"</c>.
          If the  <c>max_actors</c> threshold not have been reached,
          the actor will re-appear as a vertical bar in the viewer.
          </p>
      </item>
      <item>
        <p>Show actor in viewer - This implies that the actor
          will be added as a known actor in the viewer with
          its own vertical bar.</p>
      </item>
    </list>
    <p>Search menu:</p>
    <list type="bulleted">
      <item>
        <p>Forward from this event - Set this event to be the first
          event in the viewer and change its display mode to be
          enter forward search mode. The actor of this event
          (from, to or both) will be added to the list of selected
          actors.
          </p>
      </item>
      <item>
        <p>Reverse from this event - Set this event to be the first
          event in the viewer and change its display mode to be
          enter reverse search mode. The actor of this event
          (from, to or both) will be added to the list of selected
          actors. Observe, that the events will be shown in reverse
          order.
          </p>
      </item>
      <item>
        <p>Abort search. Display all - Switch the display mode
          of the viewer to show all events regardless of any
          ongoing searches. Abort the searches.</p>
      </item>
    </list>
  </section>
</chapter>