Today, system administrators and developers often find themselves sifting through vast amounts of log data and status reports to diagnose issues. This can be a time-consuming and error-prone process. What if we could harness the power of AI to instantly analyze these reports and provide actionable insights?

In this blog post, we'll explore how to build a command-line tool in Golang that integrates with Gemini AI to analyze PHP-FPM status reports. This tool will demonstrate Golang's efficiency and Gemini AI's capability to distill complex information into clear, actionable summaries, significantly streamlining troubleshooting efforts.
The Challenge of Troubleshooting PHP-FPM
PHP-FPM (FastCGI Process Manager) is a widely used daemon for PHP applications, especially in high-traffic environments. Its status reports contain crucial information about process health, pool activity, and potential bottlenecks. However, interpreting these reports quickly, especially during an outage, requires deep expertise and keen attention to detail. This is where AI can make a significant difference.
Why Golang for This Tool?
Golang is an excellent choice for building such a utility due to several key advantages:
-
Performance: Go's compilation to machine code results in fast execution times, critical for real-time analysis tools.
-
Concurrency: Go's goroutines and channels make it easy to handle concurrent operations, though less critical for this specific tool, it's a powerful feature for related tasks (e.g., monitoring multiple servers).
-
Simplicity and Readability: Go's clear syntax and strong typing promote maintainable code.
-
Robust Standard Library: Go provides a comprehensive standard library, reducing the need for external dependencies.
-
Static Linking: Go applications can be compiled into a single binary, simplifying deployment.
Integrating Gemini AI for Intelligent Analysis
The core of our tool lies in its integration with the Gemini AI. We'll send the raw PHP-FPM status report to Gemini with a carefully crafted prompt, instructing the AI to act as a technical support engineer and provide a structured analysis.
Here's how we achieve this in Golang:
// Gemini AI integration.
ctx := context.Background()
geminiClient, err := genai.NewClient(ctx, &genai.ClientConfig{
APIKey: cf.GeminiAPIKey, // Your Gemini API Key
})
if err != nil {
log.Fatal(err)
}
modelService := geminiClient.Models
promptText := fmt.Sprintf(`
As technical support engineer, provide a concise analysis of the following PHP-FPM status report.
Structure your response into these sections, using bold headers and bullet points. Take note that the
environment is command-line only, so avoid any unnecessary explanations or verbose language:
1. Overall Status Summary: Briefly summarize the health of the server.
2. Critical Issues Identified:
- For each critical issue, state the problem clearly.
- Explain the immediate impact.
- Provide a primary, actionable recommendation.
3. Warning/Non-Critical Observations:
- List any non-critical observations.
- Suggest proactive measures.
4. Next Steps:
- A concise list of the most urgent actions.
- Include any follow-up tasks.
PHP-FPM Health Report: %s
`, body) // 'body' would contain the PHP-FPM status report
// Call GenerateContent on the modelService, specifying the model name
gemeniResponse, geminiErr := modelService.GenerateContent(ctx, "gemini-2.5-flash", genai.Text(promptText), nil)
if geminiErr != nil {
log.Fatalf("Error generating content from Gemini: %v", geminiErr)
}
In this snippet:
-
We initialize the Gemini client using our API Key.
-
We construct a detailed
promptText
. This prompt is crucial. It defines the AI's persona ("As technical support engineer"), the task ("provide a concise analysis"), and, most importantly, the desired output format. By specifying bold headers and bullet points, we guide Gemini to return a structured response. -
We send the PHP-FPM report (
body
) along with the prompt to thegemini-2.5-flash
model usingmodelService.GenerateContent
.
Formatting and Presenting the AI's Insights
Once we receive the response from Gemini, the next step is to format it for optimal readability in a command-line environment. The Golang code goes further by applying custom formatting and color-coding to highlight critical information:
// Regex to remove markdown bolding (e.g., **text**)
var boldRegex = regexp.MustCompile(`\*\*([^\*]+)\*\*`)
// Regex to match and capture the content of main section headers (e.g., "1. Overall Status Summary")
// This is now more precise to avoid matching numbered list items within "Next Steps".
var mainHeaderRegex = regexp.MustCompile(`^(\d+\.\s+.*?):?\s*$`) // Matches "N. Text" or "N. Text:" at start of line
// Regex to clean up bullet points: matches any leading whitespace, an asterisk or hyphen,
// followed by optional non-breaking spaces or regular spaces.
var bulletCleanRegex = regexp.MustCompile(`^\s*[\*\-]\s*`)
// Regex to match numbered list items (e.g., "1. Item") within "Next Steps"
var numberedListItemRegex = regexp.MustCompile(`^(\d+)\.\s*(.*)$`)
if len(gemeniResponse.Candidates) > 0 && len(gemeniResponse.Candidates[0].Content.Parts) > 0 {
fullText := ""
for _, part := range gemeniResponse.Candidates[0].Content.Parts {
if part.Text != "" {
fullText += string(part.Text)
}
}
// Apply the new formatting logic here.
lines := strings.Split(fullText, "\n")
for _, line := range lines {
// Start with the original line.
formattedLine := line
// Remove bold markdown (**text**) - do this first
formattedLine = boldRegex.ReplaceAllString(formattedLine, "$1")
// Clean up non-breaking spaces (U+00A0) that Gemini sometimes inserts.
formattedLine = strings.ReplaceAll(formattedLine, "\u00A0", " ")
trimmedLine := strings.TrimSpace(formattedLine)
// 1. Check for main section headers
// (e.g., "1. Overall Status Summary")
headerMatch := mainHeaderRegex.FindStringSubmatch(formattedLine)
if len(headerMatch) > 1 && headerMatch[1] != "" {
// Use the captured content.
formattedLine = strings.TrimSpace(headerMatch[1])
} else if numberedListItemRegex.MatchString(trimmedLine) {
// 2. Handle numbered list items (e.g., in "Next Steps")
// We want these to start from the margin,
// with a consistent space after the number.
itemMatch := numberedListItemRegex.FindStringSubmatch(trimmedLine)
if len(itemMatch) == 3 {
// Use 0-indent for the number, then 3 spaces after the period.
formattedLine = fmt.Sprintf("%s. %s", itemMatch[1], strings.TrimSpace(itemMatch[2]))
} else {
// Fallback if regex doesn't capture right.
formattedLine = trimmedLine
}
} else if bulletCleanRegex.MatchString(formattedLine) {
// 3. Handle bullet points (after cleaning leading symbols).
formattedLine = " - " + bulletCleanRegex.ReplaceAllString(formattedLine, "")
} else if trimmedLine == "" {
// Keep empty lines as is for spacing.
formattedLine = ""
} else {
// 4. Handle general text within a section (indent by 4 spaces)
// Trim all leading whitespace (including non-breaking spaces)
// before indenting.
formattedLine = " - " + strings.TrimLeftFunc(formattedLine, func(r rune) bool {
return r == ' ' || r == '\t' || r == '\u00A0'
})
}
// Apply color logic using the final formatted line.
lowerLine := strings.ToLower(formattedLine)
if strings.Contains(lowerLine, "critical issues") || strings.Contains(lowerLine, "failed") || strings.Contains(lowerLine, "critical") {
color.New(color.FgRed, color.Bold).Println(formattedLine)
} else if strings.Contains(lowerLine, "warning") || strings.Contains(lowerLine, "high") || strings.Contains(lowerLine, "non-critical observations") {
color.New(color.FgYellow).Println(formattedLine)
} else if strings.Contains(lowerLine, "overall status summary") || strings.Contains(lowerLine, "next steps") {
color.New(color.FgGreen, color.Bold).Println(formattedLine)
} else if formattedLine != "" {
// Only print if not an empty line after processing.
fmt.Println(formattedLine)
}
}
} else {
color.Red("No explanation generated by AI. This might indicate an issue with the AI's response or safety settings.")
}
This part of the code demonstrates:
-
Robust Text Processing: It iterates through each line of the AI's response, applying regular expressions to identify and reformat headers, numbered lists, and bullet points. This ensures consistent and clean output.
-
Color-Coding for Clarity: Using a library like
fatih/color
, the tool intelligently applies colors (red for critical issues, yellow for warnings, green for summaries, and next steps) to make the output immediately scannable and highlight the most important information. -
Error Handling: It includes a fallback message if the AI doesn't generate content, indicating potential issues.
The Power of AI in Troubleshooting
This Golang tool showcases a powerful application of AI in system administration:
-
Accelerated Analysis: Instead of manually parsing lengthy reports, administrators get an instant, prioritized summary.
-
Reduced Human Error: AI can consistently identify patterns and anomalies that a human might miss, especially under pressure.
-
Actionable Insights: The structured output, with clear recommendations and next steps, directly guides troubleshooting efforts.
-
Empowering Junior Staff: Even less experienced personnel can leverage the AI's analysis to understand and address complex system issues.
Conclusion
By combining the efficiency of Golang with the analytical power of Gemini AI, we can create intelligent tools that revolutionize how we approach system troubleshooting. This example of analyzing PHP-FPM status reports is just one instance; the same principles can be applied to various log files, performance metrics, and system diagnostics across different platforms.
This approach not only saves valuable time but also enhances the accuracy and effectiveness of problem-solving in complex IT environments.
What other system reports or log files do you think could benefit from AI-powered analysis? Let us know in the comments below!
If you have any questions about the full implementation or want to discuss how AI can further enhance your system administration workflows, feel free to email me at geraldvillorente@gmail.com.
Comments