Logging in Concrete CMS

User
Concrete cms Add logs from custom package ti default concrete cms logs
we are using concrete cms 9
Assistant
To add logs from your **custom package** to the default **Concrete CMS logs** in version 9, you can use Concrete’s built-in logging system, which integrates with the `DatabaseLogger`.

Here’s how you can log messages from your package:

### ✅ Step-by-Step: Logging in Concrete CMS 9 from a Custom Package

#### 1. **Import the Logger Facade**
At the top of your PHP file (e.g., in a controller, service, or class), import the Logger:

use ConcreteCoreLoggingLoggerFactory;
use PsrLogLoggerInterface;

#### 2. **Get the Logger Instance**
You can get the logger via the application's service container:

$logger = app(LoggerFactory::class)->createLogger('shopping_feed'); // Use a custom channel name

> This `shopping_feed` channel will still write to the same `Logs` section in the dashboard (`/dashboard/reports/logs`), and you can filter by channel name.

#### 3. **Write Log Messages**
Now use standard PSR-3 log levels:

$logger->info('Feed generated successfully for ID: ' . $feedId);
$logger->warning('Feed generation took longer than expected.');
$logger->error('Failed to generate feed: ' . $exception->getMessage());

### 🔧 Example: Logging from a Custom Controller

use ConcreteCoreLoggingLoggerFactory;

class FeedGenerator
{
    protected $logger;

    public function __construct(LoggerFactory $loggerFactory)
    {
        $this->logger = $loggerFactory->createLogger('shopping_feed');
    }

    public function generate($feedId)
    {
        try {
            // your feed generation logic...
            $this->logger->info("Feed generated for ID: {$feedId}");
        } catch (Exception $e) {
            $this->logger->error("Feed generation failed: " . $e->getMessage());
        }
    }
}

If you're in a controller or class where dependency injection isn’t feasible, you can also call it directly using:

$logger = Core::make(LoggerFactory::class)->createLogger('shopping_feed');
$logger->debug('This is a debug message');

### 📍Where It Appears in Concrete CMS Admin

You’ll find your logs in:

Dashboard → Reports → Logs

Filter by **Channel** to see only logs from `shopping_feed`.

Would you like me to include this in your package’s installation routine or inject it via a service provider?

User
$this->logFeedStatus($db, $config['id'], 'error', 'No matching product found');
use for this
Assistant
To make your call to `$this->logFeedStatus()` write to the **Concrete CMS logs**, you should use the `LoggerFactory` service inside your method like this:

### ✅ Update your `logFeedStatus()` method

Here’s how you can implement it:

use ConcreteCoreLoggingLoggerFactory;

protected function logFeedStatus($db, $feedId, $level = 'info', $message = '')
{
    // Optional: you can also insert into a custom table here using $db if needed

    // Get Concrete CMS logger for 'shopping_feed' channel
    $logger = app(LoggerFactory::class)->createLogger('shopping_feed');

    // Prepare the full message
    $fullMessage = "Feed ID: {$feedId} — {$message}";

    // Log using dynamic level
    switch (strtolower($level)) {
        case 'debug':
            $logger->debug($fullMessage);
            break;
        case 'notice':
            $logger->notice($fullMessage);
            break;
        case 'warning':
            $logger->warning($fullMessage);
            break;
        case 'error':
            $logger->error($fullMessage);
            break;
        case 'critical':
            $logger->critical($fullMessage);
            break;
        case 'alert':
            $logger->alert($fullMessage);
            break;
        case 'emergency':
            $logger->emergency($fullMessage);
            break;
        case 'info':
        default:
            $logger->info($fullMessage);
            break;
    }
}

### 📌 Usage Example

$this->logFeedStatus($db, $config['id'], 'error', 'No matching product found');

This will log the message:

> `Feed ID: 12 — No matching product found`

…to the **Concrete CMS Logs dashboard** under channel `shopping_feed`.

Let me know if you'd like this extended to store in a custom DB table *and* write to Concrete logs simultaneously.

User
protected function logFeedStatus($db, $feedId, $status, $message = null)
{
try {
$now = (new DateTime())->format('Y-m-d H:i:s');

$db->insert('shoppingfeedlog', [
'feed_id' => $feedId,
'updated_at' => $now,
'status' => $status,
'error_message' => $message
]);
} catch (Exception $logException) {
// Optional: Log error to file or skip silently
// error_log("Feed log error: " . $logException->getMessage());
}
}
replace this

Assistant
Here's the **updated version** of your `logFeedStatus()` method that:

1. **Inserts into your custom `shoppingfeedlog` table** (as it currently does).
2. **Also logs to Concrete CMS’s built-in Logs dashboard** using `LoggerFactory`.

### ✅ Updated `logFeedStatus()` with Concrete CMS Logging

use ConcreteCoreLoggingLoggerFactory;
use DateTime;
use Exception;

protected function logFeedStatus($db, $feedId, $status, $message = null)
{
    try {
        $now = (new DateTime())->format('Y-m-d H:i:s');

        // Save to custom table
        $db->insert('shoppingfeedlog', [
            'feed_id' => $feedId,
            'updated_at' => $now,
            'status' => $status,
            'error_message' => $message
        ]);

        // Also log to Concrete CMS core logger
        $logger = app(LoggerFactory::class)->createLogger('shopping_feed');
        $logMessage = "Feed ID: {$feedId} — Status: {$status}" . ($message ? " — {$message}" : '');

        switch (strtolower($status)) {
            case 'debug':
                $logger->debug($logMessage);
                break;
            case 'notice':
                $logger->notice($logMessage);
                break;
            case 'warning':
                $logger->warning($logMessage);
                break;
            case 'error':
                $logger->error($logMessage);
                break;
            case 'critical':
                $logger->critical($logMessage);
                break;
            case 'alert':
                $logger->alert($logMessage);
                break;
            case 'emergency':
                $logger->emergency($logMessage);
                break;
            case 'info':
            default:
                $logger->info($logMessage);
                break;
        }

    } catch (Exception $logException) {
        // Avoid infinite logging loops – log to PHP error log
        error_log("Feed logging failed: " . $logException->getMessage());
    }
}

### 📝 Notes
– The `status` field is reused as the log level (e.g., `'info'`, `'error'`, `'warning'`).
– If you store custom statuses (like `'completed'` or `'processing'`), you can normalize them or default to `'info'`.

Let me know if you want a fallback/default level or to sanitize unknown statuses.

Leave a Comment

Your email address will not be published. Required fields are marked *