diff --git a/docs/guide/runtime-logging.md b/docs/guide/runtime-logging.md
index c34daaf..6e00bb8 100644
--- a/docs/guide/runtime-logging.md
+++ b/docs/guide/runtime-logging.md
@@ -15,6 +15,9 @@ Basic logging is as simple as calling one method:
 \Yii::info('Hello, I am a test log message');
 ```
 
+You can log simple strings as well as more complex data structures such as arrays or objects.
+When logging data that is not a string the defaulf yii log targets will serialize the value using [[yii\helpers\Vardumper::export()]].
+
 ### Message category
 
 Additionally to the message itself message category could be specified in order to allow filtering such messages and
diff --git a/extensions/debug/panels/LogPanel.php b/extensions/debug/panels/LogPanel.php
index af92474..35b07ce 100644
--- a/extensions/debug/panels/LogPanel.php
+++ b/extensions/debug/panels/LogPanel.php
@@ -63,7 +63,6 @@ class LogPanel extends Panel
     {
         $target = $this->module->logTarget;
         $messages = $target->filterMessages($target->messages, Logger::LEVEL_ERROR | Logger::LEVEL_INFO | Logger::LEVEL_WARNING | Logger::LEVEL_TRACE);
-
         return ['messages' => $messages];
     }
 
diff --git a/extensions/debug/panels/ProfilingPanel.php b/extensions/debug/panels/ProfilingPanel.php
index 635f4f8..9f08fdc 100644
--- a/extensions/debug/panels/ProfilingPanel.php
+++ b/extensions/debug/panels/ProfilingPanel.php
@@ -69,7 +69,6 @@ class ProfilingPanel extends Panel
     {
         $target = $this->module->logTarget;
         $messages = $target->filterMessages($target->messages, Logger::LEVEL_PROFILE);
-
         return [
             'memory' => memory_get_peak_usage(),
             'time' => microtime(true) - YII_BEGIN_TIME,
diff --git a/extensions/debug/views/default/panels/log/detail.php b/extensions/debug/views/default/panels/log/detail.php
index aad9789..86f115d 100644
--- a/extensions/debug/views/default/panels/log/detail.php
+++ b/extensions/debug/views/default/panels/log/detail.php
@@ -1,6 +1,7 @@
 <?php
 use yii\helpers\Html;
 use yii\grid\GridView;
+use yii\helpers\VarDumper;
 use yii\log\Logger;
 
 ?>
@@ -51,8 +52,7 @@ echo GridView::widget([
         [
             'attribute' => 'message',
             'value' => function ($data) {
-                $message = nl2br(Html::encode($data['message']));
-
+                $message = Html::encode(is_string($data['message']) ? $data['message'] : VarDumper::export($data['message']));
                 if (!empty($data['trace'])) {
                     $message .= Html::ul($data['trace'], [
                         'class' => 'trace',
@@ -61,7 +61,6 @@ echo GridView::widget([
                         }
                     ]);
                 };
-
                 return $message;
             },
             'format' => 'html',
diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md
index 6733d2c..01c2167 100644
--- a/framework/CHANGELOG.md
+++ b/framework/CHANGELOG.md
@@ -60,6 +60,7 @@ Yii Framework 2 Change Log
 - Enh #3222: Added `useTablePrefix` option to the model generator for Gii (horizons2)
 - Enh #3230: Added `yii\filters\AccessControl::user` to support access control with different actors (qiangxue)
 - Enh #3232: Added `export()` and `exportAsString()` methods to `yii\helpers\BaseVarDumper` (klimov-paul)
+- Enh #3244: Allow logging complex data such as arrays and object via the log system (cebe)
 - Enh #3252: Added support for case insensitive matching using ILIKE to PostgreSQL QueryBuilder (cebe)
 - Enh #3284: Added support for checking multiple ETags by `yii\filters\HttpCache` (qiangxue)
 - Enh #3298: Supported configuring `View::theme` using a class name (netyum, qiangxue)
@@ -106,6 +107,8 @@ Yii Framework 2 Change Log
 - Chg: `yii\data\ActiveDataProvider::$query` will not be modified directly with pagination and sorting anymore so it will be reuseable (cebe)
 - Chg: Removed `yii\rest\ActiveController::$transactional` property and connected functionality (samdark)
 - Chg: Changed the default value of the `keyPrefix` property of cache components to be null (qiangxue)
+- Chg: Added `prefix` column to `yii\log\DbTarget` to have the same amount of information logged as in files and emails (cebe)
+
 
 2.0.0-beta April 13, 2014
 -------------------------
diff --git a/framework/UPGRADE.md b/framework/UPGRADE.md
index a437c01..615aae1 100644
--- a/framework/UPGRADE.md
+++ b/framework/UPGRADE.md
@@ -43,4 +43,7 @@ Upgrade from Yii 2.0 Beta
   of the callable to be `function ($model, $key, $index, $widget)`. The `$key` parameter was newly added
   in this release.
 
-* `yii\console\controllers\AssetController` is now using hashes instead of timestamps. Replace all `{ts}` with `{hash}`.
\ No newline at end of file
+* `yii\console\controllers\AssetController` is now using hashes instead of timestamps. Replace all `{ts}` with `{hash}`.
+
+* The database table of the `yii\log\DbTarget` now needs a `prefix` column to store context information.
+  You can add it with `ALTER TABLE log ADD COLUMN prefix TEXT AFTER log_time;`.
diff --git a/framework/helpers/BaseVarDumper.php b/framework/helpers/BaseVarDumper.php
index 882fa4e..2ed84fa 100644
--- a/framework/helpers/BaseVarDumper.php
+++ b/framework/helpers/BaseVarDumper.php
@@ -133,6 +133,8 @@ class BaseVarDumper
      * This method is similar to `var_export()`. The main difference is that
      * it generates more compact string representation using short array syntax.
      *
+     * It also handles objects by using the PHP functions serialize() and unserialize().
+     *
      * PHP 5.4 or above is required to parse the exported value.
      *
      * @param mixed $var the variable to be exported.
diff --git a/framework/log/DbTarget.php b/framework/log/DbTarget.php
index 52e1f23..86d0edd 100644
--- a/framework/log/DbTarget.php
+++ b/framework/log/DbTarget.php
@@ -16,7 +16,7 @@ use yii\di\Instance;
  * DbTarget stores log messages in a database table.
  *
  * By default, DbTarget stores the log messages in a DB table named 'log'. This table
- * must be pre-created. The table name can be changed by setting [[logTable]].
+ * must be pre-created. The table name can be changed by setting the [[logTable]] property.
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
  * @since 2.0
@@ -39,6 +39,7 @@ class DbTarget extends Target
      *     level    INTEGER,
      *     category VARCHAR(255),
      *     log_time INTEGER,
+     *     prefix   TEXT,
      *     message  TEXT,
      *     INDEX idx_log_level (level),
      *     INDEX idx_log_category (category)
@@ -55,6 +56,7 @@ class DbTarget extends Target
      */
     public $logTable = '{{%log}}';
 
+
     /**
      * Initializes the DbTarget component.
      * This method will initialize the [[db]] property to make sure it refers to a valid DB connection.
@@ -72,15 +74,20 @@ class DbTarget extends Target
     public function export()
     {
         $tableName = $this->db->quoteTableName($this->logTable);
-        $sql = "INSERT INTO $tableName ([[level]], [[category]], [[log_time]], [[message]])
-                VALUES (:level, :category, :log_time, :message)";
+        $sql = "INSERT INTO $tableName ([[level]], [[category]], [[log_time]], [[prefix]], [[message]])
+                VALUES (:level, :category, :log_time, :prefix, :message)";
         $command = $this->db->createCommand($sql);
         foreach ($this->messages as $message) {
+            list($text, $level, $category, $timestamp) = $message;
+            if (!is_string($text)) {
+                $text = var_export($text, true);
+            }
             $command->bindValues([
-                ':level' => $message[1],
-                ':category' => $message[2],
-                ':log_time' => $message[3],
-                ':message' => $message[0],
+                ':level' => $level,
+                ':category' => $category,
+                ':log_time' => $timestamp,
+                ':prefix' => $this->getMessagePrefix($message),
+                ':message' => $text,
             ])->execute();
         }
     }
diff --git a/framework/log/Dispatcher.php b/framework/log/Dispatcher.php
index a71c8cd..eda796d 100644
--- a/framework/log/Dispatcher.php
+++ b/framework/log/Dispatcher.php
@@ -13,14 +13,14 @@ use yii\base\Component;
 /**
  * Dispatcher manages a set of [[Target|log targets]].
  *
- * Dispatcher implements [[dispatch()]] that forwards the log messages from [[Logger]] to
+ * Dispatcher implements the [[dispatch()]]-method that forwards the log messages from a [[Logger]] to
  * the registered log [[targets]].
  *
- * Dispatcher is registered as a core application component and can be accessed using `Yii::$app->log`.
+ * An instance of Dispatcher is registered as a core application component and can be accessed using `Yii::$app->log`.
  *
  * You may configure the targets in application configuration, like the following:
  *
- * ~~~
+ * ```php
  * [
  *     'components' => [
  *         'log' => [
@@ -41,14 +41,13 @@ use yii\base\Component;
  *         ],
  *     ],
  * ]
- * ~~~
+ * ```
  *
- * Each log target can have a name and can be referenced via the [[targets]] property
- * as follows:
+ * Each log target can have a name and can be referenced via the [[targets]] property as follows:
  *
- * ~~~
+ * ```php
  * Yii::$app->log->targets['file']->enabled = false;
- * ~~~
+ * ```
  *
  * @property integer $flushInterval How many messages should be logged before they are sent to targets. This
  * method returns the value of [[Logger::flushInterval]].
@@ -66,6 +65,7 @@ class Dispatcher extends Component
      * or the configuration for creating the log target instance.
      */
     public $targets = [];
+
     /**
      * @var Logger the logger.
      */
@@ -77,6 +77,7 @@ class Dispatcher extends Component
      */
     public function __construct($config = [])
     {
+        // ensure logger gets set before any other config option
         if (isset($config['logger'])) {
             $this->setLogger($config['logger']);
             unset($config['logger']);
diff --git a/framework/log/EmailTarget.php b/framework/log/EmailTarget.php
index 2564068..7259a2a 100644
--- a/framework/log/EmailTarget.php
+++ b/framework/log/EmailTarget.php
@@ -35,6 +35,7 @@ class EmailTarget extends Target
      */
     public $mail = 'mail';
 
+
     /**
      * @inheritdoc
      */
diff --git a/framework/log/FileTarget.php b/framework/log/FileTarget.php
index c1bf807..06edb42 100644
--- a/framework/log/FileTarget.php
+++ b/framework/log/FileTarget.php
@@ -57,6 +57,7 @@ class FileTarget extends Target
      */
     public $rotateByCopy = false;
 
+
     /**
      * Initializes the route.
      * This method is invoked after the route is created by the route manager.
diff --git a/framework/log/Logger.php b/framework/log/Logger.php
index 029f474..540f79f 100644
--- a/framework/log/Logger.php
+++ b/framework/log/Logger.php
@@ -13,7 +13,7 @@ use yii\base\Component;
 /**
  * Logger records logged messages in memory and sends them to different targets if [[dispatcher]] is set.
  *
- * Logger can be accessed via `Yii::getLogger()`. You can call the method [[log()]] to record a single log message.
+ * A Logger instance can be accessed via `Yii::getLogger()`. You can call the method [[log()]] to record a single log message.
  * For convenience, a set of shortcut methods are provided for logging messages of various severity levels
  * via the [[Yii]] class:
  *
@@ -25,7 +25,8 @@ use yii\base\Component;
  * - [[Yii::endProfile()]]
  *
  * When the application ends or [[flushInterval]] is reached, Logger will call [[flush()]]
- * to send logged messages to different log targets, such as file, email, Web, with the help of [[dispatcher]].
+ * to send logged messages to different log targets, such as [[FileTarget|file]], [[EmailTarget|email]],
+ * or [[DbTarget|database]], with the help of the [[dispatcher]].
  *
  * @property array $dbProfiling The first element indicates the number of SQL statements executed, and the
  * second element the total time spent in SQL execution. This property is read-only.
@@ -122,7 +123,8 @@ class Logger extends Component
      * Logs a message with the given type and category.
      * If [[traceLevel]] is greater than 0, additional call stack information about
      * the application code will be logged as well.
-     * @param string $message the message to be logged.
+     * @param string|array $message the message to be logged. This can be a simple string or a more
+     * complex data structure that will be handled by a [[Target|log target]].
      * @param integer $level the level of the message. This must be one of the following:
      * `Logger::LEVEL_ERROR`, `Logger::LEVEL_WARNING`, `Logger::LEVEL_INFO`, `Logger::LEVEL_TRACE`,
      * `Logger::LEVEL_PROFILE_BEGIN`, `Logger::LEVEL_PROFILE_END`.
diff --git a/framework/log/SyslogTarget.php b/framework/log/SyslogTarget.php
index 8494eeb..c6ba3e2 100644
--- a/framework/log/SyslogTarget.php
+++ b/framework/log/SyslogTarget.php
@@ -8,6 +8,7 @@
 namespace yii\log;
 
 use Yii;
+use yii\helpers\VarDumper;
 
 /**
  * SyslogTarget writes log to syslog.
@@ -39,6 +40,7 @@ class SyslogTarget extends Target
         Logger::LEVEL_ERROR => LOG_ERR,
     ];
 
+
     /**
      * Writes log messages to syslog
      */
@@ -59,11 +61,10 @@ class SyslogTarget extends Target
         list($text, $level, $category, $timestamp) = $message;
         $level = Logger::getLevelName($level);
         if (!is_string($text)) {
-            $text = var_export($text, true);
+            $text = VarDumper::export($text, true);
         }
 
-        $prefix = $this->prefix ? call_user_func($this->prefix, $message) : $this->getMessagePrefix($message);
-
+        $prefix = $this->getMessagePrefix($message);
         return "{$prefix}[$level][$category] $text";
     }
 }
diff --git a/framework/log/Target.php b/framework/log/Target.php
index 950852f..4b27ddc 100644
--- a/framework/log/Target.php
+++ b/framework/log/Target.php
@@ -60,9 +60,12 @@ abstract class Target extends Component
      */
     public $logVars = ['_GET', '_POST', '_FILES', '_COOKIE', '_SESSION', '_SERVER'];
     /**
-     * @var callable a PHP callable that returns a string to be prefix to every exported message.
-     * If not set, [[getMessagePrefix()]] will be used, which prefixes user IP, user ID and session ID
-     * to every message. The signature of the callable should be `function ($message)`.
+     * @var callable a PHP callable that returns a string to be prefixed to every exported message.
+     *
+     * If not set, [[getMessagePrefix()]] will be used, which prefixes the message with context information
+     * such as user IP, user ID and session ID.
+     *
+     * The signature of the callable should be `function ($message)`.
      */
     public $prefix;
     /**
@@ -79,6 +82,7 @@ abstract class Target extends Component
 
     private $_levels = 0;
 
+
     /**
      * Exports log [[messages]] to a specific destination.
      * Child classes must implement this method.
@@ -177,7 +181,8 @@ abstract class Target extends Component
 
     /**
      * Filters the given messages according to their categories and levels.
-     * @param array $messages messages to be filtered
+     * @param array $messages messages to be filtered.
+     * The message structure follows that in [[Logger::messages]].
      * @param integer $levels the message levels to filter by. This is a bitmap of
      * level values. Value 0 means allowing all levels.
      * @param array $categories the message categories to filter by. If empty, it means all categories are allowed.
@@ -214,14 +219,13 @@ abstract class Target extends Component
                 unset($messages[$i]);
             }
         }
-
         return $messages;
     }
 
     /**
-     * Formats a log message.
-     * The message structure follows that in [[Logger::messages]].
+     * Formats a log message for display as a string.
      * @param array $message the log message to be formatted.
+     * The message structure follows that in [[Logger::messages]].
      * @return string the formatted message
      */
     public function formatMessage($message)
@@ -229,30 +233,38 @@ abstract class Target extends Component
         list($text, $level, $category, $timestamp) = $message;
         $level = Logger::getLevelName($level);
         if (!is_string($text)) {
-            $text = var_export($text, true);
+            $text = VarDumper::export($text, true);
         }
 
-        $prefix = $this->prefix ? call_user_func($this->prefix, $message) : $this->getMessagePrefix($message);
-
+        $prefix = $this->getMessagePrefix($message);
         return date('Y-m-d H:i:s', $timestamp) . " {$prefix}[$level][$category] $text";
     }
 
     /**
      * Returns a string to be prefixed to the given message.
+     * If [[prefix]] is configured it will return the result of the callback.
      * The default implementation will return user IP, user ID and session ID as a prefix.
-     * @param array $message the message being exported
+     * @param array $message the message being exported.
+     * The message structure follows that in [[Logger::messages]].
      * @return string the prefix string
      */
     public function getMessagePrefix($message)
     {
+        if ($this->prefix !== null) {
+            return call_user_func($this->prefix, $message);
+        }
+
         $request = Yii::$app->getRequest();
         $ip = $request instanceof Request ? $request->getUserIP() : '-';
+
         /** @var \yii\web\User $user */
         $user = Yii::$app->has('user', true) ? Yii::$app->get('user') : null;
         $userID = $user ? $user->getId(false) : '-';
+
         /** @var \yii\web\Session $session */
         $session = Yii::$app->has('session', true) ? Yii::$app->get('session') : null;
         $sessionID = $session && $session->getIsActive() ? $session->getId() : '-';
+
         return "[$ip][$userID][$sessionID]";
     }
 }