Skip to main content
Glama

discover_logs

Find available log containers across Optimizely DXP environments to identify which logs exist before downloading or analyzing them. Returns container names, log types, and environment availability.

Instructions

šŸ”Ž Discover available log containers across all environments. REAL-TIME: <2s. Returns container names, log types available (http, application), and environment availability. Use this before download_logs() or analyze_logs_streaming() to understand what logs exist. Useful for multi-environment projects to find which environments have logging enabled. Optional: project. Returns container inventory.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectNameNo
projectIdNo
apiKeyNo
apiSecretNo

Implementation Reference

  • Main handler function for the 'discover_logs' tool. Discovers and classifies log containers across all DXP environments (Production, Preproduction, Integration). Uses StorageTools to list containers, matches against log patterns, generates diagnostic report with recommendations.
    static async discoverLogContainers(args: DiscoveryArgs): Promise<any> { try { OutputLogger.info('šŸ” Discovering log containers across all environments...\n'); // Resolve project configuration const resolved = ProjectTools.resolveCredentials(args); if (!resolved.success || !resolved.credentials) { return ResponseBuilder.invalidParams('Missing required project configuration'); } const projectConfig = resolved.credentials; const projectName = resolved.project ? resolved.project.name : 'Unknown'; OutputLogger.info(`šŸ“‹ Project: ${projectName}`); OutputLogger.info(`šŸ”‘ Using API key: ${projectConfig.apiKey?.substring(0, 8)}...`); // Test each environment const environments = ['Production', 'Preproduction', 'Integration']; const discoveryResults: DiscoveryResults = {}; for (const env of environments) { OutputLogger.info(`\nšŸŒ Checking ${env} environment...`); try { const envArgs = { ...projectConfig, environment: env }; if (process.env.DEBUG === 'true') { console.error(`[DISCOVER_LOGS] Calling handleListStorageContainers for ${env}`); console.error(`[DISCOVER_LOGS] Args:`, { hasApiKey: !!envArgs.apiKey, hasApiSecret: !!envArgs.apiSecret, hasProjectId: !!envArgs.projectId, environment: envArgs.environment }); } // Get all containers for this environment const containersResult = await StorageTools.handleListStorageContainers(envArgs as any); if (process.env.DEBUG === 'true') { console.error(`[DISCOVER_LOGS] Result type:`, typeof containersResult); console.error(`[DISCOVER_LOGS] Result structure:`, Object.keys(containersResult || {})); } const containers = this.extractContainerList(containersResult); if (process.env.DEBUG === 'true') { console.error(`[DISCOVER_LOGS] Extracted ${containers.length} containers from result`); } if (!containers || containers.length === 0) { OutputLogger.info(` āš ļø No containers accessible in ${env}`); discoveryResults[env] = { accessible: false, logContainers: [], otherContainers: [] }; continue; } // Identify log containers const logContainers: LogContainerInfo[] = []; const otherContainers: string[] = []; for (const container of containers) { const match = this.identifyLogContainer(container); if (match) { logContainers.push({ name: container, type: match.type, description: match.description }); } else { otherContainers.push(container); } } discoveryResults[env] = { accessible: true, totalContainers: containers.length, logContainers: logContainers, otherContainers: otherContainers }; // Display results for this environment OutputLogger.info(` āœ… Found ${containers.length} total containers`); if (logContainers.length > 0) { OutputLogger.info(` šŸ“Š Log containers (${logContainers.length}):`); for (const log of logContainers) { OutputLogger.info(` • ${log.name} (${log.description})`); } } else { OutputLogger.info(` āš ļø No log containers found!`); } if (otherContainers.length > 0) { OutputLogger.info(` šŸ“¦ ALL other containers (${otherContainers.length}):`); for (const container of otherContainers) { OutputLogger.info(` • ${container}`); } } } catch (error: any) { if (process.env.DEBUG === 'true') { console.error(`[DISCOVER_LOGS] Full error for ${env}:`, error); console.error(`[DISCOVER_LOGS] Error stack:`, error.stack); } OutputLogger.error(` āŒ Error accessing ${env}: ${error.message}`); // Provide more context in the error let errorDetail = error.message; if (error.response) { errorDetail += ` (HTTP ${error.response.statusCode || error.response.status})`; } if (error.code) { errorDetail += ` [${error.code}]`; } discoveryResults[env] = { accessible: false, error: errorDetail }; } } // Generate diagnostic report return this.generateDiagnosticReport(discoveryResults, projectName); } catch (error: any) { return ResponseBuilder.error(`Log discovery failed: ${error.message}`); } }
  • LOG_CONTAINER_PATTERNS: Comprehensive regex patterns used to identify and classify different types of log containers across DXP environments.
    static LOG_CONTAINER_PATTERNS: LogContainerPattern[] = [ // Standard DXP containers { pattern: /^appservicelogs$/, type: 'application', description: 'Application logs' }, { pattern: /^webservicelogs$/, type: 'web', description: 'Web server logs' }, { pattern: /^cloudflarelogpush$/, type: 'cloudflare', description: 'Cloudflare logs (beta)' }, // App Service Insights containers { pattern: /^insights-logs-appserviceconsolelogs$/, type: 'application', description: 'App Service console logs' }, { pattern: /^insights-logs-appservicehttplogs$/, type: 'web', description: 'App Service HTTP logs' }, { pattern: /^insights-logs-/, type: 'insights', description: 'Application Insights logs' }, // Alternative Azure containers (commonly found in Production) { pattern: /^azure-application-logs$/, type: 'application', description: 'Azure application logs' }, { pattern: /^azure-web-logs$/, type: 'web', description: 'Azure web server logs' }, { pattern: /^azure-logs-/, type: 'azure', description: 'Azure logs' }, // Application Insights containers { pattern: /applicationinsights/, type: 'appinsights', description: 'Application Insights data' }, { pattern: /appinsights/, type: 'appinsights', description: 'Application Insights data' }, // Enhanced generic log patterns { pattern: /logs?$/, type: 'generic', description: 'Generic log container' }, { pattern: /log-/, type: 'generic', description: 'Generic log container' }, { pattern: /-logs?$/, type: 'generic', description: 'Log container (suffix)' }, { pattern: /diagnostic.*logs?/i, type: 'diagnostic', description: 'Diagnostic logs' }, { pattern: /inte-.*logs?/i, type: 'integration', description: 'Integration environment logs' }, { pattern: /backup.*logs?/i, type: 'backup', description: 'Backup logs' }, { pattern: /^db-backups?-/i, type: 'database', description: 'Database backup container' } ];
  • extractContainerList: Parses container lists from various response formats (structured MCP, legacy text, JSON, markdown tables, bullet lists). Handles DXP-86 structured responses and falls back to text parsing.
    static extractContainerList(response: any): string[] { if (!response) { return []; } // DXP-86: First check for structured data (preferred method) if (typeof response === 'object' && response !== null) { const structuredResponse = response as StructuredResponse; // Check for structuredContent.data.containers (MCP protocol format) if (structuredResponse.structuredContent?.data?.containers) { if (process.env.DEBUG === 'true') { console.error('[DISCOVER_LOGS] Found containers in structuredContent.data.containers'); } return structuredResponse.structuredContent.data.containers; } // Check for direct data.containers format if (structuredResponse.data?.containers) { if (process.env.DEBUG === 'true') { console.error('[DISCOVER_LOGS] Found containers in data.containers'); } return structuredResponse.data.containers; } // Check for error response if (structuredResponse.error) { OutputLogger.info(`Error in container list response: ${structuredResponse.error}`); return []; } } // Fall back to text parsing for legacy formats let text = ''; if (typeof response === 'object' && response !== null) { const structuredResponse = response as StructuredResponse; if (structuredResponse.content && Array.isArray(structuredResponse.content) && structuredResponse.content[0]) { text = structuredResponse.content[0].text || ''; } else if (structuredResponse.result && structuredResponse.result.content && Array.isArray(structuredResponse.result.content)) { const content = structuredResponse.result.content[0]; if (content && content.text) { text = content.text; } } else { text = JSON.stringify(response); } } else if (typeof response === 'string') { text = response; } if (!text) { return []; } if (process.env.DEBUG === 'true') { console.error('[DISCOVER_LOGS] Falling back to text parsing'); } const containers: string[] = []; const lines = text.split('\n'); for (const line of lines) { if (!line.trim()) continue; // Look for numbered emoji format: "1. šŸ“¦ container-name" let match = line.match(/^\d+\.\s*šŸ“¦\s*(.+)$/); if (match) { containers.push(match[1].trim()); continue; } // Look for simple bullet format: "- container-name" or "• container-name" match = line.match(/^[\s\-•]\s*([^\s\-•].+)$/); if (match && !match[1].includes('Storage Container') && !match[1].includes('---')) { const name = match[1].trim(); if (name && !name.includes('|') && !name.includes('Environment')) { containers.push(name); } continue; } // Look for markdown table format: "| container-name |" match = line.match(/\|\s*([^|]+)\s*\|/); if (match && !match[1].includes('Storage Container') && !match[1].includes('---')) { containers.push(match[1].trim()); continue; } // Try JSON parsing if it looks like container data if (line.includes('{') || line.includes('[')) { try { const data = JSON.parse(line); if (Array.isArray(data)) { data.forEach((item: any) => { const name = item.StorageContainer || item.Name || item.ContainerName; if (name) containers.push(name); }); } else if (data.StorageContainer || data.Name || data.ContainerName) { containers.push(data.StorageContainer || data.Name || data.ContainerName); } } catch (e) { // Not JSON, continue } } } return containers.filter(Boolean); }
  • TOOL_MATRIX entry for 'discover_logs': Defines availability across hosting types, category, and description. Used for hosting-aware tool filtering and restriction messages.
    'discover_logs': { hostingTypes: ['dxp-paas', 'dxp-saas', 'self-hosted'], category: 'Storage & Downloads', description: 'Discover available log containers' },

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JaxonDigital/optimizely-dxp-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server