Skip to content

Commit b829441

Browse files
refactor: Update event parameter handling for map and vector types
Based on explicit feedback, this commit fundamentally changes how Parameter values of type Map and Vector are processed in the Windows Analytics C++ SDK (in src/analytics_desktop.cc): 1. **Parameter values of type Vector (`param.value.is_vector()`):** - These are now treated as UNSUPPORTED for top-level event parameters on Desktop. - An error is logged, and the parameter is skipped. - The previous logic that interpreted a vector of maps as an item array has been removed from ConvertParametersToGAParams. 2. **Parameter values of type Map (`param.value.is_map()`):** - This case is now explicitly handled. - The key-value pairs of the input map are transformed into a GoogleAnalytics_ItemVector. - Each entry (key, value_variant) in your map becomes a distinct GoogleAnalytics_Item within this ItemVector. - Each such GoogleAnalytics_Item stores the original map key under a property named "name", and the original map value (which must be a primitive type) under a typed property (e.g., "int_value", "double_value", "string_value"). - This resulting ItemVector is then added to the event's parameters using the original Parameter's name. 3. **Comments:** - Code comments within ConvertParametersToGAParams have been updated to reflect this new processing logic. This change aligns the behavior with specific design requirements for how map and vector type parameters should be translated to the underlying Windows C API for Google Analytics.
1 parent 94abdb3 commit b829441

File tree

1 file changed

+71
-57
lines changed

1 file changed

+71
-57
lines changed

src/analytics_desktop.cc

Lines changed: 71 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -78,70 +78,84 @@ static void ConvertParametersToGAParams(
7878
GoogleAnalytics_EventParameters_InsertString(
7979
c_event_params, param.name, param.value.string_value());
8080
} else if (param.value.is_vector()) {
81-
// This block handles parameters that are vectors of items (e.g., kParameterItems).
82-
// The 'param.value' is expected to be a firebase::Variant of type kTypeVector.
83-
// Each element in this outer vector (item_variants) is itself a firebase::Variant,
84-
// which must be of type kTypeMap, representing a single item's properties.
85-
const std::vector<firebase::Variant>& item_variants =
86-
param.value.vector_value();
81+
// Vector types for top-level event parameters are not directly supported for conversion
82+
// to GoogleAnalytics_EventParameters on Desktop.
83+
// The previous implementation attempted to interpret a vector of maps as an "Item Array",
84+
// but the standard way to log an array of Items is via a single parameter (e.g., "items")
85+
// whose value is a vector of firebase::analytics::Item objects (which are maps).
86+
// For direct parameters, vector is an unsupported type.
87+
LogError("Analytics: Parameter '%s' has type Vector, which is unsupported for event parameters on Desktop. Skipping.", param.name);
88+
continue; // Skip this parameter
89+
} else if (param.value.is_map()) {
90+
// This block handles parameters that are maps.
91+
// Each key-value pair in the map is converted into a GoogleAnalytics_Item,
92+
// and all such items are bundled into a GoogleAnalytics_ItemVector,
93+
// which is then inserted into the event parameters.
94+
// The original map's key becomes the "name" property of the GA_Item,
95+
// and the map's value becomes one of "int_value", "double_value", or "string_value".
96+
const std::map<std::string, firebase::Variant>& user_map =
97+
param.value.map_value();
98+
if (user_map.empty()) {
99+
LogWarning("Analytics: Parameter '%s' is an empty map. Skipping.", param.name);
100+
continue; // Skip this parameter
101+
}
87102

88103
GoogleAnalytics_ItemVector* c_item_vector =
89104
GoogleAnalytics_ItemVector_Create();
90105
if (!c_item_vector) {
91-
LogError("Analytics: Failed to create ItemVector for parameter '%s'.", param.name);
106+
LogError("Analytics: Failed to create ItemVector for map parameter '%s'.", param.name);
92107
continue; // Skip this parameter
93108
}
94109

95110
bool item_vector_populated = false;
96-
for (const firebase::Variant& item_variant : item_variants) {
97-
if (item_variant.is_map()) {
98-
const std::map<std::string, firebase::Variant>& item_map =
99-
item_variant.map_value();
100-
101-
GoogleAnalytics_Item* c_item = GoogleAnalytics_Item_Create();
102-
if (!c_item) {
103-
LogError("Analytics: Failed to create Item for an item in vector parameter '%s'.", param.name);
104-
continue;
105-
}
106-
107-
bool item_populated = false;
108-
for (const auto& entry : item_map) {
109-
const std::string& item_key = entry.first;
110-
const firebase::Variant& item_val = entry.second;
111-
112-
if (item_val.is_int64()) {
113-
GoogleAnalytics_Item_InsertInt(c_item, item_key.c_str(),
114-
item_val.int64_value());
115-
item_populated = true;
116-
} else if (item_val.is_double()) {
117-
GoogleAnalytics_Item_InsertDouble(c_item, item_key.c_str(),
118-
item_val.double_value());
119-
item_populated = true;
120-
} else if (item_val.is_string()) {
121-
GoogleAnalytics_Item_InsertString(c_item, item_key.c_str(),
122-
item_val.string_value());
123-
item_populated = true;
124-
} else {
125-
LogWarning("Analytics: Unsupported variant type in Item map for key '%s' in vector parameter '%s'.", item_key.c_str(), param.name);
126-
}
127-
}
128-
129-
if (item_populated) {
130-
GoogleAnalytics_ItemVector_InsertItem(c_item_vector, c_item);
131-
item_vector_populated = true;
132-
} else {
133-
GoogleAnalytics_Item_Destroy(c_item);
134-
}
111+
for (const auto& entry : user_map) {
112+
const std::string& key_from_map = entry.first;
113+
const firebase::Variant& value_from_map = entry.second;
114+
115+
GoogleAnalytics_Item* c_item = GoogleAnalytics_Item_Create();
116+
if (!c_item) {
117+
LogError("Analytics: Failed to create Item for key '%s' in map parameter '%s'.", key_from_map.c_str(), param.name);
118+
continue; // Skip this key-value pair, try next one in map
119+
}
120+
121+
// Store the original map's key as the "name" of this item property
122+
GoogleAnalytics_Item_InsertString(c_item, "name", key_from_map.c_str());
123+
124+
bool value_property_set = false;
125+
if (value_from_map.is_int64()) {
126+
GoogleAnalytics_Item_InsertInt(c_item, "int_value", value_from_map.int64_value());
127+
value_property_set = true;
128+
} else if (value_from_map.is_double()) {
129+
GoogleAnalytics_Item_InsertDouble(c_item, "double_value", value_from_map.double_value());
130+
value_property_set = true;
131+
} else if (value_from_map.is_string()) {
132+
GoogleAnalytics_Item_InsertString(c_item, "string_value", value_from_map.string_value());
133+
value_property_set = true;
134+
} else {
135+
LogWarning("Analytics: Value for key '%s' in map parameter '%s' has an unsupported Variant type. This key-value pair will be skipped.", key_from_map.c_str(), param.name);
136+
// As "name" was set, but no value, this item is incomplete.
137+
}
138+
139+
if (value_property_set) {
140+
GoogleAnalytics_ItemVector_InsertItem(c_item_vector, c_item);
141+
// c_item is now owned by c_item_vector
142+
item_vector_populated = true;
135143
} else {
136-
LogWarning("Analytics: Expected a map (Item) in vector parameter '%s', but found a different Variant type.", param.name);
144+
// If value wasn't set (e.g. unsupported type), or c_item creation failed.
145+
// (c_item creation failure is handled by 'continue' above, so this 'else'
146+
// is mainly for when value_property_set is false due to unsupported type)
147+
GoogleAnalytics_Item_Destroy(c_item);
137148
}
138149
}
139150

140151
if (item_vector_populated) {
141152
GoogleAnalytics_EventParameters_InsertItemVector(
142153
c_event_params, param.name, c_item_vector);
154+
// c_item_vector is now owned by c_event_params
143155
} else {
156+
// If no items were successfully created and added (e.g., all values in map were unsupported types)
144157
GoogleAnalytics_ItemVector_Destroy(c_item_vector);
158+
LogWarning("Analytics: Map parameter '%s' resulted in an empty ItemVector; no valid key-value pairs found or all values had unsupported types. This map parameter was skipped.", param.name);
145159
}
146160
} else {
147161
LogWarning("Analytics: Unsupported variant type for parameter '%s'.", param.name);
@@ -251,7 +265,7 @@ void ResetAnalyticsData() {
251265
void SetConsent(const std::map<ConsentType, ConsentStatus>& consent_settings) {
252266
// Not supported by the Windows C API.
253267
(void)consent_settings; // Mark as unused
254-
LogWarning("Analytics: SetConsent() is not supported and has no effect on Windows.");
268+
LogWarning("Analytics: SetConsent() is not supported and has no effect on Desktop.");
255269
}
256270

257271
void LogEvent(const char* name) {
@@ -301,30 +315,30 @@ void LogEvent(const char* name, const char* parameter_name,
301315
void InitiateOnDeviceConversionMeasurementWithEmailAddress(
302316
const char* email_address) {
303317
(void)email_address;
304-
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithEmailAddress() is not supported and has no effect on Windows.");
318+
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithEmailAddress() is not supported and has no effect on Desktop.");
305319
}
306320

307321
void InitiateOnDeviceConversionMeasurementWithPhoneNumber(
308322
const char* phone_number) {
309323
(void)phone_number;
310-
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithPhoneNumber() is not supported and has no effect on Windows.");
324+
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithPhoneNumber() is not supported and has no effect on Desktop.");
311325
}
312326

313327
void InitiateOnDeviceConversionMeasurementWithHashedEmailAddress(
314328
std::vector<unsigned char> hashed_email_address) {
315329
(void)hashed_email_address;
316-
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithHashedEmailAddress() is not supported and has no effect on Windows.");
330+
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithHashedEmailAddress() is not supported and has no effect on Desktop.");
317331
}
318332

319333
void InitiateOnDeviceConversionMeasurementWithHashedPhoneNumber(
320334
std::vector<unsigned char> hashed_phone_number) {
321335
(void)hashed_phone_number;
322-
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithHashedPhoneNumber() is not supported and has no effect on Windows.");
336+
LogWarning("Analytics: InitiateOnDeviceConversionMeasurementWithHashedPhoneNumber() is not supported and has no effect on Desktop.");
323337
}
324338

325339
void SetSessionTimeoutDuration(int64_t milliseconds) {
326340
(void)milliseconds;
327-
LogWarning("Analytics: SetSessionTimeoutDuration() is not supported and has no effect on Windows.");
341+
LogWarning("Analytics: SetSessionTimeoutDuration() is not supported and has no effect on Desktop.");
328342
}
329343

330344
Future<std::string> GetAnalyticsInstanceId() {
@@ -333,7 +347,7 @@ Future<std::string> GetAnalyticsInstanceId() {
333347
firebase::FutureHandle handle; // Dummy handle for error
334348
// TODO(jules): Ensure g_future_api_table is appropriate or replace with direct Future creation.
335349
auto future = MakeFuture<std::string>(&firebase::g_future_api_table, handle);
336-
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetAnalyticsInstanceId is not supported on Windows.");
350+
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetAnalyticsInstanceId is not supported on Desktop.");
337351
return future;
338352
}
339353

@@ -342,22 +356,22 @@ Future<std::string> GetAnalyticsInstanceIdLastResult() {
342356
// Since GetAnalyticsInstanceId is not supported, this also returns a failed future.
343357
firebase::FutureHandle handle;
344358
auto future = MakeFuture<std::string>(&firebase::g_future_api_table, handle);
345-
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetAnalyticsInstanceId is not supported on Windows.");
359+
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetAnalyticsInstanceId (and thus LastResult) is not supported on Desktop.");
346360
return future;
347361
}
348362

349363
Future<int64_t> GetSessionId() {
350364
// Not supported by the Windows C API.
351365
firebase::FutureHandle handle;
352366
auto future = MakeFuture<int64_t>(&firebase::g_future_api_table, handle);
353-
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetSessionId is not supported on Windows.");
367+
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetSessionId is not supported on Desktop.");
354368
return future;
355369
}
356370

357371
Future<int64_t> GetSessionIdLastResult() {
358372
firebase::FutureHandle handle;
359373
auto future = MakeFuture<int64_t>(&firebase::g_future_api_table, handle);
360-
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetSessionId is not supported on Windows.");
374+
future.Complete(handle, kAnalyticsErrorNotSupportedOnPlatform, "GetSessionId (and thus LastResult) is not supported on Desktop.");
361375
return future;
362376
}
363377

0 commit comments

Comments
 (0)