Verwenden von trace und dbg in Erlang

70

Ich versuche, erlang:trace/3das dbgModul zu verwenden, um das Verhalten eines Live-Produktionssystems zu verfolgen, ohne den Server herunterzufahren.

Die Dokumentation ist undurchsichtig (um es milde auszudrücken) und es scheint keine nützlichen Online-Tutorials zu geben.

Was ich verbrachte den ganzen Tag versucht zu tun war erfassen , was in einer bestimmten Funktion geschieht , indem Sie versuchen eine Spur zu bewerben Module:Functionverwenden dbg:cund dbg:paber ohne Erfolg überhaupt.

Hat jemand eine kurze Erklärung, wie Trace in einem lebenden Erlang-System verwendet wird?

Gordon Guthrie
quelle

Antworten:

8

Wenn Sie einen grafischen Tracer bevorzugen, versuchen Sie es einfach . Sie können die Funktionen auswählen, die Sie verfolgen möchten (derzeit für alle Prozesse), und sich mit der dbg-API befassen.

Es schützt jedoch nicht vor Überlastung und ist daher nicht für Produktionssysteme geeignet.

Geben Sie hier die Bildbeschreibung ein

Andy Till
quelle
97

Die grundlegenden Schritte zur Ablaufverfolgung für Funktionsaufrufe befinden sich auf einem nicht aktiven Knoten:

> dbg:start().   % start dbg
> dbg:tracer().  % start a simple tracer process
> dbg:tp(Module, Function, Arity, []).   % specify MFA you are interested in
> dbg:p(all, c).   % trace calls (c) of that MFA for all processes.

... trace here

> dbg:stop_clear().   % stop tracer and clear effect of tp and p calls.

Sie können mehrere Funktionen gleichzeitig verfolgen. Fügen Sie Funktionen hinzu, indem Sie tpfür jede Funktion aufrufen . Wenn Sie nach nicht exportierten Funktionen suchen möchten, müssen Sie aufrufen tpl. Um Funktionen zu entfernen, rufen Sie ctpoder ctplauf ähnliche Weise auf. Einige allgemeine TP-Aufrufe sind:

> dbg:tpl(Module, '_', []).  % all calls in Module
> dbg:tpl(Module, Function, '_', []).   % all calls to Module:Function with any arity.
> dbg:tpl(Module, Function, Arity, []). % all calls to Module:Function/Arity.
> dbg:tpl(M, F, A, [{'_', [], [{return_trace}]}]).   % same as before, but also show return value.

Das letzte Argument ist eine Übereinstimmungsspezifikation. Damit können Sie herumspielen dbg:fun2ms.

Sie können die Prozesse auswählen, die mit dem Aufruf von p () verfolgt werden sollen. Die Artikel sind unter erlang: trace beschrieben. Einige Anrufe sind:

> dbg:p(all, c).   % trace calls to selected functions by all functions
> dbg:p(new, c).   % trace calls by processes spawned from now on
> dbg:p(Pid, c).   % trace calls by given process
> dbg:p(Pid, [c, m]).  % trace calls and messages of a given process

Ich denke, Sie müssen nie direkt anrufen erlang:trace, da dbgso ziemlich alles für Sie erledigt ist.

Eine goldene Regel für einen Live-Knoten besteht darin, nur eine Menge von Trace-Ausgaben für die Shell zu generieren, mit denen Sie eingeben können dbg:stop_clear(). . :) :)

Ich benutze oft einen Tracer, der sich nach einer Reihe von Ereignissen automatisch stoppt. Zum Beispiel:

dbg:tracer(process, {fun (_,100) -> dbg:stop_clear();
                        (Msg, N) -> io:format("~p~n", [Msg]), N+1 end, 0
                    }).

Wenn Sie für das Debuggen auf entfernten Knoten (oder mehrere Knoten) suchen, suchen pan, eper, invisooder onviso.

Zed
quelle
2
Ich konnte bisher keine Spur bekommen, um etwas an die Shell zu senden :(
Gordon Guthrie
Sie sagen, das sind die grundlegenden Schritte auf einem nicht aktiven Knoten ... vermutlich, weil Sie auf einem aktiven Knoten nur mit der Shell in einen Bildlauf geraten (und verlieren) würden?
Gordon Guthrie
1
Die Ablaufverfolgung erfordert einige Ressourcen vom System. Wenn Sie nach häufigen Ereignissen suchen, können Sie Ihre Leistung gefährden. Im schlimmsten Fall verlieren Sie den Kontakt und es geht -Boom-.
Zed
1
Auf einem Live-System würde ich die Funktionsaufrufe sehr genau beschreiben, einschließlich einiger Übereinstimmungen mit Argumenten. In den meisten Fällen können Sie die Ablaufverfolgung auch auf einen Prozess anstatt auf alle beschränken.
Zed
2
Sie können dbg tatsächlich nur für das Debuggen von Clustern / Remote-Knoten verwenden. dbg:n(Node)richtet sich Nodefür dieselbe Ablaufverfolgung ein wie der Knoten, auf dem Sie sich befinden.
Archaelus
24

Auf Live-Systemen verfolgen wir selten die Shell. Wenn das System gut konfiguriert ist, sammelt es bereits Ihre Erlang-Protokolle, die auf der Shell gedruckt wurden. Ich muss nicht betonen, warum dies in einem Live-Knoten entscheidend ist ...

Lassen Sie mich näher auf die Rückverfolgung von Dateien eingehen:

Es ist möglich, eine Datei zu verfolgen, wodurch eine Binärausgabe erzeugt wird, die später konvertiert und analysiert werden kann. (zur weiteren Analyse oder automatisierten Steuerung usw.)

Ein Beispiel könnte sein:

  • Verfolgen Sie mehrere umschlossene Dateien (12 x 50 MB). Bitte überprüfen Sie immer den verfügbaren Speicherplatz, bevor Sie einen so großen Trace verwenden!

    dbg:tracer(port,dbg:trace_port(file,{"/log/trace",wrap,atom_to_list(node()),50000000,12})).
    

    dbg:p(all,[call,timestamp,return_to]).

    • Testen Sie immer auf einem Testknoten, bevor Sie etwas in die Shell eines Live-Knotens eingeben!
    • Es wird am meisten empfohlen, einen Testknoten oder einen Replikatknoten zu haben, um die Skripte zuerst zu testen.

Lassen Sie uns einen Blick auf eine grundlegende Ablaufverfolgungsbefehlssequenz werfen:

<1> dbg:stop_clear().

  • Beginnen Sie immer damit, die Trace-Ports zu leeren und sicherzustellen, dass keine vorherige Ablaufverfolgung die aktuelle Ablaufverfolgung beeinträchtigt.

<2> dbg:tracer().

  • Starten Sie den Tracer-Prozess.

<3> dbg:p(all,[call, timestamp]).

  • In diesem Fall verfolgen wir alle Prozesse und Funktionsaufrufe.

<4> dbg:tp( ... ).

  • Wie in Zeds Antwort zu sehen.

<5> dbg:tpl( ... ).

  • Wie in Zeds Antwort zu sehen.

<42> dbg:stop_clear().

  • Auch hier soll sichergestellt werden, dass alle Spuren in die Ausgabe geschrieben wurden, und spätere Unannehmlichkeiten vermieden werden.

Sie können:

  • Fügen Sie Trigger hinzu, indem Sie einige fun () - s in der Shell definieren, um die Ablaufverfolgung zu einem bestimmten Zeitpunkt oder Ereignis zu stoppen. Rekursive fun () - s sind die besten, um dies zu erreichen, aber seien Sie sehr vorsichtig, wenn Sie diese anwenden.

  • Wenden Sie eine Vielzahl von Mustervergleichen an, um sicherzustellen, dass Sie nur den spezifischen Prozess mit dem spezifischen Funktionsaufruf mit dem spezifischen Argumenttyp verfolgen ...

Ich hatte vor einiger Zeit ein Problem, als wir den Inhalt einer ETS-Tabelle überprüfen mussten und beim Erscheinen eines bestimmten Eintrags die Ablaufverfolgung innerhalb von 2-3 Minuten stoppen mussten.

Ich schlage auch das Buch Erlang Programming von Francesco Cesarini vor. ( Erlang Programming @ Amazon )

cdlf
quelle
9

Das 'dbg'-Modul ist ziemlich einfach. Es gibt zwei Hacks, die ich sehr häufig für die Aufgaben verwende, die ich normalerweise benötige.

  1. Verwenden Sie den Erlang CLI / Shell-Erweiterungscode unter http://www.snookles.com/erlang/user_default.erl . Es wurde ursprünglich (soweit ich weiß) von Serge Aleynikov geschrieben und war ein nützliches Beispiel dafür, wie ich der Shell benutzerdefinierte Funktionen hinzufüge. Kompilieren Sie das Modul und bearbeiten Sie Ihre ~ / .erlang-Datei so, dass sie auf ihren Pfad verweist (siehe Kommentar oben in der Datei).

  2. Verwenden Sie das Dienstprogramm " redbug ", das in der EPER- Sammlung von Dienstprogrammen enthalten ist. Es ist sehr einfach, mit 'dbg' in wenigen Sekunden Millionen von Ablaufverfolgungsereignissen zu erstellen. Dies in einer Produktionsumgebung zu tun, kann katastrophal sein. Für die Entwicklung oder Produktion macht es Redbug nahezu unmöglich, ein laufendes System mit einer durch Spuren verursachten Überlastung zu töten.

Scott Lystig Fritchie
quelle