In Produktionsumgebungen sind Bugs und Leistungsprobleme unvermeidlich. Effektive Debugging-Tools wie Traces und Logs können Zeit sparen und die Benutzerzufriedenheit verbessern.
Nur ein weiterer manischer Montag
Sie gehören zu einem Team, das für eine große Softwareanwendung verantwortlich ist, die zahlreiche Client-Frontends, serverlose Funktionen und interne Dienstprogrammbibliotheken umfasst. Diese Woche bist du im Schilddienst, was bedeutet, dass du der erste Ansprechpartner für alle eingehenden Rückmeldungen und Support-Anfragen bist.
Nachdem Sie Ihren Morgenkaffee getrunken haben, öffnen Sie Ihren Posteingang und finden die folgende Nachricht von einem sehr wichtigen Kunden, der ~ 30% zum Umsatz Ihres Produkts beiträgt:
Betreff: Die Website funktioniert nicht.
Ich habe alle Mitarbeiter des Unternehmens eingeladen, der App beizutreten, aber es ist über eine Stunde her, und sie haben ihre Bestätigungs-E-Mails nicht erhalten. Ich habe auch versucht, eine Datei auf unser Dashboard hochzuladen, aber sie wird nicht angezeigt. Wenn das Problem nicht innerhalb von 24 Stunden gelöst ist, müssen wir unser Geschäft woanders erledigen.
Sie machen sich schnell an die Arbeit und führen den Code lokal aus. Sie laden 20 Personen zu einem Team auf der Website ein, und jede Bestätigungs-E-Mail wird innerhalb von Sekunden gesendet. Sie versuchen, eine Datei auf das Dashboard hochzuladen, und sie wird wie erwartet ohne Probleme angezeigt.
Als Nächstes testen Sie dieselben Szenarien in einer Remote-Entwicklungsumgebung. Immer noch keine Probleme. Sie probieren sogar 50 verschiedene Möglichkeiten aus, um diese beiden Funktionen zu unterbrechen, aber alles funktioniert einwandfrei.
In der Zwischenzeit tickt die Uhr und es steht viel auf dem Spiel. Ihr Manager, der verständlicherweise Angst hat, einen so wichtigen Kunden zu verlieren, plant einen spontanen Zoom-Anruf, um einzuchecken.
Sie teilen Ihren Bildschirm und beginnen, Ihre Untersuchung zu erklären. Wenn Sie zwischen verschiedenen Code-Repositorys navigieren, verweist jedes auf zehn weitere Repositorys, die es zu erkunden gilt. Das Kaninchenloch wird immer tiefer, und schon bald sind Dutzende von VSCode-Tabs geöffnet, was Ihren Computer an seine Grenzen bringt. Ihr Manager meldet sich nervös zu:
„Schon Glück gehabt?“
Aber an diesem Punkt haben Sie einfach das Gefühl, Ihre Codebasis zu durchsuchen, ohne dass ein Ende in Sicht ist.

Wie können wir unser Leben einfacher machen?
Diese Situation kann vermieden werden, indem Sie nur ein bisschen mehr haben Daten. Schauen wir uns an, wie das Hinzufügen von Traces und Logs zu unserem Code uns helfen kann, die Probleme zu lösen, die sich aus der oben genannten gefälschten Kundenanfrage ergeben haben!
Erfassung der Daten, die Ihnen Ihre Kunden nicht senden
Beim Debuggen ist es üblich, sich auf die von Benutzern bereitgestellten Informationen zu verlassen. Wie in unserem Beispiel melden Kunden jedoch häufig vage Probleme wie „Die Website funktioniert nicht“ und geben kaum bis gar keine technischen Details an. Das ist wo aufzeichnen werden von unschätzbarem Wert — sie sammeln wichtige Daten automatisch, sodass Sie sich nicht auf unvollständiges oder unklares Feedback verlassen müssen.
Schauen wir uns den folgenden Code an, der Datei-Uploads verarbeitet:
const { uploadFile } = require('fake-upload-file');
const handler = ({ filename }) => {
uploadFile(filename);
};
Auf den ersten Blick gibt uns dieser Schnipsel nicht viel, womit wir arbeiten könnten. Wenn Fake-Upload-Datei
ist ein äußeres Paket, wir sind blind für sein Innenleben. Ebenso hat unser Kunde keine Informationen zu den Dateien angegeben, die er hochladen wollte. Ohne zusätzliche Daten ist es schwierig, das Problem zu lokalisieren.
Logs helfen Sie, diese Lücke zu schließen. Logs sind einfach Aufzeichnungen von Ereignissen, die in Ihrer Anwendung auftreten, wobei Details wie die folgenden erfasst werden:
- Was Aktionen wurden durchgeführt.
- Wann sie sind passiert.
- Wo im Code sind sie aufgetreten.
- Irgendwelche relevanten Daten oder Fehler zu diesem Zeitpunkt.
Durch die strategische Platzierung von Protokollanweisungen erstellen Sie einen Breadcrumb-Trail, der Ihnen hilft, die Schritte der Anwendung nachzuvollziehen und potenzielle Probleme zu identifizieren. Dies ist besonders nützlich, wenn Sie das Problem nicht replizieren können oder wenn Benutzer selbst keine detaillierten Informationen bereitstellen können.
Es gibt viele Observability-Tools zum Sammeln, Speichern und Analysieren von Protokollen, wie ELK-Stapel, Datenhund, Splunk, und andere. Diese Plattformen aggregieren Protokolle aus verschiedenen Quellen, bieten eine Echtzeitüberwachung und helfen Ihnen bei der effizienten Fehlerbehebung. Für diese Demonstration verwenden wir Coralogix.
Lassen Sie uns unseren Datei-Upload-Handler um die Protokollierung erweitern, um wichtige Details zu erfassen:
const { uploadFile } = require('fake-upload-file');
const handler = ({ filename }) => {
try {
uploadFile(filename);
logger.info({
message: 'File uploaded successfully!',
route: 'file-upload',
filename,
});
} catch (error) {
logger.error({
message: 'Error occurred while uploading file',
route: 'file-upload',
filename,
});
throw error;
}
};
In diesem aktualisierten Code:
- Erfolgsprotokolle:
- Wir protokollieren eine Erfolgsmeldung für jede hochgeladene Datei, einschließlich der
Dateiname
undRoute
(gesetzt aufDatei-Upload
). - Dies erleichtert das Filtern und Konzentrieren auf relevante Protokolle bei der Problembehandlung.
- Wir protokollieren eine Erfolgsmeldung für jede hochgeladene Datei, einschließlich der
- Fehlerprotokolle:
- Wenn etwas schief geht, protokollieren wir eine Fehlermeldung zusammen mit dem Dateinamen und den Fehlerdetails (z. B.
error.message
). - Dadurch wird sichergestellt, dass kritische Fehler für zukünftiges Debugging erfasst werden.
- Wenn etwas schief geht, protokollieren wir eine Fehlermeldung zusammen mit dem Dateinamen und den Fehlerdetails (z. B.
Durch das systematische Hinzufügen von Protokollen zu Ihrer Anwendung ermöglichen Sie proaktives Debugging und müssen sich nicht darauf verlassen, dass Benutzer detaillierte Berichte bereitstellen. Lassen Sie uns nun Coralogix verwenden, um die in der Produktion gesammelten Protokolle zu analysieren.

Wenn Sie die Protokolle überprüfen, stellen Sie ein Muster fest: Alle Fehler beinhalten .pdf
Dateien. Lassen Sie uns weiter untersuchen, indem wir die untersuchen Datei hochladen
funktion:
const uploadFile = (filename) => {
const extension = filename.split('.').pop();
if (extension === 'pdf') {
throw new Error('Not implemented yet!')
} else {
// ...logic to upload files
}
};
Es stellt sich heraus, dass das Programm nicht unterstützt .pdf
Dateien noch, und diese Einschränkung wurde dem Kunden nicht mitgeteilt. Mit diesen Erkenntnissen können Sie schnell über die nächsten Schritte entscheiden, z. B. die Verbesserung der Fehlerbehandlung oder die Aktualisierung der Dokumentation zur Klärung nicht unterstützter Dateitypen.
Identifizierung von Engpässen in unserem Code
Auf zu unserem nächsten Problem! Der Kunde hat Probleme mit dem Nichtsenden von Bestätigungs-E-Mails gemeldet.
Wir wissen, dass der Kunde versucht hat, eine große Anzahl von Mitarbeitern einzuladen, als das Problem auftrat. Nehmen wir jedoch an, diese Zahl übersteigt bei weitem das, was wir in einem Stresstest simulieren können, und lokale Tests haben keine Hinweise auf Engpässe ergeben.
Hier ist der Code, der das Senden von Bestätigungs-E-Mails verarbeitet:
const getUsers = () => {
return Database.getAllUsers();
};
const filterByVerification = (users) => {
return users.reduce((filteredUsers, user) => {
if (user.requiresEmailVerification) {
return filteredUsers.concat([user]);
}
return filteredUsers;
}, []);
};
const sendVerificationEmails = (users) => {
return Promise.all(
users.map(user => EmailUtils.sendVerificationEmail(user))
);
}
const handler = async () => {
const users = await getUsers();
const usersRequiringVerification = filterByVerification(users);
await sendVerificationEmails(usersRequiringVerification);
}
Was wir wirklich gerne wissen würden ist welcher Teil des Codes wird für den Kunden langsamer. Ruft es Benutzer aus der Datenbank ab? Benutzer filtern, die eine Überprüfung benötigen? Oder vielleicht E-Mails in großen Mengen versenden?
Das ist wo Verfolgung kommt rein. Tracing ist eine Methode zur Nachverfolgung von Anfragen, die sich durch verschiedene Teile Ihrer Anwendung bewegen. Im Gegensatz zu Protokollen, die diskrete Aufzeichnungen von Ereignissen liefern, erstellen Traces eine Zeitleiste von Aktionen (genannt überspannt), die zeigen, wie lange jeder Schritt dauert. Auf diese Weise können Sie Engpässe lokalisieren und sich auf die Optimierung der richtigen Bereiche konzentrieren.
Fügen wir dieser Logik Tracing hinzu, um die Ausführungszeit für bestimmte Operationen zu verfolgen:
const getUsers = () => {
return tracing.wrap(() => {
return Database.getAllUsers();
}, 'getUsers');
};
const filterByVerification = (users) => {
return tracing.wrap(() => {
return users.reduce((filteredUsers, user) => {
if (user.requiresEmailVerification) {
return filteredUsers.concat([user]);
}
return filteredUsers;
}, []);
}, 'filterByVerification');
};
const sendVerificationEmails = (users) => {
return tracing.wrap(() => {
return Promise.all(
users.map(user => EmailUtils.sendVerificationEmail(user))
);
}, 'sendVerificationEmails');
}
const handler = async () => {
return tracing.wrap(async (span) => {
const users = await getUsers();
const usersRequiringVerification = filterByVerification(users);
span.setAttribute('numUsersRequiringVerification', usersRequiringVerification.length);
await sendVerificationEmails(usersRequiringVerification);
}, 'send-verification-emails:handler');
}
Jeder verfolgte Abschnitt macht Folgendes:
Benutzer abrufen
: Verfolgt, wie lange es dauert, alle Benutzer aus der Datenbank abzurufen.Nach Überprüfung filtern
: Verfolgt die Zeit, die für das Filtern von Benutzern aufgewendet wurde, die eine Überprüfung benötigen.Bestätigungs-E-Mails senden
: Verfolgt die Zeit, die für das Senden von E-Mails in großen Mengen aufgewendet wurde.Handler
: Verfolgt den gesamten Prozess und fügt Metadaten über die Anzahl der Benutzer hinzu, die überprüft werden müssen.
Sobald dieser Code in der Produktion eingesetzt wird, können wir die Spuren in einsehen Coralogix um Engpässe zu identifizieren. Schauen wir uns die Spuren an, die wir gesammelt haben:

Wenn wir uns die gesammelten Spuren ansehen, können wir sehen, dass Bestätigungs-E-Mails senden:Handler
span dauert mit steigender Anzahl von Benutzern länger. Wenn Sie auf den Trace mit der längsten Dauer klicken, erhalten Sie eine detaillierte Zeitleiste mit den untergeordneten Zeitspannen:

Hier ist die Aufschlüsselung der Zeiträume für jedes Kind:
Span-Name/DauerFQ-Users-API: getUsers
80,53 msFQ-Users-API: Nach Überprüfung filtern
26,32 sFQ-Users-API: Bestätigungs-E-Mails versenden
523,92 ms
Offensichtlich ist der Nach Überprüfung filtern
Span ist der Engpass. Lassen Sie uns seine Logik untersuchen:
const filterByVerification = (users) => {
return users.reduce((filteredUsers, user) => {
if (user.requiresEmailVerification) {
return filteredUsers.concat([user]);
}
return filteredUsers;
}, []);
};
Das Problem liegt bei der Concat
Methode. Jedes Mal Concat
aufgerufen wird, erzeugt es ein neues Array, das zunehmend ineffizient wird, je größer der Benutzer
Array wächst. Dies wird in einer Schleife zusammengefasst, in der für jede Iteration ein neues Array erstellt wird.
Wir können dies optimieren, indem wir die drücken
Methode stattdessen. drücken
ändert das Array an Ort und Stelle, wodurch der Aufwand beim Erstellen neuer Arrays entfällt:
const filterByVerification = (users) => {
return users.reduce((filteredUsers, user) => {
if (user.requiresEmailVerification) {
filteredUsers.push(user);
}
return filteredUsers;
}, []);
};
Austauschen Concat
mit drücken
beseitigt diesen Engpass und verbessert die Leistung erheblich.
Diese Änderung ermöglicht es uns, Bestätigungs-E-Mails schneller zu versenden, um unseren Kunden ein besseres Erlebnis zu bieten und gleichzeitig die Systemeffizienz aufrechtzuerhalten.
Irgendwo in einer besseren Zeitleiste...
Sie sind in einem Team, das für eine große Softwareanwendung verantwortlich ist, und das Team weiß, dass gute Traces und Logs für die Wartung einer so großen Anwendung unerlässlich sind.
Du schnappst dir deinen Morgenkaffee, öffnest deinen Posteingang und findest Feedback von einem sehr wichtigen Kunden.
Sie fragen nach der ID des Kunden und öffnen dann Coralogix. Innerhalb weniger Minuten entdecken Sie den Engpass in der FQ-Users-API: Nach Überprüfung filtern
Logik, die die Spuren verwendet. Nachdem Sie das Problem identifiziert haben, tauschen Sie das ineffiziente aus Concat
Methode für das optimierte drücken
Methode und Bereitstellung des Fixes in der Produktion.
Als Nächstes überprüfen Sie die Protokolle für Datei-Upload
Route. Das Problem wird klar: alles pdf
Dateien können nicht hochgeladen werden. Dieses Problem erfordert zwar eine umfassendere Lösung, aber Sie können den Kunden schnell darüber informieren, dass andere Dateitypen in der Zwischenzeit funktionieren sollten. Dieses sofortige Feedback sorgt für Klarheit und reduziert die Frustration des Kunden.
Dank Traces und Logs haben Sie die Probleme nicht nur schnell erkannt, sondern dem Kunden auch vertrauensvoll und mit umsetzbaren Updates reagiert. Der Kunde ist beeindruckt von Ihrer schnellen Reaktion und Lösung. Sie bleiben ein treuer Partner, veröffentlichen eine begeisterte Bewertung Ihres Produkts und empfehlen Ihren Service anderen in ihrem Netzwerk.

All dieser Erfolg ist auf die Weitsicht des Entwicklungsteams zurückzuführen, die Protokollierungs- und Nachverfolgungspraktiken proaktiv umzusetzen. Diese Tools verwandelten einen möglicherweise chaotischen Debugging-Prozess in eine optimierte und effiziente Lösung.
Warum Logs and Traces ein Muss sind
Da Software immer komplexer wird, wird die Fähigkeit, schnell, effizient und sicher zu debuggen, zu einem Wettbewerbsvorteil. Indem Sie Protokolle und Traces hinzufügen, bevor Probleme auftreten, können Sie nicht nur besser auf Kundenanfragen reagieren, sondern auch Leistungsengpässe, Systemausfälle und Dateninkonsistenzen schneller als je zuvor erkennen.
Wenn Sie heute in robuste Observability-Praktiken investieren, können Sie Zeit sparen, Kunden binden und in Zukunft Kopfschmerzen vermeiden. Logs und Traces sind nicht nur Tools zum Debuggen — sie sind Tools, mit denen Sie Ihr Unternehmen und Ihre Kunden zufrieden stellen können.