@@ -30,6 +30,26 @@ namespace Plugin {
3030
3131 const uint32_t POPULATE_DEVICE_INFO_RETRY_MS = 3000 ;
3232
33+ class AnalyticsConfig : public Core ::JSON::Container {
34+ private:
35+ AnalyticsConfig (const AnalyticsConfig&) = delete ;
36+ AnalyticsConfig& operator =(const AnalyticsConfig&) = delete ;
37+
38+ public:
39+ AnalyticsConfig ()
40+ : Core::JSON::Container()
41+ , EventsMap()
42+ {
43+ Add (_T (" eventsmap" ), &EventsMap);
44+ }
45+ ~AnalyticsConfig ()
46+ {
47+ }
48+
49+ public:
50+ Core::JSON::String EventsMap;
51+ };
52+
3353 SERVICE_REGISTRATION (AnalyticsImplementation, 1 , 0 );
3454
3555 AnalyticsImplementation::AnalyticsImplementation ():
@@ -146,6 +166,21 @@ namespace Plugin {
146166 backend.second ->Configure (shell, mSysTime );
147167 }
148168
169+ std::string configLine = mShell ->ConfigLine ();
170+ Core::OptionalType<Core::JSON::Error> error;
171+ AnalyticsConfig config;
172+
173+ if (config.FromString (configLine, error) == false )
174+ {
175+ SYSLOG (Logging::ParsingError,
176+ (_T (" Failed to parse config line, error: '%s', config line: '%s'." ),
177+ (error.IsSet () ? error.Value ().Message ().c_str () : " Unknown" ),
178+ configLine.c_str ()));
179+ }
180+
181+ LOGINFO (" EventsMap: %s" , config.EventsMap .Value ().c_str ());
182+ ParseEventsMapFile (config.EventsMap .Value ());
183+
149184 return result;
150185 }
151186
@@ -273,27 +308,41 @@ namespace Plugin {
273308
274309 void AnalyticsImplementation::SendEventToBackend (const AnalyticsImplementation::Event& event)
275310 {
276- // TODO: Add mapping of event source/name to backend
277311 IAnalyticsBackend::Event backendEvent;
278- backendEvent.eventName = event.eventName ;
312+ backendEvent.eventName = mEventMapper .MapEventNameIfNeeded (event.eventName , event.eventSource ,
313+ event.eventSourceVersion , event.eventVersion );
279314 backendEvent.eventVersion = event.eventVersion ;
280315 backendEvent.eventSource = event.eventSource ;
281316 backendEvent.eventSourceVersion = event.eventSourceVersion ;
282317 backendEvent.epochTimestamp = event.epochTimestamp ;
283318 backendEvent.eventPayload = event.eventPayload ;
284319 backendEvent.cetList = event.cetList ;
285320
321+ // TODO: Add mapping of event source/name to the desired backend
286322 if (mBackends .empty ())
287323 {
288324 LOGINFO (" No backends available!" );
289325 }
290326 else if (mBackends .find (IAnalyticsBackend::SIFT) != mBackends .end ())
291327 {
292- LOGINFO (" Sending event to Sift backend: %s" , event .eventName .c_str ());
328+ LOGINFO (" Sending event to Sift backend: %s" , backendEvent .eventName .c_str ());
293329 mBackends .at (IAnalyticsBackend::SIFT)->SendEvent (backendEvent);
294330 }
295331 }
296332
333+ void AnalyticsImplementation::ParseEventsMapFile (const std::string& eventsMapFile)
334+ {
335+ if (eventsMapFile.empty ())
336+ {
337+ LOGINFO (" Events map file path is empty, skipping parsing" );
338+ return ;
339+ }
340+ std::ifstream t (eventsMapFile);
341+ std::string str ((std::istreambuf_iterator<char >(t)),
342+ std::istreambuf_iterator<char >());
343+ mEventMapper .FromString (str);
344+ }
345+
297346 uint64_t AnalyticsImplementation::GetCurrentTimestampInMs ()
298347 {
299348 return std::chrono::duration_cast<std::chrono::milliseconds>( std::chrono::system_clock::now ().time_since_epoch () ).count ();
@@ -319,5 +368,102 @@ namespace Plugin {
319368 return currentTimestamp - uptimeDiff;
320369 }
321370
371+ void AnalyticsImplementation::EventMapper::FromString (const std::string &jsonArrayStr)
372+ {
373+ // expect json array:
374+ // [
375+ // {
376+ // "event_name": "event_name",
377+ // "event_source": "event_source",
378+ // "event_source_version": "event_source_version", - optional
379+ // "event_version": "event_version", - optional
380+ // "mapped_event_name": "mapped_event_name"
381+ // }
382+ // ]
383+ if (jsonArrayStr.empty ())
384+ {
385+ LOGERR (" Empty events map json array string" );
386+ return ;
387+ }
388+
389+ JsonArray array;
390+ array.FromString (jsonArrayStr);
391+
392+ if (array.Length () == 0 )
393+ {
394+ LOGERR (" Empty or corrupted events map json array" );
395+ return ;
396+ }
397+
398+ for (int i = 0 ; i < array.Length (); i++)
399+ {
400+ JsonObject entry = array[i].Object ();
401+ if (entry.HasLabel (" event_name" ) && entry.HasLabel (" event_source" ) && entry.HasLabel (" mapped_event_name" ))
402+ {
403+ AnalyticsImplementation::EventMapper::Key key{
404+ entry[" event_name" ].String (),
405+ entry[" event_source" ].String (),
406+ entry.HasLabel (" event_source_version" ) ? entry[" event_source_version" ].String () : " " ,
407+ entry.HasLabel (" event_version" ) ? entry[" event_version" ].String () : " " };
408+
409+ std::string mapped_event_name = entry[" mapped_event_name" ].String ();
410+ map[key] = mapped_event_name;
411+ LOGINFO (" Index %d: Mapped event: %s -> %s" , i, entry[" event_name" ].String ().c_str (), mapped_event_name.c_str ());
412+ }
413+ else
414+ {
415+ LOGERR (" Invalid entry in events map file at index %d" , i);
416+ }
417+ }
418+ }
419+
420+ std::string AnalyticsImplementation::EventMapper::MapEventNameIfNeeded (const std::string &eventName,
421+ const std::string &eventSource,
422+ const std::string &eventSourceVersion,
423+ const std::string &eventVersion) const
424+ {
425+ // Try exact match
426+ AnalyticsImplementation::EventMapper::Key key{eventName, eventSource, eventSourceVersion, eventVersion};
427+ auto it = map.find (key);
428+ if (it != map.end ())
429+ {
430+ return it->second ;
431+ }
432+
433+ // Try without eventVersion
434+ if (!eventVersion.empty ())
435+ {
436+ AnalyticsImplementation::EventMapper::Key partialKey{eventName, eventSource, eventSourceVersion, " " };
437+ it = map.find (partialKey);
438+ if (it != map.end ())
439+ {
440+ return it->second ;
441+ }
442+ }
443+
444+ // Try without eventSourceVersion
445+ if (!eventSourceVersion.empty ())
446+ {
447+ AnalyticsImplementation::EventMapper::Key partialKey{eventName, eventSource, " " , eventVersion};
448+ it = map.find (partialKey);
449+ if (it != map.end ())
450+ {
451+ return it->second ;
452+ }
453+ }
454+
455+ // Try without both eventSourceVersion and eventVersion
456+ if (!eventSourceVersion.empty () || !eventVersion.empty ())
457+ {
458+ AnalyticsImplementation::EventMapper::Key partialKey{eventName, eventSource, " " , " " };
459+ it = map.find (partialKey);
460+ if (it != map.end ())
461+ {
462+ return it->second ;
463+ }
464+ }
465+
466+ return eventName; // Not found, nothing to map
467+ }
322468}
323469}
0 commit comments