Hello folks!
A Processing sketch that reports detailed system and environment diagnostics at runtime.
Designed to solve real-world project issues, this sketch blends system diagnostics with AI-assisted development (ChatGPT & Gemini). Building it demanded technical expertise, close oversight, critical thinking, and constant review to ensure useful, accurate results. Not for the inexperienced or faint of heart.
It will certainly require more work and updates!
Enjoy!
// Report System and Environment Diagnostics at Runtime
// Author: glv
// Date: 2025-10-16
// Version: 1.0.0
// A Processing sketch that reports detailed system and environment diagnostics at runtime.
// This was a collaborative effort with ChatGPT and Google Gemini
// Global variables for colour and diagnostic strings
color favouriteColour;
String hexColourEntry;
// Global variables to hold the long diagnostic strings calculated in setup()
String dateTime, osName, osVersion, osArchitecture, osSpecific, cpuList;
String javaVersion, javaVendor, javaSpecVersion, jvmName, jvmVendor, javaHome, fileEncoding;
String memTotal, memFree, memMax;
String userHome, currentDir, pathSeparator, fileSeparatorRaw, lineSeparator;
// Variable to hold the filtered PATH information
String relevantPathEntries;
// Variables for new paths
String processingSketchbookPath;
String processingPreferencesPath;
String currentSketchPath;
String currentSketchDataPath; // REVISED: Will hold the expected path
String isSketchRunning;
String libraryPlaceholder;
String processingTempDir;
String systemJavaPath;
String javaHomeEnv;
// Global variables for folder existence status
String dataFolderStatus;
String codeFolderStatus;
String librariesFolderStatus;
// Global variables for file counts
String rootJarCount;
String codeJarCount;
String rootJavaCount;
String codeJavaCount;
// Global variable for comprehensive Library Status
String libraryStatus;
// --- GLOBAL VARIABLE FOR PARSED SKETCHBOOK PATH ---
String parsedSketchbookPath;
// Import Java I/O for file handling
import java.io.File;
import java.io.FileFilter;
// Helper function to read and parse the sketchbook.path from preferences.txt
// Searches for 'sketchbook.path.four' first, then 'sketchbook.path'
String parseSketchbookPath(String prefsFilePath) {
try {
String[] lines = loadStrings(prefsFilePath);
String p4Path = null;
String genericPath = null;
if (lines != null) {
for (String line : lines) {
String trimmedLine = line.trim();
// 1. Search for P4 specific key (sketchbook.path.four=...)
if (trimmedLine.startsWith("sketchbook.path.four=")) {
String[] parts = split(trimmedLine, '=');
if (parts.length > 1) {
p4Path = parts[1].trim();
}
}
// 2. Search for generic key (sketchbook.path=...)
else if (trimmedLine.startsWith("sketchbook.path=")) {
String[] parts = split(trimmedLine, '=');
if (parts.length > 1) {
genericPath = parts[1].trim();
}
}
}
}
if (p4Path != null) {
return p4Path;
} else if (genericPath != null) {
return genericPath;
}
} catch (Exception e) {
return "ERROR: Parsing failed after loadStrings(). Check file encoding.";
}
return "KEY NOT FOUND in preferences.txt";
}
// Helper function to get the list of ALL installed libraries (Core + Contribution)
String getLibraryStatus() {
ArrayList<String> libraryReport = new ArrayList<String>();
String sketchbookRootPath = parsedSketchbookPath;
String processingInstallPath = System.getProperty("user.dir");
// Use the raw file separator character for constructing paths
String rawSep = System.getProperty("file.separator");
// 1. CHECK CONTRIBUTION (SKETCHBOOK) LIBRARIES (User-installed libraries)
if (sketchbookRootPath != null && !sketchbookRootPath.startsWith("ERROR") && !sketchbookRootPath.startsWith("KEY NOT FOUND")) {
File contributionDir = new File(sketchbookRootPath, "libraries");
if (contributionDir.exists()) {
File[] files = contributionDir.listFiles(new FileFilter() {
public boolean accept(File file) { return file.isDirectory(); }
});
if (files != null && files.length > 0) {
String[] libNames = new String[files.length];
for (int i = 0; i < files.length; i++) {
libNames[i] = files[i].getName();
}
libraryReport.add(" - Contribution Libraries (Sketchbook Folder) [" + sketchbookRootPath + "]:\n - " + join(libNames, "\n - "));
} else {
libraryReport.add(" - Contribution Libraries (Sketchbook Folder) [" + sketchbookRootPath + "]: None found.");
}
} else {
libraryReport.add(" - Contribution Libraries Path: Sketchbook 'libraries' folder not found at: " + contributionDir.getAbsolutePath());
}
} else {
libraryReport.add(" - Contribution Libraries Path: Sketchbook path is unknown/invalid. Cannot check user libraries.");
}
// 2. CHECK CORE LIBRARIES (Bundled libraries like 'net')
// Use rawSep for correct path construction
String pathA = "modes" + rawSep + "java" + rawSep + "libraries"; // Standard path
String pathB = "app" + rawSep + "resources" + rawSep + "modes" + rawSep + "java" + rawSep + "libraries"; // Portable path
File coreDir = new File(processingInstallPath, pathA);
String pathUsed = pathA;
if (!coreDir.exists()) {
coreDir = new File(processingInstallPath, pathB);
pathUsed = pathB;
}
if (coreDir.exists()) {
File[] files = coreDir.listFiles(new FileFilter() {
public boolean accept(File file) { return file.isDirectory(); }
});
if (files != null && files.length > 0) {
String[] libNames = new String[files.length];
for (int i = 0; i < files.length; i++) {
libNames[i] = files[i].getName();
}
libraryReport.add(" - Core Libraries (Processing Modes) [Path: " + pathUsed + "]:\n - " + join(libNames, "\n - "));
} else {
libraryReport.add(" - Core Libraries: Path found, but no folders detected inside. (" + coreDir.getAbsolutePath() + ")");
}
} else {
// Correctly display the paths that were checked using rawSep
String pathA_display = "modes" + rawSep + "java" + rawSep + "libraries";
String pathB_display = "app" + rawSep + "resources" + rawSep + "modes" + rawSep + "java" + rawSep + "libraries";
libraryReport.add(" - Core Libraries Path: Not found. (Checked: " + pathA_display + " and " + pathB_display + ")");
}
return join(libraryReport.toArray(new String[0]), "\n");
}
// Helper function to count files with a specific extension
int countFiles(String[] fileList, String extension) {
if (fileList == null) return 0;
int count = 0;
for (String fileName : fileList) {
if (fileName.toLowerCase().endsWith(extension)) {
count++;
}
}
return count;
}
void setup()
{
// --- Setup for the visual window ---
size(150, 150, P2D);
// Make favouriteColour random
int r = (int)random(256);
int g = (int)random(256);
int b = (int)random(256);
favouriteColour = color(r, g, b);
// --- Calculate Hex Code ---
String hexCode = hex(favouriteColour & 0xFFFFFF, 6);
hexColourEntry = "Favourite Colour (Hex): #" + hexCode;
// --- System Information Properties (Calculation) ---
dateTime = "Current Date/Time: " + nf(year(), 4) + "-" + nf(month(), 2) + "-" + nf(day(), 2) + " " + nf(hour(), 2) + ":" + nf(minute(), 2) + ":" + nf(second(), 2);
// Operating System (OS)
osName = "OS Name: " + System.getProperty("os.name");
osVersion = "OS Version: " + System.getProperty("os.version");
osArchitecture = "OS Architecture: " + System.getProperty("os.arch");
cpuList = "CPU Instruction Set: " + System.getProperty("sun.cpu.isalist");
// DYNAMIC: Retrieve JAVA_HOME (OS Environment Variable)
String envJavaHomeRaw = System.getenv("JAVA_HOME");
javaHomeEnv = "JAVA_HOME (Env Variable): " + (envJavaHomeRaw != null ? envJavaHomeRaw : "Not Set/Found");
// Report what to do to find the system Java executable, as the tool cannot report it directly.
systemJavaPath = "System Default Java Executable (OS): Run 'where java' (Win) or 'which java' (Mac/Linux) in terminal for exact path.";
// Java/Processing Environment (This block will be printed in the Processing section)
String processingJavaVendor = System.getProperty("java.vendor");
String javaClassification = (processingJavaVendor.toLowerCase().contains("processing") || processingJavaVendor.toLowerCase().contains("oracle") || System.getProperty("java.home").toLowerCase().contains("processing"))
? " (Processing Bundled)"
: " (OS/System Default)";
javaVersion = "Java Version: " + System.getProperty("java.version") + javaClassification;
javaVendor = "Java Vendor: " + processingJavaVendor;
javaSpecVersion = "Java Specification Version: " + System.getProperty("java.specification.version");
jvmName = "JVM Name: " + System.getProperty("java.vm.name");
jvmVendor = "JVM Vendor: " + System.getProperty("java.vm.vendor");
javaHome = "Java Home Dir: " + System.getProperty("java.home");
fileEncoding = System.getProperty("file.encoding");
// Runtime Memory Information
Runtime runtime = Runtime.getRuntime();
long totalMemory = runtime.totalMemory() / (1024 * 1024);
long freeMemory = runtime.freeMemory() / (1024 * 1024);
long maxMemory = runtime.maxMemory() / (1024 * 1024);
memTotal = "Total JVM Memory (MB): " + totalMemory;
memFree = "Free JVM Memory (MB): " + freeMemory;
memMax = "Max JVM Memory (MB): " + maxMemory;
// User/System paths
userHome = "User Home Dir: " + System.getProperty("user.home");
currentDir = "Current Working Dir (Installation Root): " + System.getProperty("user.dir");
// DYNAMIC: Processing Temp Path (using Java's default temp directory property)
processingTempDir = "Temporary Directory (Java Default Temp): " + System.getProperty("java.io.tmpdir");
// File and Path Separators (Prepared for new section)
pathSeparator = "Path Separator: " + System.getProperty("path.separator");
// Store the raw file separator character separately for path construction
fileSeparatorRaw = System.getProperty("file.separator");
lineSeparator = "Line Separator: " + getEscapedSeparator(System.getProperty("line.separator"));
// --- Filter and Format Relevant PATH Entries (Where OS looks for Java) ---
String rawPath = System.getenv("Path");
if (rawPath == null) rawPath = System.getenv("PATH"); // Check for case variations
String separator = System.getProperty("path.separator");
String[] pathDirectories = (rawPath != null) ? split(rawPath, separator) : new String[0];
ArrayList<String> filteredPaths = new ArrayList<String>();
for (String dir : pathDirectories) {
String lowerDir = dir.toLowerCase();
// Looks for any path that might contain Java/JDK/Processing/Python executables
if (lowerDir.contains("java") || lowerDir.contains("jdk") || lowerDir.contains("processing") || lowerDir.contains("python")) {
filteredPaths.add(" - " + dir);
}
}
if (filteredPaths.isEmpty()) {
relevantPathEntries = "Relevant PATH Entries: None found containing 'java', 'jdk', 'processing', or 'python'.";
} else {
String[] pathsArray = filteredPaths.toArray(new String[0]);
relevantPathEntries = "Relevant PATH Entries:\n" + join(pathsArray, "\n");
}
// --- PROCESSING SPECIFIC PATHS & STATUS ---
// DYNAMIC: Processing Preferences Path (Windows/macOS/Linux friendly)
String userHomeDir = System.getProperty("user.home");
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
processingPreferencesPath = userHomeDir + fileSeparatorRaw + "AppData" + fileSeparatorRaw + "Roaming" + fileSeparatorRaw + "Processing" + fileSeparatorRaw + "preferences.txt";
} else if (os.contains("mac")) {
processingPreferencesPath = userHomeDir + fileSeparatorRaw + "Library" + fileSeparatorRaw + "Processing" + fileSeparatorRaw + "preferences.txt";
} else {
// Linux/other
processingPreferencesPath = userHomeDir + fileSeparatorRaw + ".config" + fileSeparatorRaw + "processing" + fileSeparatorRaw + "preferences.txt";
}
parsedSketchbookPath = parseSketchbookPath(processingPreferencesPath);
processingSketchbookPath = "Sketchbook Folder: " + parsedSketchbookPath;
currentSketchPath = "Current Sketch Folder: " + sketchPath();
// REVISED: Clarify that dataPath returns the expected location
currentSketchDataPath = "Expected Data Folder Path (dataPath(\"\")): " + dataPath("");
isSketchRunning = "Sketch is Running: " + (frameRate > 0 ? "True" : "False");
// --- FOLDER EXISTENCE CHECKS ---
File rootDir = new File(currentSketchPath);
File dataDir = new File(currentSketchPath, "data");
File codeDir = new File(currentSketchPath, "code");
File libDir = new File(currentSketchPath, "libraries");
dataFolderStatus = " - data/ Folder Exists: " + dataDir.exists();
codeFolderStatus = " - code/ Folder Exists: " + codeDir.exists();
librariesFolderStatus = " - libraries/ Folder Exists: " + libDir.exists();
// --- FILE EXISTENCE CHECKS ---
String[] rootFiles = rootDir.list();
rootJarCount = " - Root JAR Files (*.jar): " + countFiles(rootFiles, ".jar");
String[] codeFiles = codeDir.list();
codeJarCount = " - code/ JAR Files (*.jar): " + countFiles(codeFiles, ".jar");
rootJavaCount = " - Root Java Files (*.java): " + countFiles(rootFiles, ".java");
codeJavaCount = " - code/ Java Files (*.java): " + countFiles(codeFiles, ".java");
// --- LIBRARY STATUS (COMPREHENSIVE) ---
libraryStatus = getLibraryStatus();
// --- LIBRARY LIST (FINAL SAFE VERSION) ---
libraryPlaceholder = "--- Libraries Used in Code ---\n\nPlease check the 'import' statements at the top of your sketch for the loaded library list.";
}
void draw()
{
// --- Diagnostic Output (Runs ONCE) ---
if (frameCount == 1) {
// #######################################################
// ### 1. SYSTEM / OS ENVIRONMENT ###
// #######################################################
println("==================================================================================");
println(); println("--- 1. SYSTEM / OS ENVIRONMENT ---"); println();
println("==================================================================================");
// --- General OS Properties ---
println();
println("--- General OS Properties ---"); println();
println(dateTime);
println(osName);
println(osVersion);
println(osArchitecture);
println(cpuList);
println();
println("------------------------------------------------------");
println();
// --- System Separators and Encoding ---
println("--- System Separators and Encoding ---");
println();
println(pathSeparator);
println("File Separator: " + fileSeparatorRaw);
println(lineSeparator);
println("Default File Encoding: " + fileEncoding);
println();
println("--------------------------------------");
println();
// --- System Paths, and OS-Level Java ---
println("--- System Paths, and OS-Level Java ---");
println();
println(userHome);
println(javaHomeEnv);
println(systemJavaPath);
println();
println("---------------------------------------");
println();
// --- Relevant PATH Entries (OS Java Search) ---
println("--- Relevant PATH Entries (OS Java Search) ---");
println();
println("These are directories the OS checks for system-level programs like Java.");
println(relevantPathEntries);
println();
println("----------------------------------------------");
println();
// #######################################################
// ### 2. PROCESSING ENVIRONMENT ###
// #######################################################
println("==================================================================================");
println(); println("--- 2. PROCESSING ENVIRONMENT ---"); println();
println("==================================================================================");
println();
// --- Java Environment (Running Sketch) ---
println("--- Java Environment (Running Sketch) ---");
println();
println(javaVersion);
println(javaVendor);
println(javaSpecVersion);
println(jvmName);
println(jvmVendor);
println(javaHome);
println(memTotal);
println(memFree);
println(memMax);
println();
println("------------------------------------------------------");
println();
// --- Processing Installation and Compiler Paths ---
println("--- Processing Installation and Compiler Paths ---");
println();
println(currentDir);
println(processingTempDir);
println("Processing Preferences File: " + processingPreferencesPath);
println(isSketchRunning);
println();
println("------------------------------------------------------");
println();
// --- Sketchbook and Current Sketch Paths ---
println("--- Sketchbook and Current Sketch Paths ---");
println();
println(processingSketchbookPath);
println(currentSketchPath);
println(currentSketchDataPath); // Prints the Expected Path
println();
println("------------------------------------------------------");
println();
// --- Installed Library Status (Core & Contribution) ---
println("--- Installed Library Status (Core & Contribution) ---");
println();
println(libraryStatus);
println();
println(libraryPlaceholder);
println();
println("------------------------------------------------------");
println();
// --- Sketch Folder Contents (MOVED TO THE END) ---
println("--- Sketch Folder Contents ---");
println();
println(dataFolderStatus); // Confirms existence of data/
println(codeFolderStatus); // Confirms existence of code/
println(librariesFolderStatus); // Confirms existence of libraries/
println(rootJarCount); // Counts files in root
println(codeJarCount); // Counts files in code/
println(rootJavaCount); // Counts files in root
println(codeJavaCount); // Counts files in code/
println();
println("------------------------------------------------------");
println();
println(hexColourEntry);
}
// --- Visual Output (Runs continuously) ---
background(240);
// Draw Favourite Colour
fill(favouriteColour);
rect(35, 35, 80, 80);
// Add label
fill(0);
textSize(12);
textAlign(CENTER, CENTER);
text("Favourite Colour", width/2, 130);
}
// Helper function to make line separator visible in output
String getEscapedSeparator(String sep) {
if (sep.equals("\n")) {
return "\\n (Unix/Mac)";
} else if (sep.equals("\r\n")) {
return "\\r\\n (Windows)";
} else if (sep.equals("\r")) {
return "\\r (Older Mac)";
}
return sep;
}
Output to console:
==================================================================================
--- 1. SYSTEM / OS ENVIRONMENT ---
==================================================================================
--- General OS Properties ---
Current Date/Time: 2025-10-16 16:25:54
OS Name: Windows 10
OS Version: 10.0
OS Architecture: amd64
CPU Instruction Set: amd64
------------------------------------------------------
--- System Separators and Encoding ---
Path Separator: ;
File Separator: \
Line Separator: \r\n (Windows)
Default File Encoding: Cp1252
--------------------------------------
--- System Paths, and OS-Level Java ---
User Home Dir: C:\Users\GLV
JAVA_HOME (Env Variable): C:\Users\GLV\AppData\Local\Programs\Eclipse Adoptium\jdk-17.0.15.6-hotspot
System Default Java Executable (OS): Run 'where java' (Win) or 'which java' (Mac/Linux) in terminal for exact path.
---------------------------------------
--- Relevant PATH Entries (OS Java Search) ---
These are directories the OS checks for system-level programs like Java.
Relevant PATH Entries:
- C:\Users\GLV\AppData\Local\Programs\Python\Python313\Scripts\
- C:\Users\GLV\AppData\Local\Programs\Python\Python313\
- E:\Program_Portable\Processing-4.4.4\app\resources\jdk\bin
- C:\Users\GLV\AppData\Local\Programs\Eclipse Adoptium\jdk-17.0.15.6-hotspot\bin
- D:\Program_Portable\Processing-4.4.10\app
----------------------------------------------
==================================================================================
--- 2. PROCESSING ENVIRONMENT ---
==================================================================================
--- Java Environment (Running Sketch) ---
Java Version: 17.0.8.1 (Processing Bundled)
Java Vendor: Eclipse Adoptium
Java Specification Version: 17
JVM Name: OpenJDK 64-Bit Server VM
JVM Vendor: Eclipse Adoptium
Java Home Dir: D:\Program_Portable\Processing-4.4.10\app\resources\jdk
Total JVM Memory (MB): 256
Free JVM Memory (MB): 239
Max JVM Memory (MB): 4072
------------------------------------------------------
--- Processing Installation and Compiler Paths ---
Current Working Dir (Installation Root): D:\Program_Portable\Processing-4.4.10
Temporary Directory (Java Default Temp): D:\temp\
Processing Preferences File: C:\Users\GLV\AppData\Roaming\Processing\preferences.txt
Sketch is Running: True
------------------------------------------------------
--- Sketchbook and Current Sketch Paths ---
Sketchbook Folder: D:\Users\GLV\Documents\P4_TEST
Current Sketch Folder: D:\Users\GLV\Documents\Processing_Test\RuntimeReport_1_0_0
Expected Data Folder Path (dataPath("")): D:\Users\GLV\Documents\Processing_Test\RuntimeReport_1_0_0\data
------------------------------------------------------
--- Installed Library Status (Core & Contribution) ---
- Contribution Libraries (Sketchbook Folder) [D:\Users\GLV\Documents\P4_TEST]:
- controlP5
- webSockets
- Core Libraries (Processing Modes) [Path: app\resources\modes\java\libraries]:
- dxf
- io
- net
- pdf
- serial
- svg
--- Libraries Used in Code ---
Please check the 'import' statements at the top of your sketch for the loaded library list.
------------------------------------------------------
--- Sketch Folder Contents ---
- data/ Folder Exists: false
- code/ Folder Exists: false
- libraries/ Folder Exists: false
- Root JAR Files (*.jar): 0
- code/ JAR Files (*.jar): 0
- Root Java Files (*.java): 0
- code/ Java Files (*.java): 0
------------------------------------------------------
Favourite Colour (Hex): #967C9B
This part really confused the AI:
I also wanted UK spelling and it changed the color datatype to colour!
Much to learn the AI has… we must temper our expectations. It is still learning!
:-)