diff --git a/core/modules/migrate/src/MigrateExecutable.php b/core/modules/migrate/src/MigrateExecutable.php
index f33781e..3cb94df 100644
--- a/core/modules/migrate/src/MigrateExecutable.php
+++ b/core/modules/migrate/src/MigrateExecutable.php
@@ -27,20 +27,6 @@ class MigrateExecutable implements MigrateExecutableInterface {
   protected $migration;
 
   /**
-   * The number of successfully imported rows since feedback was given.
-   *
-   * @var int
-   */
-  protected $successesSinceFeedback;
-
-  /**
-   * The number of rows that were successfully processed.
-   *
-   * @var int
-   */
-  protected $totalSuccesses;
-
-  /**
    * Status of one row.
    *
    * The value is a MigrateIdMapInterface::STATUS_* constant, for example:
@@ -51,15 +37,6 @@ class MigrateExecutable implements MigrateExecutableInterface {
   protected $sourceRowStatus;
 
   /**
-   * The number of rows processed.
-   *
-   * The total attempted, whether or not they were successful.
-   *
-   * @var int
-   */
-  protected $totalProcessed;
-
-  /**
    * The queued messages not yet saved.
    *
    * Each element in the array is an array with two keys:
@@ -81,6 +58,13 @@ class MigrateExecutable implements MigrateExecutableInterface {
   protected $options;
 
   /**
+   * An object for tracking statistics.
+   *
+   * @var MigrationStatistics
+   */
+  protected $statistics;
+
+  /**
    * The PHP max_execution_time.
    *
    * @var int
@@ -116,13 +100,6 @@ class MigrateExecutable implements MigrateExecutableInterface {
   protected $sourceIdValues;
 
   /**
-   * The number of rows processed since feedback was given.
-   *
-   * @var int
-   */
-  protected $processedSinceFeedback = 0;
-
-  /**
    * The PHP memory_limit expressed in bytes.
    *
    * @var int
@@ -183,10 +160,14 @@ class MigrateExecutable implements MigrateExecutableInterface {
    *
    * @throws \Drupal\migrate\MigrateException
    */
-  public function __construct(MigrationInterface $migration, MigrateMessageInterface $message) {
+  public function __construct(MigrationInterface $migration, MigrateMessageInterface $message, MigrationStatisticsInterface $statistics = NULL) {
     $this->migration = $migration;
     $this->message = $message;
     $this->migration->getIdMap()->setMessage($message);
+    if (is_null($statistics)) {
+      $statistics = new MigrationStatistics();
+    }
+    $this->statistics = $statistics;
     // Record the memory limit in bytes
     $limit = trim(ini_get('memory_limit'));
     if ($limit == '-1') {
@@ -290,8 +271,7 @@ public function import() {
             if ($destination_id_values !== TRUE) {
               $id_map->saveIdMapping($row, $destination_id_values, $this->sourceRowStatus, $this->rollbackAction);
             }
-            $this->successesSinceFeedback++;
-            $this->totalSuccesses++;
+            $this->statistics->incrementSuccesses();
           }
           else {
             $id_map->saveIdMapping($row, array(), MigrateIdMapInterface::STATUS_FAILED, $this->rollbackAction);
@@ -312,8 +292,7 @@ public function import() {
           $this->handleException($e);
         }
       }
-      $this->totalProcessed++;
-      $this->processedSinceFeedback++;
+      $this->statistics->incrementProcessed();
       if ($high_water_property = $this->migration->get('highWaterProperty')) {
         $this->migration->saveHighWater($row->getSourceProperty($high_water_property['name']));
       }
@@ -605,6 +584,15 @@ protected function getTimeElapsed() {
   }
 
   /**
+   * Return an object containing current execution statistics for a migration.
+   *
+   * @return MigrationStatistics
+   */
+  public function getStatistics() {
+    return $this->statistics;
+  }
+
+  /**
    * Takes an Exception object and both saves and displays it.
    *
    * Pulls in additional information on the location triggering the exception.
diff --git a/core/modules/migrate/src/MigrateExecutableInterface.php b/core/modules/migrate/src/MigrateExecutableInterface.php
index 4a362fe..50930b3 100644
--- a/core/modules/migrate/src/MigrateExecutableInterface.php
+++ b/core/modules/migrate/src/MigrateExecutableInterface.php
@@ -45,6 +45,13 @@ public function processRow(Row $row, array $process = NULL, $value = NULL);
   public function getTimeLimit();
 
   /**
+   * Return an object containing current execution statistics for a migration.
+   *
+   * @return MigrationStatistics
+   */
+  public function getStatistics();
+
+  /**
    * Passes messages through to the map class.
    *
    * @param string $message
diff --git a/core/modules/migrate/src/MigrationStatistics.php b/core/modules/migrate/src/MigrationStatistics.php
new file mode 100644
index 0000000..a85beaf
--- /dev/null
+++ b/core/modules/migrate/src/MigrationStatistics.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\MigrationStatistics.
+ */
+
+namespace Drupal\migrate;
+
+/**
+ * Defines the migration statistics class.
+ */
+class MigrationStatistics implements MigrationStatisticsInterface {
+
+  /**
+   * The number of successfully imported rows since feedback was given.
+   *
+   * @var int
+   */
+  protected $successesSinceFeedback = 0;
+
+  /**
+   * The number of rows that were successfully processed.
+   *
+   * @var int
+   */
+  protected $totalSuccesses = 0;
+
+  /**
+   * The number of rows processed.
+   *
+   * The total attempted, whether or not they were successful.
+   *
+   * @var int
+   */
+  protected $totalProcessed = 0;
+
+  /**
+   * The number of rows processed since feedback was given.
+   *
+   * @var int
+   */
+  protected $processedSinceFeedback = 0;
+
+  /**
+   * Returns the number of items successfully imported since the last feedback.
+   *
+   * @param boolean $reset
+   *   TRUE to reset the number of successes since feedback to 0.
+   *
+   * @return int
+   *   The number of successes since last feedback.
+   */
+  public function getSuccessesSinceFeedback($reset = FALSE) {
+    $num_successes = $this->successesSinceFeedback;
+    if ($reset) {
+      $this->successesSinceFeedback = 0;
+    }
+    return $num_successes;
+  }
+
+  /**
+   * Returns the number of items successfully imported on this run.
+   *
+   * @return int
+   *   The total number of successes.
+   */
+  public function getTotalSuccesses() {
+    return $this->totalSuccesses;
+  }
+
+  /**
+   * Increment the success statistics.
+   */
+  public function incrementSuccesses() {
+    $this->successesSinceFeedback++;
+    $this->totalSuccesses++;
+  }
+
+  /**
+   * Returns the number of items processed since the last feedback.
+   *
+   * @param boolean $reset
+   *   TRUE to reset the number of processed since feedback to 0.
+   *
+   * @return int
+   *   The number of items processed since last feedback.
+   */
+  public function getProcessedSinceFeedback($reset = FALSE) {
+    $num_processed = $this->processedSinceFeedback;
+    if ($reset) {
+      $this->processedSinceFeedback = 0;
+    }
+    return $num_processed;
+  }
+
+  /**
+   * Returns the number of items processed on this run.
+   *
+   * @return int
+   *   The total number of items processed.
+   */
+  public function getTotalProcessed() {
+    return $this->totalProcessed;
+  }
+
+  /**
+   * Increment the processed statistics.
+   */
+  public function incrementProcessed() {
+    $this->processedSinceFeedback++;
+    $this->totalProcessed++;
+  }
+
+}
diff --git a/core/modules/migrate/src/MigrationStatisticsInterface.php b/core/modules/migrate/src/MigrationStatisticsInterface.php
new file mode 100644
index 0000000..d59d6c1
--- /dev/null
+++ b/core/modules/migrate/src/MigrationStatisticsInterface.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\migrate\MigrationStatisticsInterface.
+ */
+
+namespace Drupal\migrate;
+
+/**
+ * Defines the migration statistics interface.
+ */
+interface MigrationStatisticsInterface {
+
+  /**
+   * Returns the number of items successfully imported since the last feedback.
+   *
+   * @param boolean $reset
+   *   TRUE to reset the number of successes since feedback to 0.
+   *
+   * @return int
+   *   The number of successes since last feedback.
+   */
+  public function getSuccessesSinceFeedback($reset = FALSE);
+
+  /**
+   * Returns the number of items successfully imported on this run.
+   *
+   * @return int
+   *   The total number of successes.
+   */
+  public function getTotalSuccesses();
+
+  /**
+   * Increment the success statistics.
+   */
+  public function incrementSuccesses();
+
+  /**
+   * Returns the number of items processed since the last feedback.
+   *
+   * @param boolean $reset
+   *   TRUE to reset the number of processed since feedback to 0.
+   *
+   * @return int
+   *   The number of items processed since last feedback.
+   */
+  public function getProcessedSinceFeedback($reset = FALSE);
+
+  /**
+   * Returns the number of items processed on this run.
+   *
+   * @return int
+   *   The total number of items processed.
+   */
+  public function getTotalProcessed();
+
+  /**
+   * Increment the processed statistics.
+   */
+  public function incrementProcessed();
+
+}
diff --git a/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php
index f862ae8..2ab4951 100644
--- a/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php
+++ b/core/modules/migrate/tests/src/Unit/MigrateExecutableTest.php
@@ -121,10 +121,11 @@ public function testImportWithValidRow() {
 
     $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
 
-    $this->assertSame(1, $this->executable->getSuccessesSinceFeedback());
-    $this->assertSame(1, $this->executable->getTotalSuccesses());
-    $this->assertSame(1, $this->executable->getTotalProcessed());
-    $this->assertSame(1, $this->executable->getProcessedSinceFeedback());
+    $statistics = $this->executable->getStatistics();
+    $this->assertSame(1, $statistics->getSuccessesSinceFeedback());
+    $this->assertSame(1, $statistics->getTotalSuccesses());
+    $this->assertSame(1, $statistics->getTotalProcessed());
+    $this->assertSame(1, $statistics->getProcessedSinceFeedback());
   }
 
   /**
@@ -171,10 +172,11 @@ public function testImportWithValidRowWithoutDestinationId() {
 
     $this->assertSame(MigrationInterface::RESULT_COMPLETED, $this->executable->import());
 
-    $this->assertSame(1, $this->executable->getSuccessesSinceFeedback());
-    $this->assertSame(1, $this->executable->getTotalSuccesses());
-    $this->assertSame(1, $this->executable->getTotalProcessed());
-    $this->assertSame(1, $this->executable->getProcessedSinceFeedback());
+    $statistics = $this->executable->getStatistics();
+    $this->assertSame(1, $statistics->getSuccessesSinceFeedback());
+    $this->assertSame(1, $statistics->getTotalSuccesses());
+    $this->assertSame(1, $statistics->getTotalProcessed());
+    $this->assertSame(1, $statistics->getProcessedSinceFeedback());
   }
 
   /**
diff --git a/core/modules/migrate/tests/src/Unit/TestMigrateExecutable.php b/core/modules/migrate/tests/src/Unit/TestMigrateExecutable.php
index f26bc56..11f22c1 100644
--- a/core/modules/migrate/tests/src/Unit/TestMigrateExecutable.php
+++ b/core/modules/migrate/tests/src/Unit/TestMigrateExecutable.php
@@ -77,46 +77,6 @@ public function getMaxExecTime() {
   }
 
   /**
-   * Allows access to protected successesSinceFeedback property.
-   *
-   * @return int
-   *   The value of the protected property.
-   */
-  public function getSuccessesSinceFeedback() {
-    return $this->successesSinceFeedback;
-  }
-
-  /**
-   * Allows access to protected totalSuccesses property.
-   *
-   * @return int
-   *   The value of the protected property.
-   */
-  public function getTotalSuccesses() {
-    return $this->totalSuccesses;
-  }
-
-  /**
-   * Allows access to protected totalProcessed property.
-   *
-   * @return int
-   *   The value of the protected property.
-   */
-  public function getTotalProcessed() {
-    return $this->totalProcessed;
-  }
-
-  /**
-   * Allows access to protected processedSinceFeedback property.
-   *
-   * @return int
-   *   The value of the protected property.
-   */
-  public function getProcessedSinceFeedback() {
-    return $this->processedSinceFeedback;
-  }
-
-  /**
    * Allows access to protected maxExecTimeExceeded method.
    *
    * @return bool
