Skip to content

Potential Data Truncation in Task Logs Leading to Errors with php spark tasks:list #187

Closed
@b1tc0re

Description

@b1tc0re

Description:

In the current implementation, the exception written to $taskLog->error is serialized in its entirety using serialize($taskLog->error ?? null) and stored in the database. The field used to store this data is of type TEXT. The serialized exception object can become quite large, especially when the exception includes a long stack trace or nested exceptions. This can lead to data truncation when writing to the TEXT field, as its size is limited. This data truncation causes errors when calling php spark tasks:list

Solution:

Instead of storing the entire serialized exception, you can store only the critical exception data. This will reduce the size of the data that needs to be stored and will ensure that the exception information is stored more reliably. However, this will not completely solve the problem.

Example Implementation:

   protected function updateLogs(TaskLog $taskLog)
    {
        if (setting('Tasks.logPerformance') === false) {
            return;
        }

        // "unique" name will be returned if one wasn't set
        $name = $taskLog->task->name;

        $errorData = null;
        if ($taskLog->error) {
            $errorData = [
                'message' => $taskLog->error->getMessage(),
                'code'    => $taskLog->error->getCode(),
                'file'    => $taskLog->error->getFile(),
                'line'    => $taskLog->error->getLine(),
            ];
            // Consider limiting stack trace if necessary:
            // $errorData['trace'] = array_slice($taskLog->error->getTrace(), 0, 5);
        }

        $data = [
            'task'     => $name,
            'type'     => $taskLog->task->getType(),
            'start'    => $taskLog->runStart->format('Y-m-d H:i:s'),
            'duration' => $taskLog->duration(),
            'output'   => $taskLog->output ?? null,
            'error'    => serialize($errorData ?? null),
        ];

        // Get existing logs
        $logs = setting("Tasks.log-{$name}");
        if (empty($logs)) {
            $logs = [];
        }

        // Make sure we have room for one more
        /** @var int $maxLogsPerTask */
        $maxLogsPerTask = setting('Tasks.maxLogsPerTask');
        if ((is_countable($logs) ? count($logs) : 0) > $maxLogsPerTask) {
            array_pop($logs);
        }

        // Add the log to the top of the array
        array_unshift($logs, $data);

        setting("Tasks.log-{$name}", $logs);
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions