Datadog Visualization Dashboard

Datadog Visualization Dashboard

Live Metrics Overview

Monitor your key metrics. Values can be edited directly on the dashboard or configured in the Data Configuration tab.

${metric.description}

`; if (metric.type === 'gauge') { valueContent = `${metric.value}${metric.unit}`; } else if (metric.type === 'status') { const statusClass = `status-${metric.status.toLowerCase().replace(/\s/g, '-')}`; valueContent = `${metric.status}`; } else if (metric.type === 'bar') { // For bar type, list the values in a simple table or list format let barHtml = '
'; for (const key in metric.barValues) { barHtml += `
${key}: ${metric.barValues[key]}%
`; } barHtml += '
'; valueContent = barHtml; } else if (metric.type === 'line') { // For line type, just display the current value and unit valueContent = `${metric.value}${metric.unit}`; // Could add a simple trend indicator if desired // valueContent += `↑`; // Example up arrow } metricCard.innerHTML = `

${metric.name}

${valueContent}
${descriptionContent} `; dashboardContentContainer.appendChild(metricCard); }); // Attach event listeners for editable cells on the dashboard dashboardContentContainer.querySelectorAll('.editable-cell').forEach(cell => { cell.addEventListener('blur', function() { // Update the underlying data when an editable cell is blurred const metricId = this.id.split('-')[1]; // e.g., 'cpu_utilization' from 'value-cpu_utilization' const metricIndex = dashboardMetrics.findIndex(m => m.id === metricId); if (metricIndex !== -1) { if (this.id.startsWith('value-')) { dashboardMetrics[metricIndex].value = parseFloat(this.innerText) || 0; } else if (this.id.startsWith('status-')) { dashboardMetrics[metricIndex].status = this.innerText; } else if (this.id.startsWith('bar-value-')) { const category = this.id.split('-')[3]; // e.g., 'Web' from 'bar-value-app_error_rate-Web' dashboardMetrics[metricIndex].barValues[category] = parseFloat(this.innerText) || 0; } // Re-render config to reflect changes if config tab is open if (currentTab === 'dataConfig') { renderConfigMetrics(); } } }); }); } /** * Renders the data configuration input fields based on dashboardMetrics. */ function renderConfigMetrics() { configMetricsContainer.innerHTML = ''; // Clear existing config fields dashboardMetrics.forEach((metric, index) => { const metricConfigDiv = document.createElement('div'); metricConfigDiv.className = 'bg-blue-50 p-4 rounded-lg shadow-sm'; metricConfigDiv.innerHTML = `

Metric ${index + 1}: ${metric.name}

`; configMetricsContainer.appendChild(metricConfigDiv); // Call toggleMetricInputs to render initial specific inputs window.toggleMetricInputs(index); }); } /** * Toggles visibility of input fields based on metric type in config. * @param {number} index - The index of the metric in dashboardMetrics. */ window.toggleMetricInputs = function(index) { const typeSelect = document.getElementById(`configType${index}`); const specificInputsDiv = document.getElementById(`metricSpecificInputs${index}`); const currentMetric = dashboardMetrics[index]; if (!typeSelect || !specificInputsDiv || !currentMetric) return; const selectedType = typeSelect.value; let inputsHtml = ''; if (selectedType === 'gauge' || selectedType === 'line') { inputsHtml = `
`; } else if (selectedType === 'status') { inputsHtml = `
`; } else if (selectedType === 'bar') { inputsHtml = `
`; } specificInputsDiv.innerHTML = inputsHtml; }; /** * Adds a new empty metric to the dashboardMetrics and re-renders config. */ addMetricBtn.addEventListener('click', function() { const newId = `new_metric_${Date.now()}`; dashboardMetrics.push({ id: newId, name: "New Metric", type: "gauge", value: 0, unit: "", status: "", barValues: {}, description: "Description for new metric." }); renderConfigMetrics(); }); /** * Removes a metric from dashboardMetrics and re-renders config. * @param {number} indexToRemove - The index of the metric to remove. */ window.removeMetric = function(indexToRemove) { if (dashboardMetrics.length > 1) { // Ensure at least one metric remains dashboardMetrics.splice(indexToRemove, 1); renderConfigMetrics(); } else { console.warn("Cannot remove the last metric."); } }; /** * Applies the values from the Data Configuration tab to the dashboardMetrics array * and re-renders the dashboard. */ window.applyConfiguration = function() { const newDashboardMetrics = []; for (let i = 0; i < dashboardMetrics.length; i++) { const nameInput = document.getElementById(`configName${i}`); const typeSelect = document.getElementById(`configType${i}`); const descriptionInput = document.getElementById(`configDescription${i}`); if (!nameInput || !typeSelect || !descriptionInput) { console.error(`Missing core input elements for metric ${i}.`); continue; // Skip this metric if core elements are missing } let newMetric = { id: dashboardMetrics[i].id, // Keep existing ID name: nameInput.value, type: typeSelect.value, description: descriptionInput.value, value: 0, unit: '', status: '', barValues: {} // Reset and set based on type }; if (newMetric.type === 'gauge' || newMetric.type === 'line') { const valueInput = document.getElementById(`configValue${i}`); const unitInput = document.getElementById(`configUnit${i}`); newMetric.value = parseFloat(valueInput?.value) || 0; newMetric.unit = unitInput?.value || ''; } else if (newMetric.type === 'status') { const statusSelect = document.getElementById(`configStatus${i}`); newMetric.status = statusSelect?.value || 'Operational'; } else if (newMetric.type === 'bar') { const barValuesTextarea = document.getElementById(`configBarValues${i}`); const barValues = {}; if (barValuesTextarea?.value) { barValuesTextarea.value.split(',').forEach(pair => { const [key, val] = pair.split(':'); if (key && val) { barValues[key.trim()] = parseFloat(val.trim()) || 0; } }); } newMetric.barValues = barValues; } newDashboardMetrics.push(newMetric); } dashboardMetrics = newDashboardMetrics; // Update the global data renderDashboardMetrics(); // Re-render dashboard sections openTab('dashboard'); // Switch back to dashboard }; /** * Handles the PDF download functionality. * Generates a PDF containing the dashboard content. */ window.downloadDashboardPdf = function() { const dashboardContent = document.getElementById('dashboard-content-for-pdf'); if (!dashboardContent) { console.error("Dashboard content for PDF not found."); return; } // Temporarily hide elements not needed in PDF (e.g., contenteditable borders) const editableCells = dashboardContent.querySelectorAll('.editable-cell'); editableCells.forEach(cell => { cell.style.border = 'none'; // Remove borders for PDF cell.style.backgroundColor = 'transparent'; // Remove background for PDF }); // Use html2canvas to capture the dashboard content html2canvas(dashboardContent, { scale: 2, // Increase scale for better resolution in PDF useCORS: true, // Required if images are from external sources (though not used here) logging: false // Disable logging for cleaner console }).then(canvas => { // Create a new jsPDF instance const { jsPDF } = window.jspdf; const pdf = new jsPDF('p', 'mm', 'a4'); // 'p' for portrait, 'mm' for millimeters, 'a4' size const imgData = canvas.toDataURL('image/png'); const imgWidth = 210; // A4 width in mm const pageHeight = 297; // A4 height in mm const imgHeight = (canvas.height * imgWidth) / canvas.width; let heightLeft = imgHeight; let position = 0; // Add image to PDF pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; // Add new pages if content overflows while (heightLeft >= 0) { position = heightLeft - imgHeight; pdf.addPage(); pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; } // Save the PDF pdf.save('Datadog_Visualization_Dashboard.pdf'); // Restore original styles for editable cells after PDF generation editableCells.forEach(cell => { cell.style.border = ''; // Restore default border cell.style.backgroundColor = ''; // Restore default background }); }).catch(error => { console.error("Error generating PDF:", error); }); }; // Attach event listeners downloadPdfBtn.addEventListener('click', downloadDashboardPdf); applyConfigBtn.addEventListener('click', applyConfiguration); // Initial rendering and setup renderDashboardMetrics(); renderConfigMetrics(); // Render config metrics initially to populate inputs updateNavigationButtons(); // Set initial button visibility });
Scroll to Top