Ankündigung

Einklappen
Keine Ankündigung bisher.

debug class programmierstil

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • debug class programmierstil

    Hallo zusammen,

    habe mich vorhin mal überwunden und mir endlich mal eine debug classe geschrieben.
    Ich stell die mal hier in den Raum, wäre super, wenn sich jemand die genauer anschauen könnte hinsichtlich Programmierstil.

    PHP-Code:
    <?php
    class Debug
    {
        private static 
    $_db;

    /**
     * @author Sebastian Sauer
     * @since 19.06.2009
     * @version 0.1
     * @todo - modify method log for Zend Framework
     *       - add forceLog method
     * 
     * environment constants :
     * APPLICATION_FRAMEWORK [optional] 
     * APPLICATION_ENV [optional]
     * APPLICATION_PATH [optional]
     * 
     *
     */

    /**
     * 
     * @private method checkParameters 
     * @param string $param
     * @return boolean
     */
        
    private static function checkParameters($param=''
        {
            if (empty(
    $param)) {
                return 
    false;
            }
            if (
    $_SERVER['HTTP_HOST']=='pages') {
                if (!
    defined('APPLICATION_ENV')) {
                    
    define('APPLICATION_ENV''development');
                }
            }
            if (!
    defined('APPLICATION_ENV')) {
                return 
    false;
            }
            if (!
    defined('APPLICATION_PATH')) {
                if (
    is_readable(__DIR__."/MySQL.class.php")) {
                    
    define('APPLICATION_PATH'__DIR__);                
                }
                else if (
    is_readable(__DIR__."/application/MySQL.class.php")) {
                    
    define('APPLICATION_PATH'__DIR__);                
                }
            }
            return 
    true;
        }

    /**
     * @private method getModel 
     * @return 
     */

        
    private static function getModel()
        {
            require_once(
    APPLICATION_PATH.'MySQL.class.php');
            require_once(
    APPLICATION_PATH.'dbfunctions.class.php');
            
    MySQL::getInstance();
            
    $resource MySQL::getResource();
            
    self::$_db = new dbfunctions($resource);
            return;
        
    // end function
        
    }
    /**
     * 
     * @return string the one to be dumped
     * @param string $var
     */
        
    private static function returnFormattedString($var)
        {
            
    $returnVal "<pre>";
            
    $returnVal .= var_dump($var);
            
    $returnVal .= "</pre>";
            return 
    $returnVal;
        
    // end function
        
    }

    /**
     * * 
     * @static method dump
     * @param object $var string or object to be dumped out formatted
     * @access public
     * @return string
     */
        
    public static function dump($var)
        {
            
    $init self::checkParameters($var);
            if (!
    $init) return;
            if (
    defined('APPLICATION_FRAMEWORK'
                        && 
    APPLICATION_FRAMEWORK == 'Zend') {
                return 
    Zend_Debug::dump($string);
            }
            return 
    self::returnFormattedString($var);            
        
    // end function
        
    }

        
    /**
         * @static method logData
         * @return boolean
         * @param string $val[optional] string to log
         */
       
        
    public static function logData($val '')
        {
            
    $init self::checkParameters($val);
            if (!
    $init) return;
            if (
    defined('APPLICATION_FRAMEWORK'
                        && 
    APPLICATION_FRAMEWORK == 'Zend') {
                return;
            }
            try {
                
    self::getModel();
                
    $logdata serialize($data);
                
    $sql "INSERT INTO 
                            logging
                        SET 
                            logtext = '"
    .self::$_db->escape($logdata)."';";
                
    $result self::$_db->query($sql);
            }
            catch (
    Exception $e) {
                if (
    defined(APPLICATION_ENV) && APPLICATION_ENV == 'development') {
                    echo 
    "<h2>logging fehlgeschlagen</h2>";
                }
                return 
    false;
            }
            
    self::$_db='';
            return 
    true;
        
    // end function
        
    }

    /**
     * 
     * @return mixed | array OR bool false
     * @param object $limit[optional]
     */
        
    public static function retrieveLog($limit='10')
        {
            
    self::getModel();
            try {
                
    $sql "SELECT 
                            logtext
                        FROM
                            logging
                        ORDER BY id DESC
                        LIMIT 
                            '"
    .self::$_db->escape($limit).";";
                
    $result self::$_db->Select($sql);
                
    $rows self::$_db->returnResult();
                foreach (
    $rows as $key => &$var) {
                    
    $var unserialize($var);
                    
    $var returnFormattedString($var);
                }
            }
            catch (
    Exception $e) {
                if (
    defined(APPLICATION_ENV) && APPLICATION_ENV == 'development') {
                    echo 
    "<h2>logging fehlgeschlagen</h2>";
                }
                return 
    false;
            }
            return 
    $rows;
        
    // end function    
        
    }
    }
    Über feedback/Kritik/Anregungen würd ich mich freuen


    Basti
    I like cooking my family and my pets.
    Use commas. Don't be a psycho.
    Blog - CoverflowJS


  • #2
    Hallo,
    du hast zuviele Abhängigkeiten in deiner Klasse, als dass sie für jemand anderen als dich hilfreich wäre. Und ob sie das für dich ist, kannst nur du beurteilen.

    Meine findest du hier, vielleicht findest du ja Ideen darin:
    Debug_class - PHP Classes

    PS: Zum Autor-Kommentar gehört immer noch eine Emailadresse.
    "Mein Name ist Lohse, ich kaufe hier ein."

    Kommentar


    • #3
      Hallo rudygotya,

      eine Debug-Klasse zu schreiben macht aus meiner Sicht keinen Sinn, denn diese wird niemals den Anforderungen an Debugging gerecht, die du heutzutage benötigts. Wenn du sinnvolle Mittel für die Entwicklung und den Betrieb bereitstellen möchtest, so solltest du

      • z.B. Netbeans + xdebug für das echte Debugging nutzen und
      • ein Benchmark-Tool in deine Applikation integrierst, das dir die relevanten Stellen bewertet.
      So hast du sowohl während der Entwicklung als auch im Betrieb geeignete Mittel. Zum Thema Benchmarking kannst du dir ja mal Benchmark :: Adventure PHP Framework (APF) ansehen.

      Viele Grüße,
      Dr.E.
      Viele Grüße,
      Dr.E.

      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      1. Think about software design before you start to write code!
      2. Discuss and review it together with experts!
      3. Choose good tools (-> Adventure PHP Framework (APF))!
      4. Write clean and reusable software only!
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

      Kommentar


      • #4
        Hallo,


        schon mal danke für das feedback Habe diesbezüglich anscheinend einige Lücken

        @ Chriz:
        - deine log methode find ich sehr genial, func_num_args und func_get_arg kannte ich noch nicht!
        - debug_backtrace kannte ich auch noch nicht, memory usage hab ich bisher direkt in linux mit top oder mit xdebug überwacht

        Mir ist leider nicht ganz klar, wieso du output buffering benutzt?
        Mit error_log zu arbeiten schaut sehr elegant aus. Benutzt du die Klasse auch mit irgendwelchen Frameworks ohne Probleme? Das output buffering schreckt mich irgendwie ab.

        Zu den phpdoc kommentaren: Da habe ich leider ehrlich gesagt ein schlechtes Halbwissen mit ekelhaftem Gefühl in der Bauchgegend. Danke für den Hinweis, falls mehr falsch ist bzw. ich mehr Standards verletze, nur raus damit.

        Zur Wiederverwendbarkeit: Imho richte ich für alle meine pages einen logging table ein (wenn nicht schon vorhanden), ein Interface oder eine parent abstract class wäre vielleicht dennoch sinnvoll. (Falls man dann doch nicht nur mysql verwendet, etc.). Darf ich Teile deiner Klasse abwandeln?

        @ Dr.E. : Ich hatte mir schon ewig vorgenommen, das APF genauer anzusehen, der output des benchmarks sieht wirklich sehr gut aus.
        Xdebug + div. eclipse derivate (hauptsächlich aptana) benutze ich schon länger- netbeans habe ich mir erst vor 2 Tagen angesehen (und das dann natürlich noch nicht so genau). Die rendertime habe ich auch berechnen lassen, jedoch nie so modular. Was mich wirklich interessiert, wie du an die ganzen Objekte und Module kommst?
        Muss ich die alle manuell zuweisen ?Oder doch automatisch, wenn beim Scriptstart das Singletion gestartet wird (irgendwie unvorstellbar)?

        In der Produktion lasse ich mir atm alle queries loggen, die länger als 10 Sekunden dauern. Und das ist mir zu wenig Info, da will und muss ich an der Ablaufverfolgung arbeiten.
        Und was mich dabei wirklich brennend interessiert:
        Entfernt ihr alle Debug- Ausgaben für das Produktiv- System oder laßt ihr die im quelltext stehen und arbeitet dann mit der Unterscheidung Produktions-/Entwicklungsumgebung?
        Im 2. Falle würden mich Erfahrungswerte interessieren, inwieweit die Latenz der Seite durch Debugging/Logging unnütz leidet. Der Unterschied sollte doch marginal sein oder irre ich mich da?

        ______________
        edit: hab mir das apf mal runtergeladen, ich probiers bei Gelegenheit das benchmarking selbst aus
        I like cooking my family and my pets.
        Use commas. Don't be a psycho.
        Blog - CoverflowJS

        Kommentar


        • #5
          Zitat von rudygotya Beitrag anzeigen
          @ Chriz:
          - deine log methode find ich sehr genial, func_num_args und func_get_arg kannte ich noch nicht!
          Ehrlich gesagt benutze ich die am seltensten. Viel wichtiger finde ich mal eben reinzuschauen was in einer Variable steht und weil ich schnell mal zur Kaffeemaschine renne, find ichs gut, dass dann dort auch gleich noch steht, wo die Funktion aufgerufen wurde. Zu oft schon hab ich var_dump() Ausgaben gefunden, die sich nur mies lokalisieren liessen (MVC, Layout, Template, Plugin, ActionHelper, find da mal die richtige Stelle).

          Zitat von rudygotya Beitrag anzeigen
          debug_backtrace kannte ich auch noch nicht, memory usage hab ich bisher direkt in linux mit top oder mit xdebug überwacht
          Letztlich ist das nur ein Gimick

          Zitat von rudygotya Beitrag anzeigen
          Mir ist leider nicht ganz klar, wieso du output buffering benutzt?
          Mit error_log zu arbeiten schaut sehr elegant aus. Benutzt du die Klasse auch mit irgendwelchen Frameworks ohne Probleme? Das output buffering schreckt mich irgendwie ab.
          Ich benutze sie mit dem Zend Framework und sie macht keine Probleme. In einer anderen Variante schicke ich noch einen Content-Type: text/plain und einen HTTP-500 Fehler mit, so dass ich im Firebug gleich den rot-gefärbten AJAX-Request sehe und im Zweifel fälschlich im Produktivsystem verwendete Debug-Ausgabe im Error-Log finden kann. Aber das sind mehr oder weniger nützliche Features, jeder hat da seinen eigenen Geschmack.
          Da Outputbuffering geschachtelt werden kann, macht es überhaupt keine Probleme, var_dump() ist einfach besser als print_r(), deshalb muss ich puffern.

          Zitat von rudygotya Beitrag anzeigen
          Zu den phpdoc kommentaren: Da habe ich leider ehrlich gesagt ein schlechtes Halbwissen mit ekelhaftem Gefühl in der Bauchgegend. Danke für den Hinweis, falls mehr falsch ist bzw. ich mehr Standards verletze, nur raus damit.
          Ist nur so eine Sache, wenn man fremde Klassen benutzt gehört ne Kontaktmöglichkeit dazu, ein Name ist einfach nichts-sagend. Benutzt du Eclipse PDT? Dort hast du Doc-Comment Autosuggestion.

          Zitat von rudygotya Beitrag anzeigen
          Zur Wiederverwendbarkeit: Imho richte ich für alle meine pages einen logging table ein (wenn nicht schon vorhanden), ein Interface oder eine parent abstract class wäre vielleicht dennoch sinnvoll. (Falls man dann doch nicht nur mysql verwendet, etc.). Darf ich Teile deiner Klasse abwandeln?
          Du darfst rauskopieren was du möchtest. Ich würde dein Logging trotzdem in eine Datei schreiben. Als eine der häufigsten Fehlerquellen würde ich die Datenbank einschätzen, und da ist es einfach keine gute Idee, das Logging dort unterzubringen.
          "Mein Name ist Lohse, ich kaufe hier ein."

          Kommentar


          • #6
            Hi,

            Was mich wirklich interessiert, wie du an die ganzen Objekte und Module kommst?
            Muss ich die alle manuell zuweisen ?Oder doch automatisch, wenn beim Scriptstart das Singletion gestartet wird (irgendwie unvorstellbar)?
            Die Methode des Benchmarks basiert darauf, dass der Page-Controller implizit für den Benutzer bereits sehr viele Messpunkte aufnimmt, auf die du als Entwickler nicht achten musst. Man könnte also fast(!) von Aspektorientierung sprechen. Du siehst quasi sowohl den Aufbau des Objektbaums bis zum ersten ::transform() als auch das eigentliche Rendering genau so wie es hirarchisch auch passiert. Sprich ist die Schachtelung noch tiefer, wird das auch in der Ausgabe der Benchmark-Punkte berücksichtigt.
            Dabei nutze ich die Klasse benchmarkTimer als Singleton und starte/stoppe verschiedene Messpunkte wann immer ich es möchte. Den Bencharker rufe ich dabei so auf:

            PHP-Code:
            $bench = &Singleton::getInstance('benchmarkTimer');
            $bench->start('Messpunkt A');
            ...
            $bench->stop('Messpunkt A'); 
            Ist am Ende der Seite (üblicherweise der index.php, wenn mit Bootstrapping gearbeitet wird) eine Ausgabe der Form

            PHP-Code:
            $bench = &Singleton::getInstance('benchmarkTimer');
            echo 
            $bench->createReport(); 
            enthalten, wird der Report wir du ihn gesehen hast angezeigt. Die Einbindung des Benchmarkers erfolgt dabei für dich automatisch vom Page-Controller, der diesen initialisiert und später Messpunkte deiner Komponenten selbständig aufnimmt. Hört sich nach Magic an, ist es aber an sich garnicht. Die Magie ergibt sich eigentlich durch die Funktion des Page-Controllers, der aus deinen Templates einen Objekt-Baum aufbaut und den du im Benchmarker auch durch die Einrückungen sehen kannst.


            In der Produktion lasse ich mir atm alle queries loggen, die länger als 10 Sekunden dauern. Und das ist mir zu wenig Info, da will und muss ich an der Ablaufverfolgung arbeiten.
            Dann solltest du schnellstens eine sinnvolle Benchmark-Komponente einbauen, die du auch im Betrieb nutzen kannst.

            Und was mich dabei wirklich brennend interessiert:
            Entfernt ihr alle Debug- Ausgaben für das Produktiv- System oder laßt ihr die im quelltext stehen und arbeitet dann mit der Unterscheidung Produktions-/Entwicklungsumgebung?
            Im 2. Falle würden mich Erfahrungswerte interessieren, inwieweit die Latenz der Seite durch Debugging/Logging unnütz leidet. Der Unterschied sollte doch marginal sein oder irre ich mich da?
            Das APF selbst besitzt keine Unterscheidung zwischen DEV und LIVE, d.h. der Benchmarker ist immer integriert. Debugging sollte definitiv nur auf DEV-Umgebungen laufen, daher ist es IMHO ratsam "externe" Debugger wie NetBeans + xdebug zu nutzen. Alles andere würde deine Performance erheblich in den Keller ziehen. Hier ist insbesondere xdebug nicht ganz unschuldig dran, denn zu Debug-Zwecken müssen sehr viele Informationen gesammelt werden.
            Was den Benchmark angeht, so kann ich nur sagen, dass das APF trotz "dauerhaft" integriertem Benchmarker trotzdem schneller als der Rest der Welt ist (siehe Yii vs. APF :: Adventure PHP Framework (APF)).

            Wenn du nun den Benchmarker bedingt einbaust, etwa so:

            PHP-Code:
            if(isset($_REQUEST['benchmarkreport']) && $_REQUEST['benchmarkreport'] == 'true'){
               
            $bench = &Singleton::getInstance('benchmarkTimer');
                echo 
            $bench->createReport();

            kannst du das auch im Live-Betrieb aktiviert lassen und im Fall von langsamen Antworttzeiten deiner Applikation nachschauen, woran es denn liegen kann. Setzt du dann z.B. in deiner Datenbank-Abstraktionsschicht entsprechende Punkte, siehst du sofort, wo es hakt.

            edit: hab mir das apf mal runtergeladen, ich probiers bei Gelegenheit das benchmarking selbst aus
            Klar. Wenn du dazu noch Fragen hast, immer her damit.

            Viele Grüße,
            Dr.E.
            Viele Grüße,
            Dr.E.

            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            1. Think about software design before you start to write code!
            2. Discuss and review it together with experts!
            3. Choose good tools (-> Adventure PHP Framework (APF))!
            4. Write clean and reusable software only!
            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            Kommentar


            • #7
              Hi,

              danke für eure Antworten, komme leider jetzt erst zum antworten.

              @ Chris: Aptana (auch Eclipse Derivat, aber das kennst du sicher). Meiner Meinung nach auch nur eine halbe Suggestion. PDT erst vor 2 Wochen runtergeladen, aber noch nicht viel ausprobiert.

              Bisher habe ich zum loggen immer erst versucht, in die DB zu schreiben, danach erst als textdatei.
              Allerdings habe ich das über ein exception Objekt gemacht, der ich nur einen string übergeben mußte und das ich im Bedarfsfall auch nicht geworfen habe. Noch stukturell zu unsauber mit zu wenig info.

              @ Dr. E. Soweit ich das richtig sehe, müßte ich für das APF benchmarking jedes Backend ins APF integrieren... Oder besteht da eine chance, dein Modul auch getrennt laufen zu lassen???
              Wär genial!!

              Alternativ:
              Durch den quellcode und deine Beispiele inspiriert habe ich mir überlegt, eine 3. Umgebung (development/production/benchmark) einzubauen. Zu benchmark- Zwecken über die autoload methode jedes Objekt auffangen (über Konstanten regeln) , dann hätte ich am Ende den gewünschten benchmark output.

              Gruß


              Basti
              I like cooking my family and my pets.
              Use commas. Don't be a psycho.
              Blog - CoverflowJS

              Kommentar


              • #8
                Hallo,

                @ Dr. E. Soweit ich das richtig sehe, müßte ich für das APF benchmarking jedes Backend ins APF integrieren... Oder besteht da eine chance, dein Modul auch getrennt laufen zu lassen???
                Wär genial!!
                Da i.d.R. jedes Backend auch ein Frontend (Präsentation) hat ist das kein Problem, denn die Frontend-Zeiten werden ja automatisch gemessen. Sprich für das Laden und Ausgeben einer beliebigen Liste siehst du ja schon die effektive Gesamtzeit.

                Wenn du nicht mit dem APF direkt arbeiten möchtest, musst du dir die Klassen benchmarkTimer und Singleton aus dem Release-Package ziehen und diese in deine Applikation integrieren. Vorsicht: die import() statements müssen durch include()/require() ersetzt werden. Alleine genutzt, bringen dir die beiden Klassen jedoch nicht den beschriebenen Mehrwert, da du dann selbst Benchmark-Messpunkte setzen musst.

                Alternativ:
                Durch den quellcode und deine Beispiele inspiriert habe ich mir überlegt, eine 3. Umgebung (development/production/benchmark) einzubauen. Zu benchmark- Zwecken über die autoload methode jedes Objekt auffangen (über Konstanten regeln) , dann hätte ich am Ende den gewünschten benchmark output.
                Aber doch nur das Laden/Einbinden einer Komponente, nicht aber dessen spezifische Ausführungszeit... Und (solch grausam intransparente) Dinge wie AspectJ gibt es für PHP nicht.
                Viele Grüße,
                Dr.E.

                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                1. Think about software design before you start to write code!
                2. Discuss and review it together with experts!
                3. Choose good tools (-> Adventure PHP Framework (APF))!
                4. Write clean and reusable software only!
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                Kommentar

                Lädt...
                X