Logging Queries and Results

Logging Queries and Results in MySQLi
Logging queries and their results is a crucial aspect of database management and application debugging. In PHP applications using MySQLi, logging can help you monitor query performance, identify issues, and maintain records of database interactions.
This article explores various techniques for logging queries and their results in MySQLi, providing practical examples and best practices to effectively implement logging in your applications.

Introduction to Query Logging

Query logging involves recording SQL queries executed against a database and their outcomes. This can include the actual SQL statement, execution time, affected rows, and error messages. Logging is essential for debugging, performance monitoring, and auditing database operations.

Techniques for Logging Queries and Results

Several techniques can be employed to log queries and their results when using MySQLi in PHP. Below, we discuss different methods and provide code examples for implementing them.

1. Logging Queries Using a Custom Logger

One of the simplest methods for logging queries is to use a custom logging function. This involves creating a function that writes query details to a log file whenever a query is executed.

Example: Custom Logger Function

				
					<?php
// Function to log queries and results
function log_query($query, $result, $filename = 'query_log.txt') {
    // Open the log file in append mode
    $logfile = fopen($filename, 'a');
    
    // Prepare log entry
    $logEntry = "[" . date('Y-m-d H:i:s') . "] Query: " . $query . "\n";
    
    // Check if result is a boolean or a result object
    if ($result === TRUE) {
        $logEntry .= "Result: Query executed successfully.\n";
    } elseif ($result === FALSE) {
        $logEntry .= "Result: Error - " . mysqli_error($GLOBALS['conn']) . "\n";
    } else {
        $logEntry .= "Result: " . mysqli_num_rows($result) . " rows affected.\n";
    }
    
    // Write to log file
    fwrite($logfile, $logEntry);
    
    // Close the log file
    fclose($logfile);
}

// Database connection
$servername = "localhost";
$username = "root";
$password = "";
$database = "mydatabase";

// Create connection
$conn = new mysqli($servername, $username, $password, $database);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// Example query
$sql = "INSERT INTO users (username, email) VALUES ('new_user', 'newuser@example.com')";
$result = $conn->query($sql);

// Log the query and result
log_query($sql, $result);

// Close the connection
$conn->close();
?>

				
			

In this example, we define a log_query() function that writes query details to a log file. The function is called after executing a query to record its execution status and any associated errors.

2. Using Prepared Statements for Logging

Prepared statements are a secure way to execute queries with dynamic data. When using prepared statements, logging involves capturing both the prepared statement and its execution results.

Example: Logging Prepared Statements

				
					<?php
// Function to log prepared statements
function log_prepared_statement($stmt, $params, $filename = 'prepared_query_log.txt') {
    // Open the log file in append mode
    $logfile = fopen($filename, 'a');
    
    // Prepare log entry
    $logEntry = "[" . date('Y-m-d H:i:s') . "] Prepared Statement: " . $stmt->sql . "\n";
    $logEntry .= "Parameters: " . json_encode($params) . "\n";
    
    // Execute and log result
    if ($stmt->execute()) {
        $logEntry .= "Result: Query executed successfully.\n";
    } else {
        $logEntry .= "Result: Error - " . $stmt->error . "\n";
    }
    
    // Write to log file
    fwrite($logfile, $logEntry);
    
    // Close the log file
    fclose($logfile);
}

// Database connection
$servername = "localhost";
$username = "root";
$password = "";
$database = "mydatabase";

// Create connection
$conn = new mysqli($servername, $username, $password, $database);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// Prepare a statement
$stmt = $conn->prepare("INSERT INTO users (username, email) VALUES (?, ?)");
$stmt->bind_param("ss", $username, $email);

// Define parameters
$username = 'new_user';
$email = 'newuser@example.com';

// Log prepared statement and result
log_prepared_statement($stmt, [$username, $email]);

// Close the statement and connection
$stmt->close();
$conn->close();
?>

				
			
In this example, log_prepared_statement() logs the details of a prepared statement, including the SQL query and parameters. This method captures the execution outcome and any errors.

3. Logging Query Execution Time

Measuring and logging query execution time is important for performance monitoring. By recording the time taken for queries to execute, you can identify slow queries and optimize your database performance.

Example: Logging Query Execution Time

				
					<?php
// Function to log query execution time
function log_query_execution_time($query, $conn, $filename = 'query_execution_log.txt') {
    // Start timing
    $start_time = microtime(true);
    
    // Execute query
    $result = $conn->query($query);
    
    // End timing
    $end_time = microtime(true);
    $execution_time = $end_time - $start_time;
    
    // Open the log file in append mode
    $logfile = fopen($filename, 'a');
    
    // Prepare log entry
    $logEntry = "[" . date('Y-m-d H:i:s') . "] Query: " . $query . "\n";
    $logEntry .= "Execution Time: " . number_format($execution_time, 4) . " seconds\n";
    
    if ($result === TRUE) {
        $logEntry .= "Result: Query executed successfully.\n";
    } elseif ($result === FALSE) {
        $logEntry .= "Result: Error - " . mysqli_error($conn) . "\n";
    } else {
        $logEntry .= "Result: " . mysqli_num_rows($result) . " rows affected.\n";
    }
    
    // Write to log file
    fwrite($logfile, $logEntry);
    
    // Close the log file
    fclose($logfile);
    
    // Return the result
    return $result;
}

// Database connection
$servername = "localhost";
$username = "root";
$password = "";
$database = "mydatabase";

// Create connection
$conn = new mysqli($servername, $username, $password, $database);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// Example query
$sql = "SELECT * FROM users";
$result = log_query_execution_time($sql, $conn);

// Close the connection
$conn->close();
?>

				
			

In this example, log_query_execution_time() logs the execution time of a query along with its result. The execution time is calculated using microtime(true) before and after executing the query.

4. Using a Database Table for Logging

For more structured logging, you can use a database table to store query logs. This approach provides a centralized location for logs and allows for more advanced querying and analysis.

Example: Logging to a Database Table

				
					<?php
// Function to log queries to a database table
function log_query_to_table($query, $result, $conn) {
    // Prepare log entry
    $logEntry = [
        'timestamp' => date('Y-m-d H:i:s'),
        'query' => $query,
        'result' => ($result === TRUE ? 'Success' : 'Error - ' . mysqli_error($conn)),
        'affected_rows' => ($result !== FALSE ? $conn->affected_rows : 0)
    ];
    
    // Insert log entry into the database
    $stmt = $conn->prepare("INSERT INTO query_logs (timestamp, query, result, affected_rows) VALUES (?, ?, ?, ?)");
    $stmt->bind_param("sssi", $logEntry['timestamp'], $logEntry['query'], $logEntry['result'], $logEntry['affected_rows']);
    $stmt->execute();
    $stmt->close();
}

// Database connection
$servername = "localhost";
$username = "root";
$password = "";
$database = "mydatabase";

// Create connection
$conn = new mysqli($servername, $username, $password, $database);

// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

// Example query
$sql = "DELETE FROM users WHERE last_login < NOW() - INTERVAL 1 YEAR";
$result = $conn->query($sql);

// Log the query to the database table
log_query_to_table($sql, $result, $conn);

// Close the connection
$conn->close();
?>

				
			

In this example, log_query_to_table() logs query details to a query_logs table in the database. This method provides a structured way to store and retrieve query logs.

Best Practices for Query Logging

To ensure effective logging and avoid potential issues, follow these best practices:

  1. Log Sensitive Data Carefully: Avoid logging sensitive information, such as user passwords or personal data. Mask or exclude sensitive details to protect user privacy.
  2. Implement Log Rotation: Regularly rotate log files to manage their size and prevent excessive disk usage. Implement a system to archive or delete old logs.
  3. Use Appropriate Logging Levels: Implement different logging levels (e.g., INFO, WARNING, ERROR) to control the amount of detail recorded. This helps in filtering logs based on severity.
  4. Secure Log Files: Ensure that log files are stored in secure locations with restricted access. Protect log files from unauthorized access or tampering.
  5. Monitor Log Files Regularly: Regularly review and analyze log files to identify issues, monitor performance, and detect anomalies. Set up alerts for critical errors or performance degradation.
  6. Optimize Logging Performance: Minimize the performance impact of logging by optimizing file I/O operations and avoiding excessive logging during high-load periods.

Conclusion

Logging queries and results in MySQLi is a valuable practice for debugging, monitoring, and maintaining PHP applications. By implementing techniques such as custom logging functions, logging prepared statements, tracking execution times, and using database tables for logging, you can gain valuable insights into your database interactions.

Following best practices ensures that your logging system is secure, efficient, and effective in capturing and managing query-related information. With these techniques and practices, you can enhance your ability to troubleshoot issues, optimize performance, and maintain robust database operations in your PHP applications.

Scroll to Top