diff --git a/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/GridReportingModule.h b/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/GridReportingModule.h
index 993a386164e2f559917403578c119bbcf3382c9f..62f4b740d029583baf15059d3b7fd86cb03cd458 100644
--- a/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/GridReportingModule.h
+++ b/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/GridReportingModule.h
@@ -10,6 +10,7 @@
 #define EVENT_LOOP_GRID__GRID_REPORTING_MODULE_H
 
 #include <EventLoop/Module.h>
+#include <vector>
 
 namespace EL
 {
@@ -21,11 +22,19 @@ namespace EL
     class GridReportingModule final : public Module
     {
       /// the panda error code for bad input files
-    public:
       static constexpr int EC_BADINPUT = 223;
 
+      /// the list of files we processed
+      std::vector<std::string> m_files;
+
+      /// the number of events we processed
+      unsigned m_eventsProcessed = 0;
+
     public:
-      virtual void reportInputFailure (ModuleData& data);
+      virtual ::StatusCode onNewInputFile (ModuleData& data) override;
+      virtual ::StatusCode onExecute (ModuleData& data) override;
+      virtual ::StatusCode postFileClose (ModuleData& data) override;
+      virtual void reportInputFailure (ModuleData& data) override;
     };
   }
 }
diff --git a/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Job.h b/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Job.h
index cf46ca6d00a0fa483b5a7f66b42f4fa6536f1383..3f2ad28ee1b40f5f84342fb321895015318bbf9a 100644
--- a/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Job.h
+++ b/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Job.h
@@ -480,6 +480,9 @@ namespace EL
     static const std::string optOfficial;
     static const std::string optVoms;
 
+    /// whether to use grid reporting even when not running on the grid
+    static const std::string optGridReporting;
+
     /// these options are defined in \ref SH::MetaNames
     /// \{
 
diff --git a/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Worker.h b/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Worker.h
index 04a9f2e6a535d9d82271d0ee17fde4be2d7e3eaa..78e76074acc9ab72e79d12ba02ac3a6e3c6d6e64 100644
--- a/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Worker.h
+++ b/PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/Worker.h
@@ -244,14 +244,6 @@ namespace EL
   public:
     ::StatusCode gridExecute (const std::string& sampleName);
 
-
-  private:
-    void gridNotifyJobFinished(uint64_t eventsProcessed,
-                           const std::vector<std::string>& fileList);
-
-  private:
-    void gridAbort();
-
   private:    
     enum GridErrorCodes {
       EC_FAIL = 220,
diff --git a/PhysicsAnalysis/D3PDTools/EventLoop/Root/GridReportingModule.cxx b/PhysicsAnalysis/D3PDTools/EventLoop/Root/GridReportingModule.cxx
index 738c7d7450c4e76e41d30022d43114e934b7af8a..5ee0e17d05cc1766e4557eaa08f7a414a672cb66 100644
--- a/PhysicsAnalysis/D3PDTools/EventLoop/Root/GridReportingModule.cxx
+++ b/PhysicsAnalysis/D3PDTools/EventLoop/Root/GridReportingModule.cxx
@@ -13,6 +13,9 @@
 #include <EventLoop/GridReportingModule.h>
 
 #include <EventLoop/MessageCheck.h>
+#include <EventLoop/ModuleData.h>
+#include <algorithm>
+#include <fstream>
 
 //
 // method implementations
@@ -22,6 +25,48 @@ namespace EL
 {
   namespace Detail
   {
+    ::StatusCode GridReportingModule ::
+    onNewInputFile (ModuleData& data)
+    {
+      if (std::find (m_files.begin(), m_files.end(), data.m_inputFileUrl) == m_files.end())
+        m_files.push_back (data.m_inputFileUrl);
+      return ::StatusCode::SUCCESS;
+    }
+
+
+
+    ::StatusCode GridReportingModule ::
+    onExecute (ModuleData& /*data*/)
+    {
+      ++m_eventsProcessed;
+      return ::StatusCode::SUCCESS;
+    }
+
+
+
+    ::StatusCode GridReportingModule ::
+    postFileClose (ModuleData& /*data*/)
+    {
+      using namespace msgEventLoop;
+
+      // createJobSummary
+      std::ofstream summaryfile("../AthSummary.txt");
+      if (summaryfile.is_open()) {
+        unsigned int nFiles = m_files.size();
+        summaryfile << "Files read: " << nFiles << std::endl;
+        for (auto& file : m_files)
+          summaryfile << "  " << file << std::endl;
+        summaryfile << "Events Read:    " << m_eventsProcessed << std::endl;
+        summaryfile.close();
+      }
+      else {
+        ANA_MSG_WARNING ("Failed to write summary file.");
+      }
+      return ::StatusCode::SUCCESS;
+    }
+
+
+
     void GridReportingModule ::
     reportInputFailure (ModuleData& /*data*/)
     {
diff --git a/PhysicsAnalysis/D3PDTools/EventLoop/Root/Job.cxx b/PhysicsAnalysis/D3PDTools/EventLoop/Root/Job.cxx
index 64f84027bd5dfba3ff5a18b0e7ee0a6adc9df94a..c05ab3a9af1da952bb39b8c2336c19710bb02035 100644
--- a/PhysicsAnalysis/D3PDTools/EventLoop/Root/Job.cxx
+++ b/PhysicsAnalysis/D3PDTools/EventLoop/Root/Job.cxx
@@ -88,6 +88,7 @@ namespace EL
   const std::string Job::optGridCpuTimePerEvent = "nc_cpuTimePerEvent";
   const std::string Job::optGridMaxWalltime = "nc_maxWalltime";
   const std::string Job::optGridAvoidVP = "nc_avoidVP";
+  const std::string Job::optGridReporting = "nc_gridReporting";
   const std::string Job::optBatchSharedFileSystem = "nc_sharedFileSystem";
   const std::string Job::optBatchSlurmExtraConfigLines = "nc_SlurmExtraConfig";
   const std::string Job::optBatchSlurmWrapperExec = "nc_SlurmWrapperExec";
diff --git a/PhysicsAnalysis/D3PDTools/EventLoop/Root/Worker.cxx b/PhysicsAnalysis/D3PDTools/EventLoop/Root/Worker.cxx
index 7c1bc3ebcac2e8599f0b60da59f3a97b3f70d518..9ac0967d5c6e0593bbf91b7856814055b1725922 100644
--- a/PhysicsAnalysis/D3PDTools/EventLoop/Root/Worker.cxx
+++ b/PhysicsAnalysis/D3PDTools/EventLoop/Root/Worker.cxx
@@ -387,6 +387,8 @@ namespace EL
       m_modules.push_back (std::make_unique<Detail::TEventModule> ());
     m_modules.push_back (std::make_unique<Detail::LeakCheckModule> ());
     m_modules.push_back (std::make_unique<Detail::StopwatchModule> ());
+    if (metaData()->castBool (Job::optGridReporting, false))
+      m_modules.push_back (std::make_unique<Detail::GridReportingModule>());
     if (metaData()->castBool (Job::optAlgorithmTimer, false))
       m_modules.push_back (std::make_unique<Detail::AlgorithmTimerModule> ());
     m_modules.push_back (std::make_unique<Detail::FileExecutedModule> ());
@@ -977,6 +979,7 @@ namespace EL
 
     const std::string location = ".";
 
+    mo->setBool (Job::optGridReporting, true);
     setMetaData (mo);
     setOutputHist (location);
     setSegmentName ("output");
@@ -1003,7 +1006,6 @@ namespace EL
 
     setJobConfig (std::move (*jobConfig));
 
-    addModule (std::make_unique<Detail::GridReportingModule> ());
     ANA_CHECK (initialize());
 
     std::vector<std::string> fileList;
@@ -1041,28 +1043,8 @@ namespace EL
     ANA_MSG_INFO ("Loop finished.");
     ANA_MSG_INFO ("Read " << nEvents << " events in " << nFiles << " files.");
 
-    gridNotifyJobFinished(eventsProcessed(), fileList);
-
     ANA_MSG_INFO ("EventLoop Grid worker finished");
     ANA_MSG_INFO ("Saving output");
     return ::StatusCode::SUCCESS;
   }
-
-  void Worker::gridNotifyJobFinished(uint64_t eventsProcessed,
-                                     const std::vector<std::string>& fileList) {
-    // createJobSummary
-    std::ofstream summaryfile("../AthSummary.txt");
-    if (summaryfile.is_open()) {
-      unsigned int nFiles = fileList.size();
-      summaryfile << "Files read: " << nFiles << std::endl;
-      for (unsigned int i = 0; i < nFiles; i++) {
-        summaryfile << "  " << fileList.at(i) << std::endl;
-      }
-      summaryfile << "Events Read:    " << eventsProcessed << std::endl;
-      summaryfile.close();
-    }
-    else {
-      //cout << "Failed to write summary file.\n";
-    }
-  }
 }