### Setup and Run LogAn Locally Source: https://github.com/log-analyzer/logan/blob/main/README.md Install LogAn dependencies and run the analysis locally using uv and the logan CLI. This requires Python 3 and uv to be installed. ```bash # Setup venv uv venv source .venv/bin/activate uv pip install -r requirements.txt # Run Log Analysis uv run logan analyze \ -f "examples/Linux_2k.log" \ -o "tmp/output" ``` -------------------------------- ### Install Logan with MCP Support Source: https://context7.com/log-analyzer/logan/llms.txt Installs the Logan package with MCP support using pip. ```bash uv pip install -e ".[mcp]" ``` -------------------------------- ### Install LogAn with MCP Dependencies Source: https://github.com/log-analyzer/logan/blob/main/README.md Install LogAn with additional dependencies required for the Model Context Protocol (MCP) server. This enables programmatic log analysis for AI agents. ```bash # Install with MCP dependencies uv pip install -e ".[mcp]" ``` -------------------------------- ### Start MCP Server with HTTP Transport Source: https://context7.com/log-analyzer/logan/llms.txt Starts the Logan MCP server using streamable HTTP transport for remote agent communication. ```bash logan-mcp --transport streamable-http ``` -------------------------------- ### Serve HTML Reports with `logan view` CLI Source: https://context7.com/log-analyzer/logan/llms.txt Use the `logan view` command to start a local HTTP server for viewing generated HTML reports. Specify the directory containing the reports and an optional port. ```bash # Serve reports from the output directory on default port 8000 uv run logan view -d "tmp/output" # → http://localhost:8000/tmp/output/ ``` ```bash # Serve on a custom port uv run logan view -d "tmp/output" --port 8080 # → http://localhost:8080/tmp/output/log_diagnosis/ ``` ```bash # Stop the server with Ctrl+C ``` -------------------------------- ### Run LogAn MCP Server Source: https://github.com/log-analyzer/logan/blob/main/README.md Start the LogAn MCP server. Use stdio transport for local integrations like Claude Desktop/Code, or HTTP transport for remote agents. ```bash # stdio transport (for Claude Desktop / Claude Code) logan-mcp # HTTP transport (for remote agents) logan-mcp --transport streamable-http ``` -------------------------------- ### Start MCP Server with Stdio Transport Source: https://context7.com/log-analyzer/logan/llms.txt Starts the Logan MCP server using stdio transport, suitable for local agents like Claude Desktop or Claude Code. ```bash logan-mcp ``` -------------------------------- ### Test LogAn MCP Server with Inspector Source: https://github.com/log-analyzer/logan/blob/main/README.md Use the MCP Inspector tool to test the LogAn MCP server. This command starts the inspector and connects it to the LogAn server for interactive testing. ```bash mcp dev logan/mcp/server.py ``` -------------------------------- ### Example extract_templates Response Structure Source: https://context7.com/log-analyzer/logan/llms.txt Illustrates the expected JSON response from the `extract_templates` MCP tool, including status, counts, and a list of extracted templates with their occurrences. ```json # Example response from extract_templates: { "status": "success", "total_log_lines": 2000, "templates_found": 47, "output_dir": "/home/user/.logan/runs/20250601_143055", "templates": [ { "template_id": "1", "template": "Jun <*> <*>:<*>:<*> combo sshd[<*>]: Accepted password for <*> from <*>", "occurrences": 420 }, { "template_id": "2", "template": "Jun <*> <*>:<*>:<*> combo sshd(pam_unix)[<*>]: authentication failure; logname= uid=<*>", "occurrences": 63 } # ... sorted by occurrences descending ] } ``` -------------------------------- ### Example analyze_logs Response Structure Source: https://context7.com/log-analyzer/logan/llms.txt Shows the expected JSON response structure from the `analyze_logs` MCP tool, including status, counts, golden signal distribution, and detailed results. ```json # Example structured response from analyze_logs: { "status": "success", "total_log_lines": 2000, "templates_found": 47, "golden_signal_distribution": { "information": 1820, "error": 95, "availability": 42, "latency": 30, "saturation": 8, "traffic": 5 }, "output_dir": "/home/user/.logan/runs/20250601_143022", "results": [ { "template_id": "12", "log_line": "Jun 14 15:16:02 combo sshd(pam_unix)[19939]: authentication failure; logname= ...", "golden_signal": "error", "fault_categories": "authentication", "occurrences": 63, "file_name": "/path/to/app.log" }, { "template_id": "3", "log_line": "Jun 14 15:16:01 combo sshd[19937]: Accepted password for root from <*>", "golden_signal": "information", "fault_categories": "other", "occurrences": 420, "file_name": "/path/to/app.log" } # ... sorted by occurrences descending ] } ``` -------------------------------- ### Prepare Output Directory with Utility Function Source: https://context7.com/log-analyzer/logan/llms.txt Use the `prepare_output_dir` utility to create the necessary subdirectory structure for Logan's output files. This function can optionally clean up existing directories before creation, ensuring a fresh environment for pipeline runs. ```python from logan.log_diagnosis.utils import prepare_output_dir # Create output directory structure (will raise if dir exists and clean_up=False) prepare_output_dir(output_dir="tmp/my_run", clean_up=False) # Clean and recreate the directory prepare_output_dir(output_dir="tmp/my_run", clean_up=True) # Created subdirectories: # tmp/my_run/ # log_diagnosis/ ← HTML reports # developer_debug_files/ ← debug JSON/log files # test_templates/ ← Drain3 template persistence # metrics/ ← timing/stats JSON files ``` -------------------------------- ### Get Anomaly Color Code Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/anomalies.html Returns a hex color code based on the anomaly type. Used for visualizing anomaly severity. ```javascript function getAnomalyColor(anomalyType) { switch (anomalyType) { case 'latency': return '#ec7a08'; case 'error': return '#c9190b'; case 'availability': return '#004b95'; case 'saturation': return '#6a4f9c'; case 'traffic': return '#3e8635'; default: return ''; } } ``` -------------------------------- ### Run LogAn via Container (Podman/Docker) Source: https://context7.com/log-analyzer/logan/llms.txt Execute the LogAn analysis pipeline within a container by mounting host directories for input logs and output reports. Configure analysis parameters using environment variables. ```bash # Basic usage — mount input and output directories mkdir -p ./tmp/output podman run --rm \ -v ./examples/:/data/input/:z \ -v ./tmp/output/:/data/output/:z \ -e LOGAN_INPUT_FILES="/data/input/Linux_2k.log" \ -e LOGAN_OUTPUT_DIR=/data/output/ \ ghcr.io/log-analyzer/logan:latest ``` ```bash # Use BART model and analyze only the last week of logs podman run --rm \ -v ./logs/:/data/input/:z \ -v ./output/:/data/output/:z \ -e LOGAN_INPUT_FILES="/data/input/" \ -e LOGAN_OUTPUT_DIR=/data/output/ \ -e LOGAN_TIME_RANGE=1-week \ -e LOGAN_MODEL=bart \ -e LOGAN_PROCESS_LOG_FILES=true \ -e LOGAN_PROCESS_TXT_FILES=false \ ghcr.io/log-analyzer/logan:latest ``` ```bash # Use a custom model in a container podman run --rm \ -v ./examples/tutorials:/data/extra/:z \ -v ./examples/:/data/input/:z \ -v ./tmp/output/:/data/output/:z \ -e LOGAN_INPUT_FILES="/data/input/Linux_2k.log" \ -e LOGAN_OUTPUT_DIR=/data/output/ \ -e LOGAN_MODEL_TYPE=custom \ -e LOGAN_MODEL="/data/extra/custom_model.py:GLiNERModel" \ ghcr.io/log-analyzer/logan:latest ``` -------------------------------- ### Get Golden Signal Color Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/summary_golden_signal_error.html Retrieves a color for a given golden signal. Uses a predefined map for known signals and cycles through an extra palette for unknown signals. ```javascript var KNOWN_GS_COLORS = { error: '#c9190b', latency: '#ec7a08', saturation: '#6a4f9c', traffic: '#004b95', availability: '#3e8635', information: '#6a6e73' }; var EXTRA_PALETTE = [ '#009596', '#a2d9d9', '#f4c145', '#b8860b', '#8b008b', '#2e8b57', '#cd5c5c', '#4682b4', '#da70d6', '#20b2aa', '#ff6347', '#708090' ]; function getSignalColor(sig, extraIdx) { var key = sig.toLowerCase(); if (KNOWN_GS_COLORS[key]) return KNOWN_GS_COLORS[key]; return EXTRA_PALETTE[extraIdx % EXTRA_PALETTE.length]; } ``` -------------------------------- ### Analyze Logs using MCP Client Tool Source: https://context7.com/log-analyzer/logan/llms.txt Demonstrates how to call the `analyze_logs` MCP tool via a Python client, specifying various parameters for log analysis. ```python # Equivalent Python call via MCP client — analyze_logs tool # The tool accepts these parameters: { "files": ["/path/to/app.log", "/path/to/system.log"], "output_dir": "", # defaults to ~/.logan/runs/ "time_range": "1-day", # all-data | 1-day | 1-week | 1-month "model_type": "zero_shot", # zero_shot | custom "model": "crossencoder", # crossencoder | bart | HuggingFace model name "debug_mode": True, "process_log_files": True, "process_txt_files": False, "clean_up": False } ``` -------------------------------- ### Run LogAn Container Image Source: https://github.com/log-analyzer/logan/blob/main/README.md Use this command to run the LogAn container image, mounting local directories for input and output. Ensure the output directory is created beforehand. ```bash mkdir -p ./tmp/output podman run --rm \ -v ./examples/:/data/input/:z \ -v ./tmp/output/:/data/output/:z \ -e LOGAN_INPUT_FILES="/data/input/Linux_2k.log" \ -e LOGAN_OUTPUT_DIR=/data/output/ \ ghcr.io/log-analyzer/logan:latest ``` -------------------------------- ### Configure Claude Desktop for LogAn MCP Source: https://github.com/log-analyzer/logan/blob/main/README.md Add LogAn as an MCP server to your Claude Desktop configuration file. This allows Claude Desktop to interact with the LogAn analysis capabilities. ```json { "mcpServers": { "logan": { "command": "logan-mcp" } } } ``` -------------------------------- ### Initialize Log Diagnosis Summary View Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/summary_golden_signal_error.html This JavaScript code initializes the summary view by loading tables and charts, and setting up event listeners for user interactions like custom filtering and golden signal filtering. ```javascript document.addEventListener('DOMContentLoaded', function() { loadSummaryTable(); loadTimelineChart(); const customFilter = document.getElementById('customFilter'); if (customFilter) customFilter.addEventListener('change', applyCustomFilter); const goldenSignalFilter = document.getElementById('goldenSignalFilter'); if (goldenSignalFilter) goldenSignalFilter.addEventListener('change', applyGoldenSignalFilter); }); ``` -------------------------------- ### ModelManager Usage Source: https://context7.com/log-analyzer/logan/llms.txt Demonstrates how to use the ModelManager to load and utilize custom models, either by specifying the model path or by providing a pre-instantiated model object. ```APIDOC ## Python API: ModelManager ### Description Manages the loading and utilization of custom machine learning models within the Logan framework. It supports loading models from specified paths or using pre-instantiated model objects. ### Usage #### Loading a custom model from a path: ```python from logan.log_diagnosis.models import ModelManager, ModelType manager = ModelManager( type=ModelType.CUSTOM, model="my_model.py:MyHuggingFaceModel" ) ``` #### Using a pre-instantiated model: ```python from my_model import MyHuggingFaceModel # Assuming MyHuggingFaceModel is defined elsewhere instance = MyHuggingFaceModel() manager = ModelManager( type=ModelType.CUSTOM, custom_model_instance=instance ) ``` ### Example Usage with a Model Instance: ```python # Assuming 'manager' is an initialized ModelManager instance with a custom model # For example: # instance = MyHuggingFaceModel() # manager = ModelManager(type=ModelType.CUSTOM, custom_model_instance=instance) # Use the model for classification results = manager.classify_golden_signal(["disk I/O error on /dev/sda"], batch_size=8) print(results) ``` ``` -------------------------------- ### Analyze Logs with `logan analyze` CLI Source: https://context7.com/log-analyzer/logan/llms.txt Use the `logan analyze` command to run the full log analysis pipeline. Specify input files or directories, output directory, and optional parameters like time range, file types, and models. ```bash # Analyze a single log file with default settings (crossencoder model, all-data time range) uv run logan analyze \ -f "examples/Linux_2k.log" \ -o "tmp/output" ``` ```bash # Analyze a directory, processing both .log and .txt files, last 24 hours only uv run logan analyze \ -f "/var/log/myapp/" \ -o "./results" \ --time-range 1-day \ --process-txt-files ``` ```bash # Use a glob pattern to match multiple log files uv run logan analyze \ -g "/var/log/*.log" \ -o "./results" ``` ```bash # Use the BART model instead of CrossEncoder and clean the output dir first uv run logan analyze \ -f "examples/Linux_2k.log" \ -o "tmp/output" \ --model bart \ --clean-up ``` ```bash # Use a custom model from an external script (see Custom Model section) uv run logan analyze \ -f "examples/Linux_2k.log" \ -o "tmp/debug" \ --model-type custom \ --model "examples/tutorials/custom_model.py:GLiNERModel" \ --clean-up ``` ```bash # Expected output directory structure: tmp/output/ log_diagnosis/ anomalies.html ← Diagnosis Report (chronological anomaly windows) summary.html ← Summary Report (template table with golden signals) developer_debug_files/ temp_id_to_signal_map.json processed_logs.csv ignored_files.log processed_files.log metrics/ preprocessing.json drain.json anomaly.json ``` -------------------------------- ### Build Timeline Chart Datasets Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/summary_golden_signal_error.html Prepares datasets for the timeline chart. Applies logarithmic scaling to data if 'scaled' is true, otherwise uses raw values. Assigns colors to signals. ```javascript function buildTimelineDatasets(data, scaled) { var signals = data.signals || []; var extraIdx = 0; return signals.map(function(sig) { var color = getSignalColor(sig, extraIdx); if (!KNOWN_GS_COLORS[sig.toLowerCase()]) extraIdx++; return { label: sig.charAt(0).toUpperCase() + sig.slice(1), data: data.bins.map(function(b) { var val = b[sig] || 0; if (!scaled || val === 0) return val; return Math.round(Math.log10(val + 1) * 100) / 100; }), rawData: data.bins.map(function(b) { return b[sig] || 0; }), backgroundColor: color, borderWidth: 0 }; }); } ``` -------------------------------- ### Collapse Logs to Initial View Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/anomalies.html Handles the 'Show Less Logs' button click. It reconstructs the HTML to display only the first 5 log entries and appends the 'Show More Logs' button. It also updates the displayed log count. ```javascript $('#resultTable').on('click', '.less-logs', function() { const scrollableDiv = this.parentElement; const logContents = scrollableDiv.querySelectorAll('.log-content'); let newHTML = ''; for (let i = 0; i < 5 && i < logContents.length; i++) { newHTML += logContents[i].outerHTML + '
'; } newHTML += ''; scrollableDiv.innerHTML = newHTML; let logNumDiv = scrollableDiv.parentElement.previousSibling.getElementsByClassName('log-num')[0]; if (logNumDiv) logNumDiv.innerHTML = '#logs displayed: 5'; }); ``` -------------------------------- ### Load More Logs and Initialize DataTable Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/anomalies.html Handles the 'Show More Logs' button click. It dynamically loads necessary scripts (jQuery, DataTables, SearchHighlight) if not already present, then calls `loadData` to fetch logs and initializes or reinitializes a DataTable with specific configurations including search highlighting. ```javascript $('#resultTable').on('click', '.more-logs', async function() { const scrollableDiv = this.parentElement; const checkboxes = scrollableDiv.closest('tr').querySelectorAll('td:nth-child(3) input[type="checkbox"]'); const uniqueFlag = checkboxes[0].checked; const gsFlag = checkboxes[1].checked; document.getElementById('loading-popup').style.display = 'block'; if (!window.jQuery || !$.fn.dataTable || !$.fn.dataTable.SearchHighlight) { const loadScript = (src) => { return new Promise((resolve) => { const script = document.createElement('script'); script.src = src; script.onload = resolve; document.head.appendChild(script); }); }; if (!window.jQuery) { await loadScript('https://code.jquery.com/jquery-3.6.0.min.js'); } await Promise.all([ loadScript('./libs/dataTables.searchHighlight.min.js'), loadScript('./libs/jquery.highlight.js') ]); } await loadData(scrollableDiv, uniqueFlag, gsFlag, "showAll"); $('#resultTable').DataTable({ "autoWidth": false, "columns": [ { "searchable": true }, { "searchable": true }, { "searchable": true }, ], "searchHighlight": true, "ordering": false, "language": { "search": "Search in log windows", "searchPlaceholder": "Enter search keyword(s)", }, "destroy": true, "paging": false, "info": false, }); document.getElementById('loading-popup').style.display = 'none'; }); ``` -------------------------------- ### prepare_output_dir Utility Source: https://context7.com/log-analyzer/logan/llms.txt Utility function to create the necessary subdirectory structure for output files in the specified directory. It can optionally clean up existing directories. ```APIDOC ## Python API: prepare_output_dir ### Description Creates the required subdirectory structure in the output directory before running the pipeline. This function must be called prior to operations like `Preprocessing.preprocess()`, `Templatizer.miner()`, or `Anomaly.get_anomaly_report()`. ### Parameters - **output_dir** (str): The root directory where the output structure will be created. - **clean_up** (bool, optional): If True, the directory will be cleaned and recreated. If False and the directory exists, an error may be raised. Defaults to False. ### Created Subdirectories: - `log_diagnosis/`: For HTML reports. - `developer_debug_files/`: For debug JSON and log files. - `test_templates/`: For Drain3 template persistence. - `metrics/`: For timing and statistics JSON files. ### Example Usage: #### Creating the directory structure: ```python from logan.log_diagnosis.utils import prepare_output_dir # Create output directory structure (will raise if dir exists and clean_up=False) prepare_output_dir(output_dir="tmp/my_run", clean_up=False) ``` #### Cleaning and recreating the directory: ```python from logan.log_diagnosis.utils import prepare_output_dir # Clean and recreate the directory prepare_output_dir(output_dir="tmp/my_run", clean_up=True) ``` ``` -------------------------------- ### Build LogAn Container Image Source: https://github.com/log-analyzer/logan/blob/main/README.md Build the LogAn container image locally if you need to customize it. This command uses Podman to build the image from the Dockerfile. ```bash podman build -t logan -f Containerfile . ``` -------------------------------- ### JavaScript: DataTable Initialization and Row Creation Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/summary_golden_signal_error.html Initializes a DataTable with provided data and configurations, including column definitions, search highlighting, and custom row creation logic. Handles empty data states and updates statistics. Use for rendering the main log summary table. ```javascript function loadSummaryTable() { const emptyEl = document.getElementById('summaryEmpty'); const tableWrap = document.getElementById('summaryTableWrap'); const tableEl = document.getElementById('jsonTable'); if (!df || !Array.isArray(df) || df.length === 0) { if (emptyEl) emptyEl.style.display = 'block'; if (tableWrap) tableWrap.style.display = 'none'; updateStats(); return; } if (emptyEl) emptyEl.style.display = 'none'; if (tableWrap) tableWrap.style.display = 'block'; populateSelectOptions(); updateStats(); const table = new DataTable('#jsonTable', { autowidth: false, columns: [ { searchable: false, width: '5%' }, { searchable: true, width: '64%' }, { searchable: true, width: '10%' }, { searchable: false, visible: false, width: '7%' }, { searchable: false, visible: false, width: '10%' } ], searchHighlight: true, language: { search: 'Search in log lines', searchPlaceholder: 'Search' }, destroy: true, ordering: false, data: df, createdRow: function(row, data, dataIndex) { const $row = $(row); $row.addClass('pf-v5-c-table__tr'); $row.find('td').eq(0).html(dataIndex + 1).addClass('pf-v5-c-table__td'); const logLine = data[1] || ''; const logCell = $row.find('td').eq(1); logCell.addClass('log-line-cell pf-v5-c-table__td').css('text-align', 'left'); logCell.attr('template-id', data[0]); logCell.attr('data-count', data[3]); logCell.attr('data-coverage', data[4]); logCell.attr('title', data[5] || ''); if (logLine.length > LOG_TRUNCATE_LEN) { const truncated = logLine.substring(0, LOG_TRUNCATE_LEN); logCell.html(truncated); const viewFull = $(''); ``` -------------------------------- ### JavaScript: Log Preview Modal Functionality Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/summary_golden_signal_error.html Handles opening and closing a modal window for previewing full log lines. Includes event listeners for closing the modal via a button or clicking outside the content area. Use for displaying truncated log details. ```javascript function openLogPreview(fullText) { const overlay = document.getElementById('logPreviewModal'); const body = document.getElementById('logPreviewBody'); if (!overlay || !body) return; body.textContent = fullText; overlay.classList.add('is-open'); overlay.setAttribute('aria-hidden', 'false'); } function closeLogPreview() { const overlay = document.getElementById('logPreviewModal'); if (!overlay) return; overlay.classList.remove('is-open'); overlay.setAttribute('aria-hidden', 'true'); } document.getElementById('logPreviewClose').addEventListener('click', closeLogPreview); document.getElementById('logPreviewModal').addEventListener('click', function(e) { if (e.target === this) closeLogPreview(); }); ``` -------------------------------- ### Load JSON Data from File Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/anomalies.html Asynchronously fetches and loads JSON data from a specified file path. It handles loading states, displays a loading popup, and stores the fetched data in local storage. Includes error handling for fetch requests. ```javascript async function loadJsonFiles(fileIndex) { if (loading) return; loading = true; document.getElementById('loading-popup').style.display = 'block'; let fileName = "{{ output_dir }}/data_" + fileIndex + ".json"; try { const response = await fetch(fileName); const data = await response.json(); if (data) { initialLoadData(data); localStorage.setItem("fileData", JSON.stringify(data)); } } catch (error) { console.error("Error loading " + fileName + ":", error); } finally { document.getElementById('loading-popup').style.display = 'none'; loading = false; } } ``` -------------------------------- ### Cluster Log Lines into Templates with Templatizer Source: https://context7.com/log-analyzer/logan/llms.txt The `Templatizer` class applies the Drain3 algorithm to cluster log lines into templates and assigns a `test_ids` column. Requires a configuration file for Drain3 and a preprocessed DataFrame. The `miner` method generates template files and updates the DataFrame. ```python import os from logan.drain.run_drain import Templatizer from logan.log_diagnosis.utils import prepare_output_dir output_dir = "tmp/output" prepare_output_dir(output_dir, clean_up=True) drain_config_path = os.path.join( os.path.dirname(__import__("logan").__file__), "drain", "drain3.ini" ) templatizer = Templatizer( config_path=drain_config_path, debug_mode="true" # saves matcher_output_json.json debug file ) # preprocessor.df is the output from the Preprocessing step above templatizer.miner( df=preprocessor.df, output_dir=output_dir, template=os.path.join(output_dir, "test_templates", "tm-test.templates.json"), ) print(f"Templates found: {templatizer.df['test_ids'].nunique()}") print(templatizer.df[["text", "test_ids"]].head(5)) ``` -------------------------------- ### Preprocess Log Files with Logan Source: https://context7.com/log-analyzer/logan/llms.txt Use the `preprocessor.preprocess` function to extract log entries from specified files or directories. Configure time range, output directory, and file types to process. Ensure the output directory has subdirectories created by `prepare_output_dir()`. ```python preprocessor.preprocess( input_files=["examples/Linux_2k.log", "/var/log/myapp/"], time_range="1-day", # "all-data", "1-day", "2-day", ..., "1-month" output_dir="tmp/output", # must already have subdirs created by prepare_output_dir() process_all_files=False, process_log_files=True, process_txt_files=False, ) if preprocessor.df is not None and len(preprocessor.df) > 0: print(f"Extracted {len(preprocessor.df)} log entries") print(preprocessor.df.columns.tolist()) # ['file_names', 'timestamps', 'epoch', 'text', 'preprocessed_text', 'truncated_log'] print(preprocessor.df.head(3)) # file_names timestamps epoch text truncated_log # 0 examples/Linux_2k.log Jun 14 15:16:01 1718378161 Jun 14 15:16:01 combo sshd... Jun 14 15:16:01 combo sshd... else: print("No log lines could be extracted") ``` -------------------------------- ### Initialize DataTable and Load Data Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/anomalies.html Initializes a DataTable for displaying log results and sets up event listeners for pagination controls. It also defines functions to load JSON data, update the table display, and manage pagination text. ```javascript let fileIndex = 1; let loading = false; var currentPage = 1; const chunkSize = {{ chunk_size }}; const totalEntries = {{ no_of_windows }}; const noOfFiles = {{ no_of_chunks }}; dataTable = new DataTable('#resultTable', { "autoWidth": false, "columns": [ { "searchable": false }, { "searchable": true }, { "searchable": false }, ], "searchHighlight": true, "ordering": false, "language": { "search": "Search in log windows", "searchPlaceholder": "Enter search keyword(s)", }, "destroy": true, "paging": false, "info": false, }); loadJsonFiles(fileIndex); updatePaginationText(fileIndex); ``` ```javascript document.getElementById('prevPage').addEventListener('click', function() { if (currentPage > 1) { currentPage--; fileIndex--; updateTableDisplay(fileIndex); scrollToTopOfTable(); } }); document.getElementById('nextPage').addEventListener('click', function() { if (currentPage < noOfFiles) { currentPage++; fileIndex++; updateTableDisplay(fileIndex); scrollToTopOfTable(); } }); ``` ```javascript function updateTableDisplay(fileIndex) { dataTable.clear().draw(); loadJsonFiles(fileIndex); updatePaginationText(fileIndex); } ``` ```javascript function scrollToTopOfTable() { document.getElementById('resultTable').scrollIntoView(); } ``` ```javascript function updatePaginationText(fileIndex) { let cs = {{ chunk_size }}; if (fileIndex == 1) { start = 1; } else { start = cs.slice(0, fileIndex - 1).reduce((acc, curr) => acc + curr, 0) + 1; } end = start + cs[fileIndex - 1] - 1; paginationText = "Showing " + start + " to " + end + " of " + totalEntries + " entries"; document.getElementById('paginationText').textContent = paginationText; prevButton = document.getElementById('prevPage'); nextButton = document.getElementById('nextPage'); prevButton.disabled = currentPage === 1; nextButton.disabled = currentPage === noOfFiles; } ``` -------------------------------- ### View LogAn Reports Source: https://github.com/log-analyzer/logan/blob/main/README.md Serve the generated analysis reports locally using the `logan view` command. The server will be available at http://localhost:8000/log_diagnosis. ```bash uv run logan view -d "tmp/output" # server should be available at http://localhost:8000/log_diagnosis ``` -------------------------------- ### Generate Log Content and Display Logic Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/anomalies.html Handles the generation of HTML for log entries, including truncation and 'Show More'/'Show Less' functionality. It also manages the overall display logic for showing all logs or a limited set, updating the log count, and hiding a loading popup. ```javascript const shouldAddContent = (signal, templateId) => { if (uniqueFlag && gsFlag) return signal === 'gs' && !templateIdSet.has(templateId); if (!uniqueFlag && gsFlag) return signal === 'gs'; if (uniqueFlag && !gsFlag) return !templateIdSet.has(templateId); return true; }; const generateLogContent = (idx) => { const log = logs[idx]; const logTitle = files[idx]; const color = getColorForGS(gs[idx]); const logContent = log.length < 500 ? log : log.substring(0, 400) + '...'; const showMoreSpan = log.length > 500 ? 'Show More' : ''; return '
' + logContent + showMoreSpan + '

'; }; if (type === "showAll") { for (index = 0; index < itemLength; index++) { const signal = getSignal(gs[index]); const templateId = templateIds[index]; if (shouldAddContent(signal, templateId)) { if (signal === 'gs') templateIdSet.add(templateId); log_num++; logHtml += generateLogContent(index); } } logHtml += ''; } else { let noOfLogLines = 0; let showMoreLogs = false; for (index = 0; noOfLogLines < 5 && index < itemLength; index++) { const signal = getSignal(gs[index]); const templateId = templateIds[index]; if (shouldAddContent(signal, templateId)) { if (signal === 'gs') templateIdSet.add(templateId); log_num++; logHtml += generateLogContent(index); noOfLogLines++; } } for (; index < itemLength; index++) { const signal = getSignal(gs[index]); const templateId = templateIds[index]; if (shouldAddContent(signal, templateId)) { showMoreLogs = true; break; } } if (showMoreLogs) logHtml += ''; } scrollableDiv.innerHTML = logHtml; let logNumDiv = scrollableDiv.parentElement.previousSibling.getElementsByClassName('log-num')[0]; if (logNumDiv) logNumDiv.innerHTML = '#logs displayed: ' + log_num; document.getElementById('loading-popup').style.display = 'none'; ``` -------------------------------- ### Initialize Logan Preprocessing Class Source: https://context7.com/log-analyzer/logan/llms.txt Initializes the `Preprocessing` class from the Logan Python API. Set `debug_mode='true'` to save intermediate debug files. ```python from logan.preprocessing.preprocessing import Preprocessing # Initialize preprocessor (debug_mode="true" saves intermediate debug files) preprocessor = Preprocessing(debug_mode="true") ``` -------------------------------- ### Initialize and Control Popup Window Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/popup.html This script initializes a popup window, making it appear on page load and allowing it to be closed by clicking a close button or outside the popup area. Ensure the HTML has elements with IDs 'popup' and 'close-popup'. ```javascript (function() { const popup = document.getElementById('popup'); const closeBtn = document.getElementById('close-popup'); if (!popup || !closeBtn) return; function openModal() { popup.classList.add('is-open'); } function closeModal() { popup.classList.remove('is-open'); } window.addEventListener('load', openModal); closeBtn.addEventListener('click', closeModal); popup.addEventListener('click', function(e) { if (e.target === popup) closeModal(); }); })(); ``` -------------------------------- ### CSS for Spinner and Tooltip Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/causality.html Styles for a loading spinner, graph node tooltips, and table visibility. The spinner uses CSS animations for visual feedback during loading operations. ```css #causalButtonWrapper { display: inline-block; /* Ensures the container only takes as much width as necessary */ position: relative; /* Allows positioning of child elements */ } /* Add CSS styles for the spinner */ .spinner { width: 24px; /* Adjust the width to match the button size */ height: 24px; /* Adjust the height to match the button size */ border: 3px solid #ccc; border-top: 3px solid #3498db; border-radius: 50%; animation: spin 2s linear infinite; display: inline-block; vertical-align: middle; margin-left: 10px; /* Add some margin to separate it from the button */ display: none; /* Hide the spinner by default */ } /* Add a spinning animation */ @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .spinner-icon { border: 4px solid rgba(0, 0, 0, 0.3); border-top: 4px solid #3498db; border-radius: 50%; width: 50px; height: 50px; animation: spin 2s linear infinite; } #tooltip { position: absolute; background-color: rgba(0, 0, 0, 0.8); color: white; padding: 5px; border-radius: 5px; pointer-events: none; font-size: 12px; } .hidden { display: none; } #jsonTable { display: none; width: 100%; border-collapse: collapse; } #jsonTable th, #jsonTable td { border: 1px solid #ddd; padding: 8px; text-align: center; } #jsonTable th { background-color: #f2f2f2; } select { width: 100%; padding: 5px; } #container { text-align: center; margin-top: 20px; } table { width: 100%; border-collapse: collapse; margin-top: 20px; border: 1px solid #ddd; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; } th { background-color: #f2f2f2; } td { background-color: #fff; } select { padding: 6px; } /* Additional styles for dropdown */ select { background-color: #f2f2f2; border: 1px solid #ccc; border-radius: 4px; } select:hover { background-color: #e0e0e0; } /* Adjust column widths */ th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; /* Add width to Golden Signal column */ max-width: 200px; /* Adjust as needed */ } /* Enable text wrapping */ td { background-color: #fff; /* Add word wrap and break word properties */ word-wrap: break-word; word-break: break-all; } /* Center-align the input elements */ #inputContainer { text-align: center; margin-top: 20px; } .rounded-border { border: 0.1in solid gray; /* 1-inch thick border */ border-radius: 25px; /* Half of 1 inch to make rounded corners */ } canvas { display: inline; margin: 50px; } ``` -------------------------------- ### MyHuggingFaceModel Source: https://context7.com/log-analyzer/logan/llms.txt Custom model implementation using HuggingFace pipelines for log analysis. It includes methods for classifying golden signals and fault categories. ```APIDOC ## Class: MyHuggingFaceModel ### Description Custom model using any HuggingFace pipeline. This class extends `ModelTemplate` and provides methods for classifying log data. ### Methods #### `init_model()` Loads the HuggingFace pipeline for zero-shot classification. This method is called automatically by `ModelManager`. #### `classify_golden_signal(input: list[str], batch_size: int = 32) -> list[dict]` Classifies log entries into predefined golden signal categories. Returns a list of dictionaries, each containing predicted labels and their scores. - **input** (list[str]): A list of log entries to classify. - **batch_size** (int, optional): The number of entries to process in each batch. Defaults to 32. Returns: - list[dict]: A list where each dictionary contains 'labels' and 'scores' for the classification. #### `classify_fault_category(input: list[str], batch_size: int = 32) -> list[dict]` Classifies log entries into fault categories using multi-label classification. Returns a list of dictionaries with labels and scores, filtering for high confidence predictions. - **input** (list[str]): A list of log entries to classify. - **batch_size** (int, optional): The number of entries to process in each batch. Defaults to 32. Returns: - list[dict]: A list where each dictionary contains 'labels' and 'scores' for the fault category classification. ``` -------------------------------- ### Causality and Temporal Data Initialization Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/causality.html These functions are responsible for initializing the causality graph and fetching/rendering temporal evolution data. They are typically called on page load. ```javascript function runCausality(){ nodes_arr = {{ graph_nodes }} edges_arr = {{ graph_edges }} show_graph(nodes_arr, edges_arr) } function fetchTemporalData() { temporal_evolution_json = {{ temporal_evolution }} createBarGraph(temporal_evolution_json['data']); } document.addEventListener("DOMContentLoaded", function () { // Call runCausality function when the DOM is ready runCausality(); fetchTemporalData(); }); ``` -------------------------------- ### Process and Display Initial Log Data Source: https://github.com/log-analyzer/logan/blob/main/logan/log_diagnosis/templates/anomalies.html Processes raw log data, formats it for display in a DataTable, and handles the display of log content, including truncated logs and 'show more' options. It also prepares data for unique log line and log with GS checkboxes. ```javascript function initialLoadData(data) { const rows = []; for (let i = 0; i < data.length; i++) { let item = data[i]; let noOfLogLines = 0; let itemLength = item.logs.length; let templateIdSet = new Set(); let logDivs = ""; let showMoreLogs = false; let index = 0; let templateId; for (index; noOfLogLines < 5 && index < itemLength; index++) { let log = item.logs[index]; let gs = item.gs[index]; templateId = item.templateIds[index]; const color = getColorForGS(gs); const signal = getSignal(gs); const logTitle = item.files[index]; const logContent = log.length < 500 ? log : log.substring(0, 400) + '...'; if (signal === 'gs' && !templateIdSet.has(templateId)) { templateIdSet.add(templateId); noOfLogLines++; logDivs += '
' + logContent + (log.length < 500 ? '' : 'Show More') + '

'; } } for (index; index < itemLength; index++) { let gs = item.gs[index]; let templateId = item.templateIds[index]; let signal = ['latency', 'error', 'availability', 'saturation', 'traffic'].includes(gs) ? 'gs' : 'non_gs'; if (signal === 'gs' && !templateIdSet.has(templateId)) { showMoreLogs = true; break; } } if (showMoreLogs) { logDivs += ''; } rows.push([ item.duration + '
#logs displayed: 5
', '
' + logDivs + '
', ' Unique LL
LL with GS' ]); } dataTable.rows.add(rows).draw(); document.getElementById('loading-popup').style.display = 'none'; } ``` -------------------------------- ### Register and Use Custom Models with ModelRegistry Source: https://context7.com/log-analyzer/logan/llms.txt Dynamically register, retrieve, and instantiate custom model classes from external Python scripts using their file path and class name. This allows for flexible model management and usage within the Logan framework. ```python from logan.log_diagnosis.models.manager import ModelRegistry # Register a model class from an external script ModelRegistry.register_from_path( "my_bert_model", "/home/user/models/bert_classifier.py:BertClassifier" ) # Check registered models print(ModelRegistry.list_registered()) # ['my_bert_model'] print(ModelRegistry.is_registered("my_bert_model")) # True # Retrieve the class and instantiate it ModelCls = ModelRegistry.get("my_bert_model") model_instance = ModelCls(threshold=0.5) model_instance.init_model() # Use directly gs = model_instance.classify_golden_signal(["disk I/O error on /dev/sda"], batch_size=8) # Unregister when done ModelRegistry.unregister("my_bert_model") ```