Juni 2007
Einführung
Manchmal gibt es keine Alternative dazu, sich anzusehen, was über die Leitung geht. Das gilt insbesondere beim Schreiben von Software, die Webdienste wie die Google Data APIs verwendet, bei denen viele Vorgänge HTTP-Anfragen umfassen. Wenn alles andere fehlschlägt, können Sie überprüfen, ob Ihr Programm das tut, was Sie erwarten, indem Sie sich die tatsächlich übertragenen und empfangenen Bytes ansehen. Viele der Clientbibliotheken für die Google Data APIs haben einen Debugging-Modus, in dem der HTTP-Traffic angezeigt wird. Das ist besonders nützlich, wenn Sie keinen Zugriff auf einen Paket-Sniffer wie WireShark oder Fiddler haben.
Ich kann nicht zählen, wie oft ich geschworen hätte, dass mein Programm korrekt war, nur um beim Untersuchen eines Paket-Traces festzustellen, dass es ein zusätzliches Zeilenumbruchzeichen oder einen falsch benannten HTTP-Header gab. Die Programmierung für einen Webdienst ohne Berücksichtigung des HTTP-Traffics ist wie der Versuch, eine Nadel einzufädeln, ohne hinzusehen.
Es kann jedoch vorkommen, dass ein Packet Sniffer nicht verfügbar ist oder nicht ausreicht, um verschlüsselte Pakete zu verarbeiten. Keine Sorge – Sie können diese Einschränkung umgehen, indem Sie einige Mechanismen zur Protokollierung im Programm nutzen. Mithilfe dieser Protokollierungsfunktionen können Sie einige oder alle ausgetauschten Daten sehen, auch für verschlüsselte HTTPS-Daten oder Remote-Code.
Für diesen Artikel habe ich Beispielcode für die Diagnose in drei Sprachen mit den Clientbibliotheken der Google Data API für Java, .NET und Python geschrieben. In jedem Beispiel aktiviere ich die Protokollierung oder das Debugging, authentifiziere mich mit der Clientanmeldung und rufe dann eine Liste meiner Google-Tabellen ab, deren Titel ich ausgebe.
Java
Mit den java.util.logging
-Klassen können Sie die Protokollierungsstufen für einige wichtige Objekte in der Clientbibliothek festlegen und so Traffic-Daten verfügbar machen. Im Beispiel unten habe ich die HTTP-Header und die Aktivitäten des XML-Parsers ausgewählt, um einen vollständigen Überblick über die übertragenen Daten zu erhalten.
Die Google Data Java-Clientbibliothek enthält separate Klassen für die Verarbeitung von HTTP-Anfragen und das Parsen von XML. Daher muss ich zwei Logger-Objekte erstellen, eines für jede Klasse: com.google.gdata.client.http.HttpGDataRequest
verarbeitet den HTTP-Traffic, während com.google.gdata.util.XmlParser
für das Parsen von XML zuständig ist.
Die Logger-Instanzen zeichnen Aktivitäten für HttpGDataRequest
und XmlParser
auf. Sie können den Detaillierungsgrad der Ausgabe jedes Loggers steuern. Für diese Demonstration habe ich alle Ereignisse ausgewählt, die von den Objekten HttpGDataRequest
und XmlParser
generiert wurden.
Nachdem ich meine Logger erstellt und konfiguriert habe, muss ich ihnen mitteilen, was sie tun sollen, wenn sie ein Ereignis von ihren Klassen empfangen. Ich möchte alle Logging-Informationen in die Konsole schreiben. Dazu erstelle ich ein ConsoleHandler
und füge es beiden Loggern hinzu.
Hier ist mein Beispielcode:
import com.google.gdata.client.spreadsheet.*;
import com.google.gdata.data.spreadsheet.*;
import com.google.gdata.util.*;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.logging.*;
public class PrintSpreadsheetsWithLogging {
public static void main(String [] args) throws AuthenticationException,
ServiceException, IOException {
// Configure the logging mechanisms.
Logger httpLogger = Logger.getLogger("com.google.gdata.client.http.HttpGDataRequest");
httpLogger.setLevel(Level.ALL);
Logger xmlLogger = Logger.getLogger("com.google.gdata.util.XmlParser");
xmlLogger.setLevel(Level.ALL);
// Create a log handler which prints all log events to the console.
ConsoleHandler logHandler = new ConsoleHandler();
logHandler.setLevel(Level.ALL);
httpLogger.addHandler(logHandler);
xmlLogger.addHandler (logHandler);
SpreadsheetService service = new SpreadsheetService("testing-loggingExampleApp-1");
service.setUserCredentials(email, password);
// Get a list of your spreadsheets.
URL metafeedUrl = new URL("http://spreadsheets.google.com/feeds/spreadsheets/private/full ");
SpreadsheetFeed feed = service.getFeed(metafeedUrl, SpreadsheetFeed.class);
// Print the title of each spreadsheet.
List spreadsheets = feed.getEntries();
for (int i = 0; i < spreadsheets.size(); i++) {
SpreadsheetEntry entry = (SpreadsheetEntry)spreadsheets.get(i);
System.out.println("\t" + entry.getTitle().getPlainText());
}
}
}
Wenn Sie dieses Programm ausführen, sehen Sie in der Konsole etwa Folgendes (ich habe einige der weniger interessanten Teile herausgeschnitten):
Jun 7, 2007 10:24:50 AM ...HttpGDataRequest setPrivateHeader FINER: Authorization: <Not Logged> Jun 7, 2007 10:24:50 AM ...HttpGDataRequest setHeader FINER: User-Agent: ... ... Jun 7, 2007 10:25:20 AM ...HttpGDataRequest execute FINE: 200 OK Jun 7, 2007 10:25:20 AM ...HttpGDataRequest execute FINER: Date: Thu, 07 Jun 2007 17:25:24 GMT Jun 7, 2007 10:25:20 AM ...HttpGDataRequest execute FINER: null: HTTP/1.1 200 OK Jun 7, 2007 10:25:20 AM ...HttpGDataRequest execute FINER: Content-Type: application/atom+xml; charset=UTF-8 Jun 7, 2007 10:25:20 AM ...HttpGDataRequest execute FINER: Last-Modified: Thu, 07 Jun 2007 17:25:22 GMT ... Jun 7, 2007 10:25:20 AM ...XmlParser startElement FINE: Start element id Jun 7, 2007 10:25:20 AM ...XmlParser endElement FINE: End element id ... Jun 7, 2007 10:25:20 AM ...XmlParser startElement FINE: Start element title Jun 7, 2007 10:25:20 AM ...XmlParser startElement FINER: Attribute type='text' Jun 7, 2007 10:25:20 AM ...XmlParser endElement FINE: End element title ... Jun 7, 2007 10:25:20 AM ...XmlParser endElement FINE: End element entry ... Jun 7, 2007 10:25:20 AM ...XmlParser endElement FINE: End element feed
Diese Logs können sehr umfangreich werden. Daher sollten Sie die Ebenen der Logger sorgfältig festlegen. Sie können auch ein FileHandler
anstelle eines ConsoleHandler
erstellen, um die Logdaten für die spätere Verwendung zu speichern.
Wenn Sie sich nicht für Java interessieren, können Sie es natürlich mit .NET versuchen.
.NET
Wenn Sie den HTTP-Traffic in der .NET-Clientbibliothek erfassen möchten, können Sie die Standardanfrage-Factory im Client durch ein GDataLoggingRequestFactory
ersetzen.
Die HTTP-Anfragen in der .NET-Bibliothek werden von GDataRequestFactory
erstellt, das sich in jedem Service-Objekt befindet. Die normalen Request-Factories führen kein Logging durch, aber die GDataLoggingRequestFactory
, die eine Unterklasse von GDataRequestFactory
ist, hat ein integriertes Logging. Sie können den vollständigen Pfad der Logdatei angeben, indem Sie CombinedFileName
festlegen.
Nachdem Sie die RequestFactory eingerichtet haben, müssen Sie sie im Service-Objekt ersetzen, indem Sie die RequestFactory
des Service-Objekts festlegen.
Ihr Code könnte etwa so aussehen:
using System;
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Spreadsheets;
namespace LogginTest
{
class Program
{
static void Main(string[] args)
{
SpreadsheetsService service = new SpreadsheetsService("-exampleApp-1");
service.setUserCredentials(email, password);
Google.GData.Client.GDataLoggingRequestFactory factory = new GDataLoggingRequestFactory("wise", "SpreadsheetsLoggingTest");
factory.MethodOverride = true;
factory.CombinedLogFileName = "c:\\temp\\xmllog.log";
Console.WriteLine("Log file name:" + factory.CombinedLogFileName);
service.RequestFactory = factory;
SpreadsheetQuery query = new SpreadsheetQuery();
SpreadsheetFeed feed = service.Query(query);
Console.WriteLine("Your spreadsheets:");
foreach (SpreadsheetEntry entry in feed.Entries)
{
Console.WriteLine(entry.Title.Text);
}
Console.ReadKey();
}
}
}
Die resultierende Logdatei enthält die XML-Anfragen und ‑Antworten. Hier ist ein gekürztes Beispiel, das ich mit tidy formatiert habe.
<?xml version='1.0' encoding='utf-8'?> <feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'> <id> http://spreadsheets.google.com/feeds/spreadsheets/private/full</id> <updated>2007-06-07T22:05: 02.674Z</updated> <link rel='self' type='application/atom+xml' href='http://spreadsheets.google.com/feeds/spreadsheets/private/full'> </link> ... <entry> <updated>2007-03-28T17:28:57.250Z</updated> <category scheme=' http://schemas.google.com/spreadsheets/2006' term='http://schemas.google.com/spreadsheets/2006#spreadsheet'> <title type='text'>events</title> <content type='text'>events</content> ... </entry> <entry> <updated>2007-05-25T22:11:08.200Z</updated> <category scheme=' http://schemas.google.com/spreadsheets/2006' term='http://schemas.google.com/spreadsheets/2006#spreadsheet'> </category> <title type='text'>UnitTest</title> <content type='text'>UnitTest</content> ... </entry> ... </feed>
Vielleicht sind Sie aber auch ein Fan von Skriptsprachen und bevorzugen Python.
Python
Wenn Sie den HTTP-Traffic in der Python-Clientbibliothek erfassen möchten, können Sie den HTTP-Header-Traffic in der Konsole ausgeben lassen, indem Sie den Debugmodus im HTTP-Client aktivieren. Das Dienstobjekt hat ein Debug-Element, das Sie auf True setzen können.
Wenn Sie „debug“ auf „true“ setzen, wird das Debugging-Flag im zugrunde liegenden HTTPRequest
-Objekt festgelegt, das im Dienstobjekt enthalten ist.
Hier ist ein Beispiel, in dem die HTTP-Header ausgegeben werden, die vom Tabellenserver gesendet werden, wenn Sie eine Liste Ihrer Tabellen anfordern.
#!/usr/bin/python
import gdata.spreadsheet.service
client = gdata.spreadsheet.service.SpreadsheetsService()
client.debug = True
client.ClientLogin(email, password)
feed = client.GetSpreadsheetsFeed()
for entry in feed.entry:
print entry.title.text
In der Konsole wird dann etwa Folgendes angezeigt:
reply: 'HTTP/1.1 200 OK\r\n' header: Content-Type: application/atom+xml; charset=UTF-8 header: Last-Modified: Thu, 07 Jun 2007 18:22:35 GMT header: Cache-Control: max-age=0, must-revalidate, private header: Transfer-Encoding: chunked ... header: Date: Thu, 07 Jun 2007 18:22:35 GMT header: Server: GFE/1.3
Wenn Sie zusätzliche Vorgänge wie das Einfügen oder Aktualisieren ausführen, werden entsprechende Anfragedaten in der Konsole angezeigt.
Fazit
In dieser kurzen Anleitung wurde gezeigt, wie Sie einem Java-, .NET- oder Python-Programm, das die Google Data API-Clientbibliotheken verwendet, grundlegende Protokollierungsfunktionen hinzufügen können. Diese Techniken können nützlich sein, wenn Sie HTTP-Austauschvorgänge debuggen müssen, aber keinen Zugriff auf einen Packet Sniffer haben. Diese Beispiele sind nur die Spitze des Eisbergs. Viele der in diesen Sprachen vorhandenen Protokollierungsmechanismen sind viel leistungsfähiger als das, was hier gezeigt wird. Weitere Informationen zur Protokollierung oder zu den Google Data APIs finden Sie in der Liste der Ressourcen unten.
Die in diesem Artikel behandelten Clientbibliotheken finden Sie auf den folgenden Seiten:
Zugehörige Wissensdatenbank-Artikel:
- Wie erhalte ich HTTP-Protokollierungsinformationen in der Java-Clientbibliothek?
- Wie erhalte ich HTTP-Protokollierungsinformationen in der .NET-Clientbibliothek?
- Welche Tools eignen sich gut für das HTTP-Debugging?
- Was ist die Google Spreadsheets API?
Diskussionsgruppen: Wir haben bereits einige und es werden noch mehr hinzukommen, wenn weitere Google Data APIs eingeführt werden. Wir behalten die Gruppen im Blick.
Wenn Sie Fragen oder Vorschläge haben, freue ich mich, von Ihnen zu hören. Treten Sie der Diskussionsgruppe bei und beginnen Sie mit dem Posten.