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.