Ersatz/Erweiterung PB Befehl "debug"

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
dussel
Beiträge: 49
Registriert: 15.09.2004 12:52
Wohnort: Bei Frankfurt/Main

Ersatz/Erweiterung PB Befehl "debug"

Beitrag von dussel »

Um Programmabläufe und Interoperabilität zwischen Code (wie Threads/Prozeduren usw.) zu prüfen, verwende ich gerne und häufig den PB Befehl "Debug". Ich wünschte mir jedoch mehr Funktionalität und habe mir über meine Anforderungen Gedanken gemacht. Die wären:

Anforderungen:

(1) Angabe eines Debuglevels

Als Verursacher meines Code benötige ich mehr Informationen zum internen Status meiner Software als ein Anwender. Je nach persönlicher Fähigkeit könnte ein betatester wiederum mehr Informationen vertragen bzw. als ein gewöhnlicher Anwender. Daher sehe ich die Notwendigkeit von Debuglevel. Mir erschien die folgende Einteilung geeignet:

- "Debug" für echte programmiertechnische Debugmeldungen (z.B. "tmp.l = 4711")
- "Verbose" für Informationen zum internem Programmablauf (z.B. "Procedure xyz called", "line 02 parsed")
- "Info" für Informationen zum Programmablauf (z.B. "Open config file xyz.cfg")
- "Warn" für Warnungen (z.B. "File open xyz.cfg failed")

(2) Welche Debuglevel sollen in das Executable übernommen werden

Eigentlich möchte ich nicht, das jeder nicht benötigte Debugaufruf im executable landet. Einerseits um meinen Code zu schützen, andererseits um das Laufzeitverhalten nicht zu beinträchtigen. Eine Konstante soll bestimmen, ob die Debugunterstützung grundsätzlich aktiviert wird und je Debuglevel eine einzelne Konstante. Niiieee wieder auskommentieren von Debug Anweisungen :-)

(3) Ausgabe von Datum und Uhrzeit

(4) Unterstützung einer Angabe in welcher Sektion/Prozedur/Codeteil der Aufruf stattfand, um diesen beim auswerten zuordnen zu können

(5) Unterstützung einer Angabe in welchem Thread dieser Sektion/Prozedur/Codeteil aufgerufen wurde, um diese beim auswerten zuordnen zu können

(6) Threadsafe aktivierbar.

Über eine Compilerdirektive soll der Code Threadsafe werden


Umsetzung:

Siehe folgenden Code :-)

Was fehlt:

Eine grafische Darstellung der gespeicherten Ereignisse mit Filter usw. Da jeder in seiner Anwendung individuelle Anforderungen an Art und Umfang haben wird, habe ich vorerst darauf verzichtet.


Code mod_debug:

Code: Alles auswählen

;
;
;   mod_debug
;
;

EnableExplicit

#mod_debug_enable_general         = #True       ; Would you like to enable mod_debug?
#mod_debug_enable_threadsafe      = #True       ; Should mod_debug work within threads?

#mod_debug_enable_level_debug     = #True       ; For Developer
#mod_debug_enable_level_verbose   = #True       ; For User/Developer: Verbose Messages
#mod_debug_enable_level_info      = #True       ; For User: INFO
#mod_debug_enable_level_warning   = #True       ; For User: WARNINGS

#mod_debug_display_on_event       = #True       ; Should any enabled event 

CompilerIf #mod_debug_enable_general = #True
 
#mod_debug_level_debug            = 1
#mod_debug_level_verbose          = 2
#mod_debug_level_info             = 4
#mod_debug_level_warning          = 8
   
  
  Structure event_structure
    event_level.l
    event_timestamp.l
    event_procedure.s
    event_thread_id.l
    event_message.s
  EndStructure
  
  NewList mod_debug_events.event_structure()
  
  CompilerIf #mod_debug_enable_threadsafe = #True
    Define mod_debug_events_mutex.l
    mod_debug_events_mutex = CreateMutex()
  CompilerEndIf
 
  Procedure.s i_mod_debug_generate_line(p_level.l, p_timestamp.l, p_procedure.s, p_message.s, p_thread_id.l=0)
  
    Define i_line.s
   
    i_line = FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss", p_timestamp)
    Select p_level
      Case #mod_debug_level_debug
        i_line.s + " [DEBG] "
      Case #mod_debug_level_verbose
        i_line.s + " [VERB] "
      Case #mod_debug_level_info
        i_line.s + " [INFO] "
      Case #mod_debug_level_warning
        i_line.s + " [WARN] "
    EndSelect
    
    i_line + p_procedure
    If p_thread_id
      i_line + "("+Str(p_thread_id)+")"
    EndIf
    i_line + ": " + p_message
    
    ProcedureReturn i_line
    
  EndProcedure
  
 
  Procedure i_mod_debug_add_event(p_level.l, p_procedure.s, p_message.s, p_thread_id.l=0)
    ;
    ;
    ;
    Shared mod_debug_events.event_structure()
    
    CompilerIf #mod_debug_enable_threadsafe = #True
      Shared mod_debug_events_mutex
      LockMutex(mod_debug_events_mutex)
    CompilerEndIf
    
    AddElement(mod_debug_events())
      mod_debug_events()\event_level      = p_level
      mod_debug_events()\event_timestamp  = Date()
      mod_debug_events()\event_procedure  = p_procedure
      mod_debug_events()\event_message    = p_message
      mod_debug_events()\event_thread_id  = p_thread_id
      
    CompilerIf #mod_debug_enable_threadsafe = #True
      UnlockMutex(mod_debug_events_mutex)
    CompilerEndIf
    
    CompilerIf #mod_debug_display_on_event=#True
      Debug i_mod_debug_generate_line(p_level, Date(), p_procedure, p_message, p_thread_id)
    CompilerEndIf
    
  EndProcedure    
  
  Procedure i_mod_debug_display_events(p_loglevel.l)
    ;
    ;
    ;

    Shared mod_debug_events.event_structure()
    Define i_loglevel.l
    Define i_line.s
    
    CompilerIf #mod_debug_enable_threadsafe = #True
      Shared mod_debug_events_mutex
      LockMutex(mod_debug_events_mutex)
    CompilerEndIf
    
      ForEach mod_debug_events()
        i_loglevel = mod_debug_events()\event_level
        If i_loglevel & p_loglevel 
          i_line = i_mod_debug_generate_line(mod_debug_events()\event_level, mod_debug_events()\event_timestamp, mod_debug_events()\event_procedure, mod_debug_events()\event_message, mod_debug_events()\event_thread_id)
          Debug i_line
        EndIf
      Next
      
    CompilerIf #mod_debug_enable_threadsafe = #True
      UnlockMutex(mod_debug_events_mutex)
    CompilerEndIf
  
  
  EndProcedure
  
  
CompilerEndIf  



Macro mod_debug_add_debug(p_procedure,p_message,p_thread_id=0)
  ; 
  ;   Wrapper for i_mod_debug_add_event

  CompilerIf #mod_debug_enable_general = #True  
    CompilerIf #mod_debug_enable_level_debug = #True
      i_mod_debug_add_event(#mod_debug_level_debug, p_procedure, p_message, p_thread_id)
    CompilerEndIf  
  CompilerEndIf  
  
EndMacro

Macro mod_debug_add_verbose(p_procedure, p_message, p_thread_id=0)
  ; 
  ;   Wrapper for i_mod_debug_add_event

  CompilerIf #mod_debug_enable_general = #True  
    CompilerIf #mod_debug_enable_level_verbose = #True
      i_mod_debug_add_event(#mod_debug_level_verbose, p_procedure, p_message, p_thread_id)
    CompilerEndIf  
  CompilerEndIf  
  
EndMacro

Macro mod_debug_add_info(p_procedure, p_message, p_thread_id=0)
  ; 
  ;   Wrapper for i_mod_debug_add_event

  CompilerIf #mod_debug_enable_general = #True  
    CompilerIf #mod_debug_enable_level_info = #True
      i_mod_debug_add_event(#mod_debug_level_info, p_procedure, p_message, p_thread_id)
    CompilerEndIf  
  CompilerEndIf  
  
EndMacro

Macro mod_debug_add_warning(p_procedure, p_message, p_thread_id=0)
  ; 
  ;   Wrapper for i_mod_debug_add_event

  CompilerIf #mod_debug_enable_general = #True  
    CompilerIf #mod_debug_enable_level_warning = #True
      i_mod_debug_add_event(#mod_debug_level_warning, p_procedure, p_message, p_thread_id)
    CompilerEndIf  
  CompilerEndIf  
  
EndMacro

Macro mod_debug_display_events(p_loglevel)

  CompilerIf #mod_debug_enable_general = #True  
    i_mod_debug_display_events(p_loglevel)
  CompilerEndIf
  
EndMacro  



Code Beispiel:

Code: Alles auswählen


XincludeFile("mod_debug.pb")

Procedure test()

  mod_debug_add_debug("test","debug message")
  mod_debug_add_verbose("test","verbose message")
  mod_debug_add_info("test","info message")
  mod_debug_add_warning("test","warning message")

EndProcedure

test()

  mod_debug_add_debug("test", "debug message")
  mod_debug_add_verbose("test", "verbose message")
  mod_debug_add_info("test", "info message")
  mod_debug_add_warning("test", "warning message")
  
mod_debug_display_events(#mod_debug_level_debug | #mod_debug_level_verbose | #mod_debug_level_info | #mod_debug_level_warning)


Bild|Bild
Bild|Bild|Bild
Benutzeravatar
ZeHa
Beiträge: 4760
Registriert: 15.09.2004 23:57
Wohnort: Friedrichshafen
Kontaktdaten:

Beitrag von ZeHa »

Jo, ein Logger quasi... sowas ist natürlich immer was feines :)
Vor allem wenn man dann noch eine gute GUI dafür baut, die man z.B. auch übers Netzwerk aufrufen kann. Zudem kann man solche Logging-Ausgaben evtl. auch seinen Kunden zumuten, sodaß diese sie dann per eMail an den Autor schicken.

Das Problem ist nur daß man momentan den Procedure-Namen und die Zeilennummer usw. immer von Hand mitgeben muß. Meiner Meinung nach sollte PureBasic da noch ein paar Compiler-Direktiven bekommen, z.B. CompilerGetProcedure, CompilerGetFile, CompilerGetLine, das würde die Sache noch abrunden :) sollten wir Fred mal vorschlagen...
Bild     Bild

ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Was ist den jetzt an der OnError Lib auszusetzen?
Macht die das nicht alles?

Zur Zeit zwar nur für Windows, aber das wird sich wohl auch in Zukunft ändern.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
ZeHa
Beiträge: 4760
Registriert: 15.09.2004 23:57
Wohnort: Friedrichshafen
Kontaktdaten:

Beitrag von ZeHa »

Die hier vorgestellte Lösung ist für den Einsatz NACH dem OnError gedacht ;) also wenn ein Error auftritt, dann kann er mit diesen Funktionen hier behandelt (sprich, ausgegeben) werden.

OnError ist ja nur dafür gedacht, bei einem Fehler irgendwo hinzuspringen (bzw. eine primitive Beschreibung zu erhalten). Schritt zwei ist dann eine gescheite Logging-Ausgabe.

Und hier geht's ja nicht nur um Errors, sondern auch um gewöhnliche Infos um Fehler überhaupt erst finden bzw. nachvollziehen zu können (also solche, bei denen OnError evtl. gar nicht erst meckert).
Bild     Bild

ZeHa hat bisher kein Danke erhalten.
Klicke hier, wenn Du wissen möchtest, woran ihm das vorbeigeht.
Antworten