Skip to content

Instantly share code, notes, and snippets.

@joshfedo
Created October 31, 2024 15:24
Show Gist options
  • Save joshfedo/aa18e9e1ef7e257d9cd9f8e7efad4742 to your computer and use it in GitHub Desktop.
Save joshfedo/aa18e9e1ef7e257d9cd9f8e7efad4742 to your computer and use it in GitHub Desktop.
PHPStrom Live Plugin - Magento 2 Warden log streamer
import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.openapi.project.ProjectManager
import javax.swing.*
import java.awt.*
import java.io.*
import static liveplugin.PluginUtil.show
import static liveplugin.PluginUtil.registerToolWindow
static JPanel createPanelWithLogButtons() {
def panel = new JPanel(new BorderLayout())
def topPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5))
// Add buttons for specific logs
def specificLogs = ["system.log", "debug.log", "error.log", "exception.log"]
specificLogs.each { logFile ->
def logButton = new JButton(logFile)
logButton.setPreferredSize(new Dimension(100, 30))
logButton.addActionListener({
stopCurrentLogStream(panel)
streamLog(logFile, panel)
} as AbstractAction)
topPanel.add(logButton)
}
// "All logs" button
def allLogsButton = new JButton("All Logs")
allLogsButton.setPreferredSize(new Dimension(100, 30))
allLogsButton.addActionListener({
stopCurrentLogStream(panel)
streamLog("*.log", panel)
} as AbstractAction)
topPanel.add(allLogsButton)
// Dropdown for other logs with a placeholder
def logFilesDropdown = new JComboBox()
logFilesDropdown.setPreferredSize(new Dimension(200, 30))
logFilesDropdown.addItem("Other logs")
// Refresh button next to the dropdown
def refreshButton = new JButton("Refresh")
refreshButton.setPreferredSize(new Dimension(100, 30))
refreshButton.addActionListener({
loadAdditionalLogs(logFilesDropdown, specificLogs)
} as AbstractAction)
// Set up lazy loading of other logs on dropdown click
logFilesDropdown.addActionListener({
def selectedLog = logFilesDropdown.getSelectedItem()
if (selectedLog == "Other logs") {
loadAdditionalLogs(logFilesDropdown, specificLogs)
} else if (selectedLog && selectedLog != "Loading...") {
stopCurrentLogStream(panel)
streamLog(selectedLog.toString().trim(), panel)
}
} as AbstractAction)
// Add components to the top panel
topPanel.add(logFilesDropdown)
topPanel.add(refreshButton)
// Create a text area for log output
def logTextArea = new JTextArea(20, 50)
logTextArea.setEditable(false)
def logScrollPane = new JScrollPane(logTextArea)
panel.add(topPanel, BorderLayout.NORTH)
panel.add(logScrollPane, BorderLayout.CENTER)
panel.putClientProperty("logTextArea", logTextArea)
panel.revalidate()
return panel
}
// Load additional logs into the dropdown
static void loadAdditionalLogs(JComboBox logFilesDropdown, java.util.List<String> specificLogs) {
logFilesDropdown.removeAllItems()
logFilesDropdown.addItem("Loading...")
// Load additional logs in a new thread
new Thread({
def additionalLogs = getAvailableLogs().findAll { !specificLogs.contains(it) }
SwingUtilities.invokeLater {
logFilesDropdown.removeAllItems()
if (additionalLogs) {
additionalLogs.each { logFile -> logFilesDropdown.addItem(logFile) }
} else {
logFilesDropdown.addItem("No additional logs found")
}
}
}).start()
}
// Fetch available logs from the container's log directory
static java.util.List<String> getAvailableLogs() {
def project = ProjectManager.instance.openProjects[0]
def projectBasePath = project?.getBasePath()
def commandLine = new GeneralCommandLine("warden", "shell")
commandLine.setWorkDirectory(projectBasePath)
try {
def process = commandLine.createProcess()
def writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()))
Thread.sleep(1000) // Wait for the shell to initialize
writer.write("ls /var/www/html/var/log/*.log\n")
writer.flush()
// Read the entire line from the process output
def reader = new BufferedReader(new InputStreamReader(process.getInputStream()))
def line = reader.readLine()
if (line) {
def logs = line.split(" ").collect {
it.replace("/var/www/html/var/log/", "").trim()
}
return logs.findAll { it }
} else {
return []
}
} catch (Exception e) {
show("Error fetching logs: ${e.message}")
return []
}
}
// Stop the current log stream
static void stopCurrentLogStream(JPanel panel) {
def logTextArea = panel.getClientProperty("logTextArea")
if (logTextArea) {
logTextArea.setText("")
}
}
// Stream logs asynchronously
static void streamLog(String logFile, JPanel panel) {
def project = ProjectManager.instance.openProjects[0]
def projectBasePath = project?.getBasePath()
def shellCommand = new GeneralCommandLine("warden", "shell")
shellCommand.setWorkDirectory(projectBasePath)
try {
def process = shellCommand.createProcess()
def writer = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()))
def logTextArea = panel.getClientProperty("logTextArea")
if (!logTextArea) {
show("Log text area not found.")
return
}
// Run in a new thread
new Thread({
Thread.sleep(1000) // Wait for the shell to initialize
println("Starting to stream: ${logFile}")
writer.write("tail -f /var/www/html/var/log/${logFile}\n")
writer.flush()
// Read the output from the log file
def reader = new BufferedReader(new InputStreamReader(process.getInputStream()))
String line
while ((line = reader.readLine()) != null) {
SwingUtilities.invokeLater({
if (logTextArea.lineCount > 1000) {
logTextArea.setText("") // Clear if over limit
}
logTextArea.append(line + "\n")
logTextArea.setCaretPosition(logTextArea.getDocument().getLength())
})
}
}).start()
} catch (Exception e) {
show("Error streaming log: ${e.message}")
}
}
// Register the tool window and ensure a valid component is returned
registerToolWindow("LogViewerToolWindow", pluginDisposable) {
def panel = createPanelWithLogButtons()
if (panel != null) {
return panel
} else {
show("Failed to create a valid panel.")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment