Skip to content

Commit

Permalink
RDK-51273: Analytics Plugin Phase 1
Browse files Browse the repository at this point in the history
  • Loading branch information
adrianM27 committed Aug 26, 2024
1 parent 842af5e commit 84cdb21
Show file tree
Hide file tree
Showing 22 changed files with 2,308 additions and 0 deletions.
23 changes: 23 additions & 0 deletions Analytics/Analytics.conf.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
precondition = ["Platform"]
callsign = "org.rdk.Analytics"
autostart = "@PLUGIN_ANALYTICS_AUTOSTART@"
startuporder = "@PLUGIN_ANALYTICS_STARTUPORDER@"

configuration = JSON()

configuration.add("deviceosname", "@PLUGIN_ANALYTICS_DEVICE_OS_NAME@")

if boolean("@PLUGIN_ANALYTICS_SIFT_BACKEND_ENABLED@"):
sift = JSON()
sift.add("commonschema", "@PLUGIN_ANALYTICS_SIFT_COMMON_SCHEMA@")
sift.add("env", "@PLUGIN_ANALYTICS_SIFT_ENV@")
sift.add("productname", "@PLUGIN_ANALYTICS_SIFT_PRODUCT_NAME@")
sift.add("loggername", "@PLUGIN_ANALYTICS_SIFT_LOGGER_NAME@")
sift.add("loggerversion", "@PLUGIN_ANALYTICS_SIFT_LOGGER_VERSION@")
sift.add("maxrandomisationwindowtime", "@PLUGIN_ANALYTICS_SIFT_MAX_RANDOMISATION_WINDOW_TIME@")
sift.add("maxeventsinpost", "@PLUGIN_ANALYTICS_SIFT_MAX_EVENTS_IN_POST@")
sift.add("maxretries", "@PLUGIN_ANALYTICS_SIFT_MAX_RETRIES@")
sift.add("minretryperiod", "@PLUGIN_ANALYTICS_SIFT_MIN_RETRY_PERIOD@")
sift.add("maxretryperiod", "@PLUGIN_ANALYTICS_SIFT_MAX_RETRY_PERIOD@")
sift.add("exponentialperiodicfactor", "@PLUGIN_ANALYTICS_SIFT_EXPONENTIAL_PERIODIC_FACTOR@")
configuration.add("sift", sift)
31 changes: 31 additions & 0 deletions Analytics/Analytics.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
set (autostart ${PLUGIN_ANALYTICS_AUTOSTART})
set (preconditions Platform)
set (callsign "org.rdk.Analytics")

if(PLUGIN_ANALYTICS_STARTUPORDER)
set (startuporder ${PLUGIN_ANALYTICS_STARTUPORDER})
endif()

map()
kv(deviceosversion ${PLUGIN_ANALYTICS_DEVICE_OS_VERSION})
end()
ans(configuration)


if(PLUGIN_ANALYTICS_SIFT_BACKEND_ENABLED)
map()
kv(commonschema ${PLUGIN_ANALYTICS_SIFT_COMMON_SCHEMA})
kv(env ${PLUGIN_ANALYTICS_SIFT_ENV})
kv(productname ${PLUGIN_ANALYTICS_SIFT_PRODUCT_NAME})
kv(loggername ${PLUGIN_ANALYTICS_SIFT_LOGGER_NAME})
kv(loggerversion ${PLUGIN_ANALYTICS_SIFT_LOGGER_VERSION})
kv(maxrandomisationwindowtime, ${PLUGIN_ANALYTICS_SIFT_MAX_RANDOMISATION_WINDOW_TIME})
kv(maxeventsinpost, ${PLUGIN_ANALYTICS_SIFT_MAX_EVENTS_IN_POST})
kv(maxretries, ${PLUGIN_ANALYTICS_SIFT_MAX_RETRIES})
kv(minretryperiod, ${PLUGIN_ANALYTICS_SIFT_MIN_RETRY_PERIOD})
kv(maxretryperiod, ${PLUGIN_ANALYTICS_SIFT_MAX_RETRY_PERIOD})
kv(exponentialperiodicfactor, ${PLUGIN_ANALYTICS_SIFT_EXPONENTIAL_PERIODIC_FACTOR})
end()
ans(siftobject)
map_append(${configuration} sift ${siftobject})
endif()
112 changes: 112 additions & 0 deletions Analytics/Analytics.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* If not stated otherwise in this file or this component's LICENSE file the
* following copyright and licenses apply:
*
* Copyright 2020 RDK Management
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "Analytics.h"
#include <interfaces/IConfiguration.h>

#define API_VERSION_NUMBER_MAJOR ANALYTICS_MAJOR_VERSION
#define API_VERSION_NUMBER_MINOR ANALYTICS_MINOR_VERSION
#define API_VERSION_NUMBER_PATCH ANALYTICS_PATCH_VERSION

namespace WPEFramework {

namespace {
static Plugin::Metadata<Plugin::Analytics> metadata(
// Version (Major, Minor, Patch)
API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH,
// Preconditions
{},
// Terminations
{},
// Controls
{}
);
}

namespace Plugin {
SERVICE_REGISTRATION(Analytics, API_VERSION_NUMBER_MAJOR, API_VERSION_NUMBER_MINOR, API_VERSION_NUMBER_PATCH);

/* virtual */ const string Analytics::Initialize(PluginHost::IShell* service)
{
ASSERT(service != nullptr);
mService = service;

ASSERT(mAnalytics == nullptr);

mAnalytics = service->Root<Exchange::IAnalytics>(mConnectionId, 2000, _T("AnalyticsImplementation"));
ASSERT(mAnalytics != nullptr);

if (mAnalytics != nullptr) {
auto configConnection = mAnalytics->QueryInterface<Exchange::IConfiguration>();
if (configConnection != nullptr) {
configConnection->Configure(service);
configConnection->Release();
}
RegisterAll();
}
// On success return empty, to indicate there is no error text.
return ((mAnalytics != nullptr))
? EMPTY_STRING
: _T("Could not retrieve the Analytics interface.");
}

/* virtual */ void Analytics::Deinitialize(PluginHost::IShell* service)
{
TRACE(Trace::Information, (_T("Analytics::Deinitialize")));
ASSERT(service != nullptr);

if (mAnalytics != nullptr) {
UnregisterAll();

RPC::IRemoteConnection *connection(service->RemoteConnection(mConnectionId));

VARIABLE_IS_NOT_USED uint32_t result = mAnalytics->Release();
mAnalytics = nullptr;

// It should have been the last reference we are releasing,
// so it should end up in a DESCRUCTION_SUCCEEDED, if not we
// are leaking...
ASSERT(result == Core::ERROR_DESTRUCTION_SUCCEEDED);

// If this was running in a (container) process...
if (connection != nullptr)
{
// Lets trigger a cleanup sequence for
// out-of-process code. Which will guard
// that unwilling processes, get shot if
// not stopped friendly :~)
connection->Terminate();
connection->Release();
}
}
}

void Analytics::Deactivated(RPC::IRemoteConnection* connection)
{
if (connection->Id() == mConnectionId) {
TRACE(Trace::Information, (_T("Analytics::Deactivated")));

ASSERT(mService != nullptr);

Core::IWorkerPool::Instance().Submit(PluginHost::IShell::Job::Create(mService, PluginHost::IShell::DEACTIVATED, PluginHost::IShell::FAILURE));
}
}

} // namespace Plugin
} // namespace WPEFramework
85 changes: 85 additions & 0 deletions Analytics/Analytics.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/**
* If not stated otherwise in this file or this component's LICENSE
* file the following copyright and licenses apply:
*
* Copyright 2020 RDK Management
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/

#pragma once

#include "Module.h"

#include <interfaces/IAnalytics.h>

namespace WPEFramework {

namespace Plugin {


// This is a server for a JSONRPC communication channel.
// For a plugin to be capable to handle JSONRPC, inherit from PluginHost::JSONRPC.
// By inheriting from this class, the plugin realizes the interface PluginHost::IDispatcher.
// This realization of this interface implements, by default, the following methods on this plugin
// - exists
// - register
// - unregister
// Any other methood to be handled by this plugin can be added can be added by using the
// templated methods Register on the PluginHost::JSONRPC class.
// As the registration/unregistration of notifications is realized by the class PluginHost::JSONRPC,
// this class exposes a public method called, Notify(), using this methods, all subscribed clients
// will receive a JSONRPC message as a notification, in case this method is called.
class Analytics : public PluginHost::IPlugin, public PluginHost::JSONRPC {
private:
// We do not allow this plugin to be copied !!
Analytics(const Analytics&) = delete;
Analytics& operator=(const Analytics&) = delete;

public:
Analytics():
mConnectionId(0),
mAnalytics(nullptr)
{
RegisterAll();
}
virtual ~Analytics()
{
UnregisterAll();
}
virtual const string Initialize(PluginHost::IShell* shell) override;
virtual void Deinitialize(PluginHost::IShell* service) override;
virtual string Information() const override { return {}; }

BEGIN_INTERFACE_MAP(Analytics)
INTERFACE_ENTRY(PluginHost::IPlugin)
INTERFACE_ENTRY(PluginHost::IDispatcher)
INTERFACE_AGGREGATE(Exchange::IAnalytics, mAnalytics)
END_INTERFACE_MAP

static const string ANALYTICS_METHOD_SEND_EVENT;
private:
void Deactivated(RPC::IRemoteConnection* connection);
// JSONRPC methods
void RegisterAll();
void UnregisterAll();

uint32_t SendEventWrapper(const JsonObject& parameters, JsonObject& response);

private:
PluginHost::IShell* mService;
uint32_t mConnectionId;
Exchange::IAnalytics* mAnalytics;
};
} // namespace Plugin
} // namespace WPEFramework
104 changes: 104 additions & 0 deletions Analytics/Analytics.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
{
"$schema": "https://raw.githubusercontent.com/rdkcentral/rdkservices/main/Tools/json_generator/schemas/interface.schema.json",
"jsonrpc": "2.0",
"info": {
"title": "Analytics API",
"class": "Analytics",
"description": "The `Analytics` plugin allows sending analytics events to dedicated backends."
},
"common": {
"$ref": "../common/common.json"
},
"definitions": {
"eventName":{
"summary": "Name of the event",
"type": "string",
"example": "app_summary"
},
"eventVersion":{
"summary": "Version number of event schema",
"type": "string",
"example": "1.0.0"
},
"eventSource": {
"summary": "Name of the component that originates the event (Durable App ID if an App)",
"type": "string",
"example": "epg"
},
"eventSourceVersion": {
"summary": "Version number for the component that originates the event",
"type": "string",
"example": "1.0.0"
},
"cetList": {
"summary": "An array of Capability Exclusion Tags to be included on the report. Each CET will exclude the event from being processed for the specified process, any may result in the event being dropped. May be an array of length zero",
"type": "array",
"items": {
"type": "string",
"example": "cet1"
}
},
"epochTimestamp":{
"summary": "Timestamp for the START of this event, epoch time, in ms UTC",
"type": "integer",
"example": 1721906631000
},
"uptimeTimestamp":{
"summary": "Timestamp for the START of this event, uptime of the device, in ms. ONLY to be used when Time quality is not good.",
"type": "integer",
"example": 35000
},
"eventPayload":{
"summary": "The payload of the event",
"type": "object",
"example": {
"key1": "value1",
"key2": "value2"
}
}
},
"methods": {
"sendEvent":{
"summary": "Send event",
"params": {
"type":"object",
"properties": {
"eventName":{
"$ref": "#/definitions/eventName"
},
"eventVersion":{
"$ref": "#/definitions/eventVersion"
},
"eventSource":{
"$ref": "#/definitions/eventSource"
},
"eventSourceVersion":{
"$ref": "#/definitions/eventSourceVersion"
},
"cetList":{
"$ref": "#/definitions/cetList"
},
"epochTimestamp":{
"$ref": "#/definitions/epochTimestamp"
},
"uptimeTimestamp":{
"$ref": "#/definitions/uptimeTimestamp"
},
"eventPayload":{
"$ref": "#/definitions/eventPayload"
}
},
"required": [
"eventName",
"eventSource",
"eventSourceVersion",
"cetList",
"eventPayload"
]
},
"result": {
"$ref": "#/common/result"
}
}
}
}
Loading

0 comments on commit 84cdb21

Please sign in to comment.