Expose more info from EventLoop and LogReader

Change-Id: I35c5903c4fc13ef29b1d055edb2593b8a440a220
diff --git a/aos/events/event_loop.h b/aos/events/event_loop.h
index bc5a5ae..0a22abe 100644
--- a/aos/events/event_loop.h
+++ b/aos/events/event_loop.h
@@ -219,6 +219,9 @@
                : nullptr;
   }
 
+  // Returns the channel this fetcher uses
+  const Channel *channel() const { return fetcher_->channel(); }
+
   // Returns the context holding timestamps and other metadata about the
   // message.
   const Context &context() const { return fetcher_->context(); }
@@ -226,6 +229,9 @@
   const T &operator*() const { return *get(); }
   const T *operator->() const { return get(); }
 
+  // Returns true if this fetcher is valid and connected to a channel.
+  operator bool() const { return static_cast<bool>(fetcher_); }
+
  private:
   friend class EventLoop;
   Fetcher(::std::unique_ptr<RawFetcher> fetcher)
@@ -414,6 +420,14 @@
   virtual monotonic_clock::time_point monotonic_now() = 0;
   virtual realtime_clock::time_point realtime_now() = 0;
 
+  // Returns true if the channel exists in the configuration.
+  template <typename T>
+  bool HasChannel(const std::string_view channel_name) {
+    return configuration::GetChannel(configuration_, channel_name,
+                                     T::GetFullyQualifiedName(), name(),
+                                     node()) != nullptr;
+  }
+
   // Note, it is supported to create:
   //   multiple fetchers, and (one sender or one watcher) per <name, type>
   //   tuple.
diff --git a/aos/events/logging/logger.h b/aos/events/logging/logger.h
index 34dbd24..b1434ed 100644
--- a/aos/events/logging/logger.h
+++ b/aos/events/logging/logger.h
@@ -340,18 +340,25 @@
     RemapLoggedChannel(name, T::GetFullyQualifiedName(), add_prefix);
   }
 
+  template <typename T>
+  bool HasChannel(std::string_view name) {
+    return configuration::GetChannel(log_file_header()->configuration(), name,
+                                     T::GetFullyQualifiedName(), "",
+                                     nullptr) != nullptr;
+  }
+
   SimulatedEventLoopFactory *event_loop_factory() {
     return event_loop_factory_;
   }
 
+  const LogFileHeader *log_file_header() const {
+    return &log_file_header_.message();
+  }
+
  private:
   const Channel *RemapChannel(const EventLoop *event_loop,
                               const Channel *channel);
 
-  const LogFileHeader *log_file_header() const {
-    return &log_file_header_.message();
-  }
-
   // Queues at least max_out_of_order_duration_ messages into channels_.
   void QueueMessages();
   // Handle constructing a configuration with all the additional remapped