Umstellung auf einen Logger mit Sensei

Veröffentlicht Nov 30, 2020
von Alan Richardson
FALLSTUDIE

Umstellung auf einen Logger mit Sensei

Veröffentlicht Nov 30, 2020
von Alan Richardson
Ressource anzeigen
Ressource anzeigen

Umstellung auf einen Logger mit Sensei

Dieser Beitrag beschreibt die Erstellung eines Rezepts für die Umstellung von System.out.println auf die Verwendung eines Java-Loggers.

Wenn ich Code hacke, anstatt TDD zu verwenden, und ich Fehler mache, habe ich die schlechte Angewohnheit, eine Zeile in System.out zu drucken, und ich wollte mir diese Angewohnheit abgewöhnen.

Beim Schreiben des untenstehenden Codes habe ich einen Haufen Fehler gemacht:

   private String getCountdownString() {
        String output = "";
        String prefix="";
        for(int countdown = 10; countdown > 0; countdown-- ){
            output = output + prefix + countdown;
            System.out.println(output);
            prefix=", ";
        }
        System.out.println(output);
        return output;
    }


Ursprünglich habe ich countdown++ geschrieben und die Schleife wurde nicht beendet.

Und ich habe Countdown > 1 verwendet, also nicht die gewünschte Ausgabe erhalten.

Am Ende habe ich meinen Code mit System.out.println überhäuft, um mir beim Debuggen zu helfen. Und die Erfahrung hat mich darin bestärkt, dass ich lernen muss, einen Logger als Standardansatz zu verwenden.

Forschung

Glücklicherweise habe ich mir die Dokumentation vonSensei durchgelesen und mich für die Anleitung "Erste Schritte" entschieden, die mir bei der Erstellung eines Rezepts zur Konvertierung von System.out.println hilft und mich zur Verwendung eines Loggers ermutigt:

  • java.util.logging.Logger

Erstellen eines Rezepts

Als erstes klicke ich auf println und dann auf alt+enter, um ein neues Rezept zu erstellen.

System ausdrucken Ein neues Rezept erstellen


Ich erstelle sie mit den folgenden Angaben:


Name: Logger: Logger anstelle von println verwenden
Beschreibung: Logger statt println verwenden - denken Sie daran, System.out.println nicht mehr zu verwenden
Ebene: Fehler


Und ich beginne mit einem passenden Methodenaufruf mit dem Namen println


suchen:
  Methodenaufruf:
    Name: "println"

Und die Vorschau zeigt mir alle Übereinstimmungen in meinem Code.


Rezepteinstellungen Methodcall Println


Ich kann sehen, dass alle Übereinstimmungen in meinem Code für System.out.println sind, aber ich vertraue nicht darauf, dass dies auf lange Sicht die einzige Übereinstimmung sein wird. Ich möchte eine qualifiziertere Anweisung abgleichen, die ich ändern möchte.

Ich erweitere den Matcher, um nach einem Methodenaufruf auf ein Feld zu suchen, das in der Klasse System.


suchen:
  Methodenaufruf:
    Name: "println"
    "ein":
      Feld:
        in:
          Klasse:
            Name: "System"
        Name: "aus"



Ich könnte, wenn ich wollte, den Namen System vollständig zu java.lang.System qualifizieren

Rezepteinstellungen Methodcall name system

Ändern des Codes zum Protokollieren


Als nächstes möchte ich den QuickFix erstellen.

Zuerst möchte ich die Codezeile ändern, die die Ausgabe protokolliert:


availableFixes:
- Name: "Logger verwenden"
  Aktionen:
  - umschreiben:
      to: "logger.log(Level.INFO, {{{ arguments.0 }}})"



Ich muss mir das Format der Schnurrbartvorlage nicht merken. Ich benutzte die Funktion "Variablen anzeigen" in der GUI, um mir das Argument anzeigen zu lassen und doppelklickte es an. Dann füllte die GUI die entsprechende passende Schnurrbartvorlage aus.



Wenn ich es ausprobiere, kann ich sehen, dass ich immer noch alt+enter drücken muss, um das Level-Enum zu importieren. Wenn ich jedoch meinen QuickFix so ändere, dass er ein voll qualifiziertes Element enthält, fügt Sensei den Import für mich hinzu, z. B.

  • Sie ersetzt System.out.println(output); durch

logger.log(Level.INFO, output);

  • Und fügen Sie einen Import für das Enum hinzu:

import java.util.logging.Level;

  • Wenn ich umschreibe in:
logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})

Das wird auch funktionieren, aber ich muss mir immer noch die Syntax merken, um den Logger überhaupt erst zu instanziieren.

Syntax zum Instanziieren des Loggers an erster Stelle


Ändern des Codes zum Hinzufügen des Logger-Feldes

Ich kann meinen QuickFix ändern, um das Feld auch für mich zu erstellen.

Ich werde den Logger zuerst codieren und dann zu meinem Rezept hinzufügen, damit ich ihn nie wieder codieren muss.

Logger logger2 = Logger.getLogger(SysOutTest.class.getName());


Ich neige dazu, den Beispielcode, den ich generiert sehen möchte, zuerst zu schreiben, weil ich dann die IntelliJ-Codevervollständigung und die Syntaxprüfung verwenden kann, um sicherzustellen, dass ich ihn richtig hinbekomme. Als Nebeneffekt wird er dann in der Codevorschau angezeigt, wenn ich das Rezept bearbeite, um die QuickFix-Zeilen hinzuzufügen, die diesen Code erzeugen.

Und wenn ich den Beispielcode schreibe, möchte ich einen anderen Feldnamen verwenden (hier verwende ich logger2), denn Sensei ist schlau genug, um kein doppeltes Feld hinzuzufügen, also muss ich es mit einem anderen Namen täuschen.

Ich ändere also das Rezept, um diesen Code zu erstellen, indem ich ein Feld mit dem Namen logger hinzufüge.

availableFixes:

- Name: "Logger verwenden"
  Aktionen:
  - umschreiben:
      to: "logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})"
  - addField:
      field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}}.class.getName())"
      Ziel: "parentClass"


Beachten Sie, dass ich SysOutTest in eine Mustache-Variable geändert habe, damit sie den Namen jeder Klasse aufnimmt, in der ich dieses Rezept verwende. Und wieder habe ich mir die Mustache-Syntax nicht gemerkt, ich habe die GUI Show Variables benutzt, um den Ersatz zu finden, den ich brauchte.

Indem ich den Logger vollständig auf java.util.logging.Logger qualifiziere, fügt Sensei den Import hinzu und schreibt die Codezeile, die ich haben möchte, d.h.

Logger logger = Logger.getLogger(SysOutTest.class.getName());


Vollständige Qualifizierung des Loggers zu java.util.logging.Logger


Eine nützliche Sache an diesem Rezept ist, dass es das Logger-Feld nur einmal hinzufügt, so dass ich es auf jeden bestehenden Code anwenden kann, in dem ich `System.out.println` verwendet habe, und Sensei verwenden kann, um alle Vorkommen in meiner Codedatei zur gleichen Zeit zu ändern.


Logger verwenden Alle Probleme in der Datei beheben



Nächste Schritte

Sobald ich mich daran gewöhnt habe, werde ich mir irgendwann abgewöhnen, System.out.println zu verwenden.

Ich kann Sensei verwenden, um mir beim proaktiven Schreiben von Code zu helfen, indem ich ein zweites Rezept erstelle, das mir hilft, einen Logger zu erstellen.

Ich kann z. B. auf eine Klasse passen, in der es kein Feld namens Logger gibt, und eines hinzufügen.

Wenn ich ein Rezept der Ebene Information erstelle


Name: Logger: Logger hinzufügen

Beschreibung: Logger zur Klasse hinzufügen


Zum Anpassen an eine Klasse ohne Loggerfeld:

suchen:
  Klasse:
    ohne:
      Kind:
        Feld:
          Name: "Logger"


Und dann werde ich einen Teil des QuickFix wiederverwenden, den wir vorhin gesehen haben:


availableFixes:

  - name: "Logger hinzufügen"
    Aktionen:
      - addField:
          field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}}.class.getName())"
          Ziel: "selbst"


Beachten Sie den Unterschied im Ziel hier im Vergleich zum ersten QuickFix. Hier wird self verwendet, weil unsere Suche mit der Klasse übereinstimmt. Der erste QuickFix verwendet parentClass, weil wir Code innerhalb der Klasse selbst gefunden haben.

Zusammenfassung

Dies stellt einen der wichtigsten Abläufe dar, die mit der Verwendung von Sensei verbunden sind, um Ihre persönlichen Programmierkenntnisse zu verbessern:

  • ein Rezept erstellen, das Ihnen bei der unmittelbaren "besten Praxis" hilft
  • Sobald Sie wissen, wie Sie diese Best Practice anwenden können... erstellen Sie ein Rezept, um Ihren Arbeitsablauf zu beschleunigen


---


Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.


Der Quellcode und die Rezepte dafür befinden sich im `sensei-blog-examples` Repository im Secure Code Warrior GitHub-Konto, im Modul `pojoexamples`.




Ressource anzeigen
Ressource anzeigen

Autor

Alan Richardson

Sie wollen mehr?

Tauchen Sie ein in unsere neuesten Erkenntnisse über sichere Kodierung im Blog.

Unsere umfangreiche Ressourcenbibliothek zielt darauf ab, die menschliche Herangehensweise an eine sichere Weiterbildung im Bereich der Programmierung zu stärken.

Blog ansehen
Sie wollen mehr?

Holen Sie sich die neuesten Forschungsergebnisse zur entwicklergesteuerten Sicherheit

Unsere umfangreiche Ressourcenbibliothek ist voll von hilfreichen Ressourcen, von Whitepapers bis hin zu Webinaren, die Ihnen den Einstieg in die entwicklungsorientierte sichere Programmierung erleichtern. Erforschen Sie sie jetzt.

Ressourcendrehscheibe

Umstellung auf einen Logger mit Sensei

Veröffentlicht Nov 30, 2020
Von Alan Richardson

Umstellung auf einen Logger mit Sensei

Dieser Beitrag beschreibt die Erstellung eines Rezepts für die Umstellung von System.out.println auf die Verwendung eines Java-Loggers.

Wenn ich Code hacke, anstatt TDD zu verwenden, und ich Fehler mache, habe ich die schlechte Angewohnheit, eine Zeile in System.out zu drucken, und ich wollte mir diese Angewohnheit abgewöhnen.

Beim Schreiben des untenstehenden Codes habe ich einen Haufen Fehler gemacht:

   private String getCountdownString() {
        String output = "";
        String prefix="";
        for(int countdown = 10; countdown > 0; countdown-- ){
            output = output + prefix + countdown;
            System.out.println(output);
            prefix=", ";
        }
        System.out.println(output);
        return output;
    }


Ursprünglich habe ich countdown++ geschrieben und die Schleife wurde nicht beendet.

Und ich habe Countdown > 1 verwendet, also nicht die gewünschte Ausgabe erhalten.

Am Ende habe ich meinen Code mit System.out.println überhäuft, um mir beim Debuggen zu helfen. Und die Erfahrung hat mich darin bestärkt, dass ich lernen muss, einen Logger als Standardansatz zu verwenden.

Forschung

Glücklicherweise habe ich mir die Dokumentation vonSensei durchgelesen und mich für die Anleitung "Erste Schritte" entschieden, die mir bei der Erstellung eines Rezepts zur Konvertierung von System.out.println hilft und mich zur Verwendung eines Loggers ermutigt:

  • java.util.logging.Logger

Erstellen eines Rezepts

Als erstes klicke ich auf println und dann auf alt+enter, um ein neues Rezept zu erstellen.

System ausdrucken Ein neues Rezept erstellen


Ich erstelle sie mit den folgenden Angaben:


Name: Logger: Logger anstelle von println verwenden
Beschreibung: Logger statt println verwenden - denken Sie daran, System.out.println nicht mehr zu verwenden
Ebene: Fehler


Und ich beginne mit einem passenden Methodenaufruf mit dem Namen println


suchen:
  Methodenaufruf:
    Name: "println"

Und die Vorschau zeigt mir alle Übereinstimmungen in meinem Code.


Rezepteinstellungen Methodcall Println


Ich kann sehen, dass alle Übereinstimmungen in meinem Code für System.out.println sind, aber ich vertraue nicht darauf, dass dies auf lange Sicht die einzige Übereinstimmung sein wird. Ich möchte eine qualifiziertere Anweisung abgleichen, die ich ändern möchte.

Ich erweitere den Matcher, um nach einem Methodenaufruf auf ein Feld zu suchen, das in der Klasse System.


suchen:
  Methodenaufruf:
    Name: "println"
    "ein":
      Feld:
        in:
          Klasse:
            Name: "System"
        Name: "aus"



Ich könnte, wenn ich wollte, den Namen System vollständig zu java.lang.System qualifizieren

Rezepteinstellungen Methodcall name system

Ändern des Codes zum Protokollieren


Als nächstes möchte ich den QuickFix erstellen.

Zuerst möchte ich die Codezeile ändern, die die Ausgabe protokolliert:


availableFixes:
- Name: "Logger verwenden"
  Aktionen:
  - umschreiben:
      to: "logger.log(Level.INFO, {{{ arguments.0 }}})"



Ich muss mir das Format der Schnurrbartvorlage nicht merken. Ich benutzte die Funktion "Variablen anzeigen" in der GUI, um mir das Argument anzeigen zu lassen und doppelklickte es an. Dann füllte die GUI die entsprechende passende Schnurrbartvorlage aus.



Wenn ich es ausprobiere, kann ich sehen, dass ich immer noch alt+enter drücken muss, um das Level-Enum zu importieren. Wenn ich jedoch meinen QuickFix so ändere, dass er ein voll qualifiziertes Element enthält, fügt Sensei den Import für mich hinzu, z. B.

  • Sie ersetzt System.out.println(output); durch

logger.log(Level.INFO, output);

  • Und fügen Sie einen Import für das Enum hinzu:

import java.util.logging.Level;

  • Wenn ich umschreibe in:
logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})

Das wird auch funktionieren, aber ich muss mir immer noch die Syntax merken, um den Logger überhaupt erst zu instanziieren.

Syntax zum Instanziieren des Loggers an erster Stelle


Ändern des Codes zum Hinzufügen des Logger-Feldes

Ich kann meinen QuickFix ändern, um das Feld auch für mich zu erstellen.

Ich werde den Logger zuerst codieren und dann zu meinem Rezept hinzufügen, damit ich ihn nie wieder codieren muss.

Logger logger2 = Logger.getLogger(SysOutTest.class.getName());


Ich neige dazu, den Beispielcode, den ich generiert sehen möchte, zuerst zu schreiben, weil ich dann die IntelliJ-Codevervollständigung und die Syntaxprüfung verwenden kann, um sicherzustellen, dass ich ihn richtig hinbekomme. Als Nebeneffekt wird er dann in der Codevorschau angezeigt, wenn ich das Rezept bearbeite, um die QuickFix-Zeilen hinzuzufügen, die diesen Code erzeugen.

Und wenn ich den Beispielcode schreibe, möchte ich einen anderen Feldnamen verwenden (hier verwende ich logger2), denn Sensei ist schlau genug, um kein doppeltes Feld hinzuzufügen, also muss ich es mit einem anderen Namen täuschen.

Ich ändere also das Rezept, um diesen Code zu erstellen, indem ich ein Feld mit dem Namen logger hinzufüge.

availableFixes:

- Name: "Logger verwenden"
  Aktionen:
  - umschreiben:
      to: "logger.log(java.util.logging.Level.INFO, {{{ arguments.0 }}})"
  - addField:
      field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}}.class.getName())"
      Ziel: "parentClass"


Beachten Sie, dass ich SysOutTest in eine Mustache-Variable geändert habe, damit sie den Namen jeder Klasse aufnimmt, in der ich dieses Rezept verwende. Und wieder habe ich mir die Mustache-Syntax nicht gemerkt, ich habe die GUI Show Variables benutzt, um den Ersatz zu finden, den ich brauchte.

Indem ich den Logger vollständig auf java.util.logging.Logger qualifiziere, fügt Sensei den Import hinzu und schreibt die Codezeile, die ich haben möchte, d.h.

Logger logger = Logger.getLogger(SysOutTest.class.getName());


Vollständige Qualifizierung des Loggers zu java.util.logging.Logger


Eine nützliche Sache an diesem Rezept ist, dass es das Logger-Feld nur einmal hinzufügt, so dass ich es auf jeden bestehenden Code anwenden kann, in dem ich `System.out.println` verwendet habe, und Sensei verwenden kann, um alle Vorkommen in meiner Codedatei zur gleichen Zeit zu ändern.


Logger verwenden Alle Probleme in der Datei beheben



Nächste Schritte

Sobald ich mich daran gewöhnt habe, werde ich mir irgendwann abgewöhnen, System.out.println zu verwenden.

Ich kann Sensei verwenden, um mir beim proaktiven Schreiben von Code zu helfen, indem ich ein zweites Rezept erstelle, das mir hilft, einen Logger zu erstellen.

Ich kann z. B. auf eine Klasse passen, in der es kein Feld namens Logger gibt, und eines hinzufügen.

Wenn ich ein Rezept der Ebene Information erstelle


Name: Logger: Logger hinzufügen

Beschreibung: Logger zur Klasse hinzufügen


Zum Anpassen an eine Klasse ohne Loggerfeld:

suchen:
  Klasse:
    ohne:
      Kind:
        Feld:
          Name: "Logger"


Und dann werde ich einen Teil des QuickFix wiederverwenden, den wir vorhin gesehen haben:


availableFixes:

  - name: "Logger hinzufügen"
    Aktionen:
      - addField:
          field: "java.util.logging.Logger logger = Logger.getLogger({{{ containingClass.name\
        }}}.class.getName())"
          Ziel: "selbst"


Beachten Sie den Unterschied im Ziel hier im Vergleich zum ersten QuickFix. Hier wird self verwendet, weil unsere Suche mit der Klasse übereinstimmt. Der erste QuickFix verwendet parentClass, weil wir Code innerhalb der Klasse selbst gefunden haben.

Zusammenfassung

Dies stellt einen der wichtigsten Abläufe dar, die mit der Verwendung von Sensei verbunden sind, um Ihre persönlichen Programmierkenntnisse zu verbessern:

  • ein Rezept erstellen, das Ihnen bei der unmittelbaren "besten Praxis" hilft
  • Sobald Sie wissen, wie Sie diese Best Practice anwenden können... erstellen Sie ein Rezept, um Ihren Arbeitsablauf zu beschleunigen


---


Sie können Sensei aus IntelliJ heraus über "Preferences \ Plugins" (Mac) oder "Settings \ Plugins" (Windows) installieren und dann einfach nach "sensei secure code" suchen.


Der Quellcode und die Rezepte dafür befinden sich im `sensei-blog-examples` Repository im Secure Code Warrior GitHub-Konto, im Modul `pojoexamples`.




Wir bitten Sie um Ihre Erlaubnis, Ihnen Informationen über unsere Produkte und/oder verwandte Themen der sicheren Codierung zuzusenden. Wir werden Ihre persönlichen Daten immer mit äußerster Sorgfalt behandeln und sie niemals zu Marketingzwecken an andere Unternehmen verkaufen.

Senden
Um das Formular abzuschicken, aktivieren Sie bitte "Analytics"-Cookies. Sie können die Cookies wieder deaktivieren, sobald Sie fertig sind.