LogSenseAI-Powered Error Analysis — right inside VS Code
Table of Contents
Project OverviewLogSense is a VS Code extension backed by a Node.js API server that uses Google Gemini AI to instantly explain error logs and suggest fixes. Developers can:
The extension sends the log to the backend, which queries the user's chosen Gemini model (defaults to Gemini 2.5 Flash), parses the AI's response into an Explanation and a Suggested Fix, persists the analysis in MongoDB, and returns it to the extension UI — complete with syntax-highlighted code blocks and one-click apply. Key Features
Core Tech Stack
File Architecture
Detailed File ReferenceBackend (
|
| File | Role |
|---|---|
src/server.js |
Application entry point. Loads environment variables via dotenv, initializes Express with CORS and JSON parsing (1MB limit), mounts API routes at /api/v1, provides a /health endpoint, connects to MongoDB via Mongoose, and starts the HTTP server on the configured port. |
src/routes/api.js |
Route definitions. Maps POST /api/v1/analyze (with sanitizer middleware) to the analyze controller and GET /api/v1/history/:userId to the history controller. |
src/controllers/analyzeController.js |
Core analysis logic. Supports BYOK (Bring Your Own Key) — if the request includes a user-provided API key, a per-request Gemini instance is created; otherwise a cached server-side instance is used. Supports model selection — the client sends a model field in the request body (defaults to gemini-2.5-flash); model instances are cached per model name in a Map. Constructs a structured prompt forcing two-section responses (Explanation + Suggested Fix), implements retry with exponential backoff (5 attempts, 3s/6s/12s/24s delays) for 429 rate-limit errors, parses the AI response with regex, persists results to MongoDB, and returns actionable error messages for quota/model/key failures. |
src/controllers/historyController.js |
History retrieval. Returns paginated analysis records for a given userId, sorted newest-first. Accepts ?page= and ?limit= query params (limit capped at 50). Uses Promise.all for concurrent count + fetch. |
src/middlewares/sanitizer.js |
Data sanitization. Runs before the analyze controller. Applies regex patterns to redact: generic API keys (sk-...), AWS keys (AKIA...), token/password/apikey assignments, and user-identifying file paths (Windows C:\Users\, macOS /Users/, Linux /home/). Replaces with [REDACTED_*] tokens. |
src/models/LogHistory.js |
Mongoose schema. Defines the LogHistory collection with fields: userId (indexed), rawLog (max 5000 chars with setter truncation), languageContext, aiExplanation, aiSuggestedFix, and createdAt timestamp. |
.env.example |
Environment template. Documents the three required variables: MONGODB_URI, GEMINI_API_KEY, PORT. |
Extension (extension/)
| File | Role |
|---|---|
package.json |
Extension manifest. Declares four commands (logsense.start, logsense.analyzeSelection, logsense.setApiKey, logsense.removeApiKey), a context menu entry (visible when text is selected), and a keybinding (Ctrl+Shift+L / Cmd+Shift+L). Published by Rishabh-Sharma. Targets VS Code ≥ 1.85. |
src/extension.ts |
Extension host entry point. On activation, registers all four commands and tracks the last active text editor (to support Apply Fix even when the webview has focus). logsense.start opens the webview panel. logsense.analyzeSelection captures the editor selection, opens the panel, and sends the text to the webview via postMessage. logsense.setApiKey prompts for a Gemini API key via a secure input dialog and stores it in VS Code's SecretStorage (OS keychain). logsense.removeApiKey deletes the stored key. Persists the selected Gemini model in globalState and syncs it to the webview via modelStatus/setModel messages. Implements a ready handshake: the webview sends "webviewReady" on mount, and the extension responds with API key status, model selection, and any pending log text. Handles applyFix messages by replacing the editor selection (or inserting at cursor) with the AI-suggested code. Generates the webview HTML with a strict Content Security Policy (CSP) including nonce-based script loading. Resets state on panel disposal. |
tsconfig.json |
TypeScript configuration. Targets ES2020, outputs CommonJS modules to out/, enables strict mode, excludes node_modules and webview-ui. |
Webview UI (extension/webview-ui/)
| File | Role |
|---|---|
src/main.tsx |
React entry point. Renders <App /> inside <StrictMode> into the #root DOM node. |
src/App.tsx |
Root application component. Manages all state (log text, language, framework, loading, results, error, API key status, selected model). The settings panel (gear icon with green/yellow status dot) contains two sections: API Key Configuration (BYOK) and Model Selection (dropdown of 5 Gemini models: 2.5 Flash, 2.5 Pro, 2.5 Flash-Lite, 3 Flash, 3.1 Pro). On mount, sends "webviewReady" to the extension host. Listens for "setLog", "apiKeyStatus", "apiKeyValue", and "modelStatus" messages. Before each analysis call, asynchronously requests the stored API key and includes both the key and selected model in the POST body. Renders the ambient glow background, header with settings button, input area, context selectors, action buttons, status bar, error banner, and result panel. |
src/index.css |
Global design system. Defines CSS custom properties for the entire dark theme (deep space palette, glassmorphism surfaces, semantic colors, gradient system, shadows). Contains utility classes: .glass-card, .ls-input, .ls-select, .ls-btn-primary, .ls-btn-ghost, .ls-label. Defines all animations: fadeInUp, fadeIn, slideDown, dotPulse, shimmer, pulseGlow, gradientShift, spin. Includes ambient glow background, custom scrollbar, code block wrapper, and Apply Fix button styles with hover reveal and applied state. |
src/hooks/useVscode.ts |
VS Code messaging bridge. Caches the singleton acquireVsCodeApi() instance (can only be called once per session). Exports getVsCodeApi() and postMessageToExtension() for sending commands to the extension host. |
src/components/LogInputArea.tsx |
Log input component. Renders a monospace textarea with placeholder text, a terminal-style section label, and a floating Ctrl+Shift+L keyboard shortcut hint overlay. Applies glass-card input styling with focus ring. |
src/components/ContextSelectors.tsx |
Context dropdowns. Renders two <select> elements for Language (14 options: TypeScript, JavaScript, Python, Java, C#, C++, Go, Rust, Ruby, PHP, Swift, Kotlin, Dart, Shell) and Framework (15 options: None, React, Next.js, Angular, Vue.js, Express.js, Spring Boot, Django, Flask, Rails, Laravel, ASP.NET, Flutter, NestJS, FastAPI). Uses custom-styled selects with SVG chevron arrows. |
src/components/ResultPanel.tsx |
AI response renderer. Parses markdown code blocks from the AI response using a flexible regex (parseBlocks) that handles both multi-line and single-line fenced code blocks, splitting into text and code segments. Renders code blocks with react-syntax-highlighter (Prism, oneDark theme) with line numbers. Displays two sections with colored left accent borders: blue for Explanation, green for Suggested Fix. Code blocks in the Suggested Fix section include an Apply Fix button that appears on hover — clicking it sends an applyFix message to the extension host, which replaces the editor selection with the code. Includes a LoadingSkeleton component with shimmer effect and dot-pulse animation during analysis. |
vite.config.ts |
Build configuration. Uses @vitejs/plugin-react and @tailwindcss/vite. Outputs a single bundle (no code splitting) to dist/assets/ with deterministic filenames — required for webview injection where the extension reads built file names from disk. |
Installation & Setup
Prerequisites
- Node.js ≥ 18.x
- npm ≥ 9.x
- VS Code ≥ 1.85.0
- A MongoDB instance (local or MongoDB Atlas)
- A Google Gemini API key (Get one free)
1. Clone the Repository
git clone https://github.com/rishabhsharmaa/LogSense.git
cd LogSense
2. Set Up the Backend
cd backend
npm install
Create the environment file:
cp .env.example .env
Edit .env with your actual values (see Environment Variables).
Start the server:
# Production
npm start
# Development (auto-reloads on file changes)
npm run dev
The backend will connect to MongoDB and start on http://localhost:3001.
3. Build the Extension
cd ../extension
# Install extension host dependencies
npm install
# Install webview UI dependencies
cd webview-ui
npm install
# Build the React webview
npm run build
# Compile the extension TypeScript
cd ..
npm run compile
4. Run in VS Code
- Open the
extension/folder in VS Code - Press
F5to launch the Extension Development Host - In the new window, press
Ctrl+Shift+P→ type "LogSense: Open Panel"
Environment Variables
All variables are configured in backend/.env:
| Variable | Required | Default | Description |
|---|---|---|---|
MONGODB_URI |
✅ | mongodb://localhost:27017/logsense |
MongoDB connection string. Supports both local instances and Atlas SRV URIs (mongodb+srv://...). |
GEMINI_API_KEY |
❌ | — | Server-side fallback Gemini API key. Not required if all users provide their own key via BYOK. Get one from AI Studio. |
PORT |
❌ | 3001 |
Port for the Express server. The extension webview hardcodes localhost:3001 in its fetch calls — if you change this, update API_BASE in App.tsx accordingly. |
Note: With BYOK support, the
GEMINI_API_KEYenvironment variable is now optional. Users can configure their personal API key directly in VS Code viaLogSense: Set Gemini API Key. The key is stored securely in the OS keychain and sent with each analysis request.
API Reference
Base URL: http://localhost:3001/api/v1
POST /analyze
Analyzes an error log using Gemini AI.
Middleware: Sanitizer (redacts secrets and file paths from the log before processing)
Request Body:
{
"log": "Error: Main method not found in the file...",
"language": "Java",
"context": "Spring Boot",
"userId": "vscode-user",
"model": "gemini-2.5-flash",
"apiKey": "user-provided-gemini-api-key"
}
| Field | Type | Required | Description |
|---|---|---|---|
log |
string | ✅ | The error log or stack trace to analyze. Truncated to 5,000 characters before storage. |
language |
string | ✅ | Programming language for context (e.g., "TypeScript", "Python", "Java"). |
context |
string | ❌ | Framework or environment context (e.g., "React", "Django"). Passed as empty string if omitted. |
userId |
string | ❌ | User identifier for history tracking. Defaults to "anonymous". |
model |
string | ❌ | Gemini model identifier. Defaults to "gemini-2.5-flash". Supported: gemini-2.5-flash, gemini-2.5-pro, gemini-2.5-flash-lite, gemini-3-flash, gemini-3.1-pro. |
apiKey |
string | ❌ | User-provided Gemini API key (BYOK). If supplied, a per-request Gemini instance is created. If omitted, the server-side GEMINI_API_KEY from .env is used. |
Success Response 200 OK:
{
"id": "6745a1b2c3d4e5f6a7b8c9d0",
"explanation": "This error indicates that the JVM could not find the required entry point...",
"suggestedFix": "Ensure your class contains a `main` method with the signature...\n\n```java\npublic static void main(String[] args) {\n System.out.println(\"Hello\");\n}\n```"
}
Error Responses:
| Status | Error Message | Cause |
|---|---|---|
400 |
Missing required fields: 'log' and 'language' are required. |
Request body missing log or language. |
401 |
Gemini API key is missing or invalid. Please configure your API key in LogSense settings. |
No API key provided (neither BYOK nor server-side), or the key was rejected by Google. |
429 |
AI API quota exceeded. Please wait a minute and try again, or check your Gemini API billing. |
Gemini rate limit hit after 5 retry attempts with exponential backoff. |
500 |
AI model not available. Please contact the extension maintainer. |
The configured model name is invalid or deprecated. |
500 |
Failed to analyze the log. Please try again. |
Generic server/database error. |
GET /history/:userId
Retrieves paginated analysis history for a user.
Query Parameters:
| Param | Type | Default | Description |
|---|---|---|---|
page |
number | 1 |
Page number (minimum 1). |
limit |
number | 10 |
Records per page (minimum 1, maximum 50). |
Example: GET /api/v1/history/vscode-user?page=1&limit=5
Success Response 200 OK:
{
"page": 1,
"limit": 5,
"total": 12,
"totalPages": 3,
"data": [
{
"_id": "6745a1b2c3d4e5f6a7b8c9d0",
"userId": "vscode-user",
"rawLog": "Error: Main method not found...",
"languageContext": "Java / Spring Boot",
"aiExplanation": "This error indicates...",
"aiSuggestedFix": "Add a main method...",
"createdAt": "2026-04-03T19:50:58.000Z"
}
]
}
GET /health
Health check endpoint (mounted at root, not under /api/v1).
Example: GET http://localhost:3001/health
Response:
{
"status": "ok",
"uptime": 1234.567
}
Usage & Workflow
Method 1: Open the Panel Manually
- Press
Ctrl+Shift+P(orCmd+Shift+Pon macOS) - Type "LogSense: Open Panel" and select it
- Paste your error log into the textarea
- Select the Language and optionally a Framework
- Click Analyze
Method 2: Analyze from the Editor (Recommended)
- Select the error text in any editor tab
- Right-click → Choose "Analyze Error with LogSense"
- Or press
Ctrl+Shift+L(Cmd+Shift+Lon macOS)
- Or press
- The LogSense panel opens automatically with the selected text pre-filled
- Click Analyze
Method 3: Apply the Fix
- After analysis, hover over any code block in the Suggested Fix section
- Click the Apply Fix button that appears
- The code replaces your current editor selection (or inserts at cursor if nothing is selected)
Configure Your Own API Key (BYOK)
- Click the ⚙ gear icon in the LogSense panel header, or
- Run
Ctrl+Shift+P→ "LogSense: Set Gemini API Key" - Enter your Gemini API key in the secure input dialog
- The key is stored in your OS keychain and never leaves your machine
- A green status dot on the gear icon confirms the key is active
Choose a Gemini Model
- Click the ⚙ gear icon in the LogSense panel header
- Scroll to the Model Selection section (below API Key Configuration)
- Select from the dropdown:
- Gemini 2.5 Flash — Fast & balanced (default)
- Gemini 2.5 Pro — Best reasoning & coding
- Gemini 2.5 Flash-Lite — Fastest, most cost-efficient
- Gemini 3 Flash — Next-gen balanced
- Gemini 3.1 Pro — Most advanced
- Your selection persists across sessions and is sent with every analysis request
Common CLI Commands
# ─── Backend ─────────────────────────────────────────────────
cd backend
npm start # Start the production server
npm run dev # Start with auto-reload (--watch)
# ─── Extension ───────────────────────────────────────────────
cd extension
npm run compile # Compile extension TypeScript → out/
npm run watch # Watch mode for development
# ─── Webview UI ───────────────────────────────────────────────
cd extension/webview-ui
npm run dev # Start Vite dev server (for standalone preview)
npm run build # Production build → dist/
npm run lint # Run ESLint
Extension Commands
| Command | Keybinding | Context Menu | Description |
|---|---|---|---|
LogSense: Open Panel |
— | — | Opens the LogSense webview panel beside the editor. |
Analyze Error with LogSense |
Ctrl+Shift+L / Cmd+Shift+L |
✅ (when text is selected) | Captures the selected text, opens the panel, and auto-fills the input for analysis. |
LogSense: Set Gemini API Key |
— | — | Opens a secure input dialog to store your personal Gemini API key in the OS keychain. Submit an empty value to remove the key. |
LogSense: Remove API Key |
— | — | Removes the stored Gemini API key from the OS keychain and reverts to the server-side default. |
Architecture Diagram
sequenceDiagram
participant Editor as VS Code Editor
participant Ext as Extension Host
participant KS as OS Keychain
participant GS as globalState
participant WV as Webview (React)
participant API as Express Backend
participant San as Sanitizer
participant AI as Gemini AI
participant DB as MongoDB
Note over Ext,GS: Settings (persisted)
Ext->>KS: Store API key via SecretStorage
Ext->>GS: Store selected model via globalState
Editor->>Ext: User selects text + triggers command
Ext->>WV: postMessage({ command: "setLog", text })
Note over Ext,WV: Handshake: waits for "webviewReady" if panel is new
WV->>Ext: postMessage({ command: "getApiKey" })
Ext->>KS: Retrieve stored key
KS-->>Ext: API key (or empty)
Ext-->>WV: postMessage({ command: "apiKeyValue", apiKey })
WV->>API: POST /api/v1/analyze { log, language, context, model, apiKey }
API->>San: sanitizerMiddleware (redact secrets/paths)
San-->>API: Sanitized log
API->>AI: generateContent(prompt) [selected model + BYOK/server key]
Note over API,AI: Retry up to 5× with exponential backoff on 429
AI-->>API: Markdown response (## Explanation + ## Suggested Fix)
API->>API: Parse response with regex
API->>DB: LogHistory.create({ ... })
API-->>WV: { explanation, suggestedFix }
WV->>WV: parseBlocks() → render with syntax highlighting
Note over WV,Editor: Apply Fix Flow
WV->>Ext: postMessage({ command: "applyFix", text: code })
Ext->>Editor: editor.edit() → replace selection or insert at cursor
Ext->>Editor: showInformationMessage("Fix applied ✓")
Data Sanitization
Before any log reaches the AI, the sanitizer middleware automatically redacts:
| Pattern | Example Input | Redacted Output |
|---|---|---|
API Keys (sk-...) |
sk-abc123def456ghi789jkl012mno345pqr |
[REDACTED_API_KEY] |
AWS Keys (AKIA...) |
AKIA1234567890ABCDEF |
[REDACTED_AWS_KEY] |
| Tokens/Passwords | password=MyS3cretP@ss! |
password=[REDACTED] |
| Windows Paths | C:\Users\john\project\ |
[REDACTED_PATH]\ |
| macOS Paths | /Users/john/project/ |
/[REDACTED_PATH]/ |
| Linux Paths | /home/john/project/ |
/[REDACTED_PATH]/ |
License
ISC
Built with ❤️ by Rishabh Sharma using Gemini AI, Express, React, and VS Code