Repository: NVIDIA/NVFlare

Issue:
Add an event_type argument in AnalyticsSender
Right now AnalyticsSender is sending default event type "analytix_log_stats".

However, in the ConvertToFedEvent and TBAnalyticsReceiver JSON configuration, the user needs to config the "analytix_log_stats" in the events to work.
It's not natural for user to know where this event is coming from.
If we add an "event_type" argument  in the AnalyticsSender, we can make the event sending, converting and receiving in pairs.
That would be easier for people to understand.


Discussion:

Resolving patch:
diff --git a/nvflare/app_common/app_event_type.py b/nvflare/app_common/app_event_type.py
--- a/nvflare/app_common/app_event_type.py
+++ b/nvflare/app_common/app_event_type.py
@@ -66,6 +66,3 @@ class AppEventType(object):
     CROSS_VAL_INIT = "_cross_val_init"
     VALIDATION_RESULT_RECEIVED = "_validation_result_received"
     RECEIVE_BEST_MODEL = "_receive_best_model"
-
-    ANALYTIC_EVENT_TYPE = "analytix_log_stats"
-    LOGGING_EVENT_TYPE = "analytix_logging"
diff --git a/nvflare/app_common/widgets/streaming.py b/nvflare/app_common/widgets/streaming.py
--- a/nvflare/app_common/widgets/streaming.py
+++ b/nvflare/app_common/widgets/streaming.py
@@ -23,13 +23,12 @@
 from nvflare.apis.fl_constant import EventScope, FLContextKey, ReservedKey
 from nvflare.apis.fl_context import FLContext
 from nvflare.apis.shareable import Shareable
-from nvflare.app_common.app_event_type import AppEventType
 from nvflare.widgets.widget import Widget
 
+ANALYTIC_EVENT_TYPE = "analytix_log_stats"
 
-def send_analytic_dxo(
-    comp: FLComponent, dxo: DXO, fl_ctx: FLContext, event_type: str = AppEventType.ANALYTIC_EVENT_TYPE
-):
+
+def send_analytic_dxo(comp: FLComponent, dxo: DXO, fl_ctx: FLContext, event_type: str = ANALYTIC_EVENT_TYPE):
     """Sends analytic dxo.
 
     Args:
@@ -67,14 +66,19 @@ def create_analytic_dxo(tag: str, value, data_type: AnalyticsDataType, **kwargs)
 
 
 class AnalyticsSender(Widget):
-    def __init__(self):
+    def __init__(self, event_type=ANALYTIC_EVENT_TYPE):
         """Sends analytics data.
 
-        This class implements some common methods follows signatures from PyTorch SummaryWriter.
-        It provides a convenient way for Learner to use.
+        Note::
+            This class implements some common methods follows signatures from PyTorch SummaryWriter.
+            It provides a convenient way for Learner to use.
+
+        Args:
+            event_type (str): event type to fire.
         """
         super().__init__()
         self.engine = None
+        self.event_type = event_type
 
     def handle_event(self, event_type: str, fl_ctx: FLContext):
         if event_type == EventType.START_RUN:
@@ -95,7 +99,7 @@ def _add(
             kwargs["global_step"] = global_step
         dxo = create_analytic_dxo(tag=tag, value=value, data_type=data_type, **kwargs)
         with self.engine.new_context() as fl_ctx:
-            send_analytic_dxo(self, dxo=dxo, fl_ctx=fl_ctx)
+            send_analytic_dxo(self, dxo=dxo, fl_ctx=fl_ctx, event_type=self.event_type)
 
     def add_scalar(self, tag: str, scalar: float, global_step: Optional[int] = None, **kwargs):
         """Sends a scalar.
@@ -163,7 +167,7 @@ def __init__(self, events: Optional[List[str]] = None):
         """
         super().__init__()
         if events is None:
-            events = [AppEventType.ANALYTIC_EVENT_TYPE, f"fed.{AppEventType.ANALYTIC_EVENT_TYPE}"]
+            events = [ANALYTIC_EVENT_TYPE, f"fed.{ANALYTIC_EVENT_TYPE}"]
         self.events = events
         self._save_lock = Lock()
         self._end = False


Test patch: