Przejdź do głównej zawartości

Wzorce debugowania

Debugowanie to dziedzina, w której pomoc AI zmienia się z pomocnej w rewolucyjną. Łącząc systematyczne podejścia z możliwościami rozpoznawania wzorców i analizy kodu przez AI, możesz wytropić nawet najbardziej nieuchwytne błędy w minuty zamiast godzin. Ten przewodnik przedstawia sprawdzone wzorce debugowania dla rzeczywistych scenariuszy.

AI zmienia debugowanie z frustrującego polowania na systematyczne badanie:

Rozpoznawanie wzorców

AI identyfikuje wzorce błędów w milionach baz kodu

Strategiczne logowanie

Automatycznie dodaje optymalne instrukcje debugowania

Analiza przyczyn źródłowych

Śledzi błędy przez złożone stosy wywołań

Walidacja poprawek

Zapewnia, że poprawki nie wprowadzają nowych błędów

Najsilniejszy wzorzec debugowania - pozwól AI inteligentnie instrumentować twój kod.

  1. Opisz problem

    Błąd: Uwierzytelnianie użytkownika zawodzi sporadycznie
    Błąd: "Token validation failed"
    Częstotliwość: ~30% prób logowania
    Wzorzec: Brak wyraźnej korelacji z typem użytkownika lub czasem
  2. AI dodaje strategiczne logowanie

    // Tryb Cursor Agent
    Agent: "Dodaj logowanie debugowania do śledzenia przepływu uwierzytelniania.
    Skup się na generowaniu tokenów, czasie walidacji i zmianach stanu"
    // AI dodaje ukierunkowane logowanie
    async function validateToken(token) {
    console.log('[AUTH] Token validation started', {
    tokenLength: token?.length,
    timestamp: Date.now(),
    tokenPrefix: token?.substring(0, 10) + '...'
    });
    try {
    const decoded = jwt.verify(token, SECRET);
    console.log('[AUTH] Token decoded', {
    userId: decoded.userId,
    exp: decoded.exp,
    timeUntilExpiry: decoded.exp * 1000 - Date.now()
    });
    // Sprawdź czy token wkrótce wygaśnie
    if (decoded.exp * 1000 - Date.now() < 60000) {
    console.warn('[AUTH] Token expiring soon', {
    expiresIn: Math.floor((decoded.exp * 1000 - Date.now()) / 1000) + 's'
    });
    }
    return decoded;
    } catch (error) {
    console.error('[AUTH] Token validation failed', {
    error: error.message,
    tokenAge: token ? Date.now() - jwt.decode(token)?.iat * 1000 : null
    });
    throw error;
    }
    }
  3. Zbieraj i analizuj

    Okno terminala
    # Uruchom testy aby wywołać problem
    npm test -- --grep "authentication" --repeat 100
    # Przekaż logi do AI
    @debug.log "Przeanalizuj te logi i zidentyfikuj przyczynę źródłową
    sporadycznych błędów"
  4. AI identyfikuje przyczynę źródłową

    Analiza: Walidacja tokenu zawodzi gdy:
    1. Żądanie trwa >5s (token wygasa podczas walidacji)
    2. Dryft zegara systemowego między usługami
    3. Warunek wyścigu przy odświeżaniu przed wygaśnięciem
    Rozwiązanie: Wdrożyć tolerancję przesunięcia zegara i wyprzedzające odświeżanie

Debuguj problemy produkcyjne bez psowania rzeczy.

// Przekaż błąd produkcyjny do AI
"Błąd produkcyjny z Sentry:
TypeError: Cannot read property 'id' of undefined
at UserService.processOrder (/app/services/user.js:145:23)
at async OrderController.create (/app/controllers/order.js:67:18)
at async /app/middleware/errorHandler.js:12:5
Przeanalizuj i podaj poprawkę, która bezpiecznie obsługuje ten przypadek brzegowy"
// Odpowiedź AI z defensywną poprawką
class UserService {
async processOrder(userId, orderData) {
// Dodaj defensywne sprawdzenia
if (!userId) {
throw new ValidationError('ID użytkownika wymagane do przetworzenia zamówienia');
}
const user = await this.getUser(userId);
if (!user) {
throw new NotFoundError(`Użytkownik ${userId} nie znaleziony`);
}
// Bezpieczny dostęp do właściwości
const customerId = user?.stripeCustomer?.id;
if (!customerId) {
// Obsłuż brakującego klienta Stripe z gracją
logger.warn('User missing Stripe customer', { userId });
const customer = await this.createStripeCustomer(user);
user.stripeCustomer = customer;
}
// Kontynuuj przetwarzanie zamówienia
return this.createOrder(user, orderData);
}
}

Identyfikuj i napraw błędy związane z czasem.

// Opisz objawy
"Użytkownicy zgłaszają podwójne obciążenia przy szybkim klikaniu submit.
Zdarza się ~5% czasu pod obciążeniem"
// AI tworzy test warunków wyścigu
describe('Warunki wyścigu przetwarzania płatności', () => {
it('powinien obsłużyć jednoczesne przesłania', async () => {
const userId = 'test-user';
const paymentData = { amount: 100, currency: 'USD' };
// Symuluj szybkie kliknięcia
const promises = Array(5).fill(null).map(() =>
processPayment(userId, paymentData)
);
const results = await Promise.allSettled(promises);
// Tylko jedno powinno się udać
const successful = results.filter(r => r.status === 'fulfilled');
expect(successful).toHaveLength(1);
// Pozostałe powinny być odrzucone z błędem idempotentności
const rejected = results.filter(r => r.status === 'rejected');
expect(rejected).toHaveLength(4);
rejected.forEach(r => {
expect(r.reason.message).toContain('Payment already processing');
});
});
});
// AI sugeruje rozwiązanie idempotentności
class PaymentService {
constructor() {
this.processingPayments = new Map();
}
async processPayment(userId, paymentData) {
const idempotencyKey = `${userId}-${Date.now()}`;
// Sprawdź czy już przetwarza
if (this.processingPayments.has(userId)) {
throw new ConflictError('Płatność jest już przetwarzana');
}
// Oznacz jako przetwarzana
this.processingPayments.set(userId, idempotencyKey);
try {
// Przetwórz płatność
const result = await this.chargeCard(paymentData);
return result;
} finally {
// Zawsze wyczyść
this.processingPayments.delete(userId);
}
}
}

Analiza wydajności wspomagana AI

// Profiluj wolny endpoint
"POST /api/reports/generate zajmuje średnio 45s.
Sprofiluj i zoptymalizuj ten endpoint"
// AI dodaje szczegółowe pomiary czasu
async function generateReport(params) {
const metrics = new PerformanceMetrics('report-generation');
try {
// Zmierz każdą fazę
metrics.start('data-fetch');
const data = await fetchReportData(params);
metrics.end('data-fetch');
metrics.start('processing');
const processed = await processData(data);
metrics.end('processing');
metrics.start('rendering');
const report = await renderReport(processed);
metrics.end('rendering');
// Zaloguj podział wydajności
console.log('Podział wydajności:', metrics.getSummary());
return report;
} catch (error) {
metrics.recordError(error);
throw error;
}
}
// AI identyfikuje wąskie gardło
"Analiza:
- Pobieranie danych: 2s (OK)
- Przetwarzanie: 40s (PROBLEM - zapytania N+1)
- Renderowanie: 3s (OK)
Rozwiązanie: Przetwarzaj zapytania bazy danych w partiach w processData()"

Debuguj problemy obejmujące wiele usług.

  1. Śledź przepływ żądań

    // Dodaj ID korelacji
    "Dodaj rozproszone śledzenie aby śledzić przepływ żądań:
    FrontendAPI GatewayUser ServicePayment ServiceDatabase"
  2. Skoreluj logi

    Okno terminala
    # Zbierz logi ze wszystkich usług
    kubectl logs -l app=user-service --since=1h > user.log
    kubectl logs -l app=payment-service --since=1h > payment.log
    # AI koreluje przez ID żądania
    claude "Skoreluj te logi przez requestId i śledź
    nieudany przepływ płatności dla request-id: abc-123"
  3. Zidentyfikuj problemy usług

    Timeline dla żądania abc-123:
    - 10:15:23.100 - Frontend: Płatność zainicjowana
    - 10:15:23.150 - API Gateway: Żądanie otrzymane
    - 10:15:23.200 - User Service: Użytkownik zwalidowany
    - 10:15:23.250 - Payment Service: Rozpoczęto przetwarzanie
    - 10:15:28.250 - Payment Service: Timeout czekania na DB
    - 10:15:28.300 - Wszystkie usługi: Kaskadowy błąd
    Przyczyna źródłowa: Pula połączeń bazy danych wyczerpana

Dla błędów, które znikają gdy próbujesz je obserwować.

// Nieinwazyjne debugowanie
"Dodaj minimalne logowanie, które nie zmieni zachowania czasowego
dla tego warunku wyścigu w obsłudze WebSocket"
// AI sugeruje asynchroniczne logowanie
class AsyncDebugger {
constructor() {
this.buffer = [];
this.flushInterval = setInterval(() => this.flush(), 1000);
}
log(message, data) {
// Nieblokujący push do bufora
this.buffer.push({
timestamp: process.hrtime.bigint(),
message,
data: JSON.stringify(data)
});
}
flush() {
if (this.buffer.length === 0) return;
// Asynchroniczny zapis aby uniknąć blokowania
const logs = this.buffer.splice(0);
process.nextTick(() => {
logs.forEach(log => console.log(log));
});
}
}

Systematycznie wyśledź wycieki pamięci.

// Przepływ wykrywania wycieków pamięci
"Pomóż mi znaleźć wycieki pamięci w naszej aplikacji Express.
Pamięć rośnie o 100MB/godzinę"
// AI tworzy konfigurację profilowania pamięci
class MemoryProfiler {
constructor() {
this.baseline = process.memoryUsage();
this.snapshots = [];
}
captureSnapshot(label) {
const current = process.memoryUsage();
const diff = {
heapUsed: current.heapUsed - this.baseline.heapUsed,
external: current.external - this.baseline.external,
arrayBuffers: current.arrayBuffers - this.baseline.arrayBuffers
};
this.snapshots.push({
label,
timestamp: Date.now(),
memory: current,
diff
});
// Ostrzeż o podejrzanym wzroście
if (diff.heapUsed > 50 * 1024 * 1024) { // 50MB
console.warn('Podejrzenie wycieku pamięci:', {
label,
growth: `${Math.round(diff.heapUsed / 1024 / 1024)}MB`
});
}
}
findLeaks() {
// Analizuj wzorce wzrostu
const growth = this.snapshots.map((s, i) => {
if (i === 0) return null;
return {
label: s.label,
heapGrowth: s.memory.heapUsed - this.snapshots[i-1].memory.heapUsed
};
}).filter(Boolean);
return growth.filter(g => g.heapGrowth > 10 * 1024 * 1024);
}
}

Najpierw odtwórz

Zawsze stwórz minimalne odtworzenie przed naprawianiem

Testuj poprawkę

Napisz test, który zawodzi bez poprawki, przechodzi z nią

Dokumentuj odkrycia

Twórz przewodniki dla podobnych problemów w przyszłości

Monitoruj nawrót

Dodaj alerty aby złapać jeśli problem powróci

  • Czy mogę odtworzyć problem?
  • Czy mam kompletne komunikaty błędów?
  • Czy sprawdziłem ostatnie zmiany?
  • Czy moje środowisko jest poprawne?
  • Czy mam niezbędne logi?
  • Dodaj strategiczne logowanie
  • Sformułuj hipotezy
  • Testuj systematycznie
  • Zidentyfikuj przyczynę źródłową
  • Wdróż poprawkę
  • Zweryfikuj brak regresji
  • Dodano test aby zapobiec regresji
  • Udokumentowano problem i poprawkę
  • Dodano monitorowanie/alerty
  • Podzielono się wiedzą z zespołem
  • Zaktualizowano przewodniki
.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug z pomocą AI",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/app.js",
"env": {
"DEBUG": "*",
"LOG_LEVEL": "trace"
},
"outputCapture": "std",
"skipFiles": ["<node_internals>/**"]
}
]
}
// Sentry + debugowanie AI
Sentry.init({
beforeSend(event, hint) {
if (event.level === 'error') {
// Wyślij złożone błędy do AI na analizę
analyzeWithAI({
error: event,
context: hint.originalException,
breadcrumbs: hint.breadcrumbs
});
}
return event;
}
});

Opanuj debugowanie z: