Skip to content

Analytics SetDefaultParameters #1262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

jonsimantov
Copy link
Contributor

Description

Provide details of the change, and generalize the change in the PR title above.

Add SetDefaultParameters API to Firebase Analytics Unity SDK.

This commit introduces the FirebaseAnalytics.SetDefaultParameters() method to the Unity SDK, wrapping the underlying C++ firebase::analytics::SetDefaultEventParameters() and firebase::analytics::ClearDefaultEventParameters() functions.


Testing

Describe how you've tested these changes.

Calls to the new API have been integrated into the existing TestApp (UIHandler.cs) for manual verification and TestAppAutomated (UIHandlerAutomated.cs) for automated execution. These tests will exercise the API surface but not programmatically verify results from the Unity side.


Type of Change

Place an x the applicable box:

  • Bug fix. Add the issue # below if applicable.
  • New feature. A non-breaking change which adds functionality.
  • Other, such as a build process or documentation change.

This commit introduces the `FirebaseAnalytics.SetDefaultParameters()` method to your Unity SDK, wrapping the underlying C++ `firebase::analytics::SetDefaultEventParameters()` and `firebase::analytics::ClearDefaultEventParameters()` functions.

My testing approach has been updated based on your feedback: NUnit tests were removed, and calls to the new API have been integrated into the existing TestApp (UIHandler.cs) for manual verification and TestAppAutomated (UIHandlerAutomated.cs) for automated execution. These tests will exercise the API surface but not programmatically verify results from the Unity side.

Key changes:
- Modified `analytics/src/swig/analytics.i`:
    - Ignored the original C++ `SetDefaultEventParameters` and `ClearDefaultEventParameters` functions.
    - Added a C++ helper function `SetDefaultEventParametersHelper` that takes vectors of parameter names and Variant values, converts them to a `std::map`, and calls the C++ `SetDefaultEventParameters`.
    - Exposed `SetDefaultEventParametersHelper` and `ClearDefaultEventParameters` to C# via SWIG.
- Modified `analytics/src/FirebaseAnalytics.cs`:
    - Added the public static method `SetDefaultParameters(IDictionary<string, object> parameters)`.
    - If `parameters` is null or empty, the method calls the internal `ClearDefaultEventParameters()`.
    - Otherwise, it converts the dictionary into `StringList` and `VariantList` and calls the internal `SetDefaultEventParametersHelper()`.
- Removed `analytics/testapp/Assets/Firebase/Sample/Analytics/AnalyticsTest.cs` (NUnit test file).
- Modified `analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandler.cs`:
    - Added a new button and method `TestSetDefaultParameters()` to call `FirebaseAnalytics.SetDefaultParameters` with various inputs (single param, multiple params, null, empty dictionary) for manual testing.
- Modified `analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandlerAutomated.cs`:
    - Added calls to `FirebaseAnalytics.SetDefaultParameters` with various inputs to the automated test sequence to ensure the API is exercised.
Corrects an issue in `analytics/src/swig/analytics.i` that caused a build failure (CS0117) because `FirebaseAnalyticsInternal.ClearDefaultEventParameters` was not being generated.

The problem was that `%ignore firebase::analytics::ClearDefaultEventParameters;` was preventing SWIG from wrapping this function, even though it was later declared in `analytics.i` with the intent to be wrapped for internal C# SDK use.

This commit removes the overly broad `%ignore` for `ClearDefaultEventParameters`. The function is now correctly wrapped by SWIG due to its explicit declaration in the SWIG interface file, making it available as `FirebaseAnalyticsInternal.ClearDefaultEventParameters()`. This allows `FirebaseAnalytics.SetDefaultParameters(null)` to call it as intended, without exposing `ClearDefaultEventParameters` as a new public API on `FirebaseAnalytics` itself.
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @jonsimantov, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

Hello team, gemini-code-assist here to provide a summary of this pull request. This PR introduces a new public API method, SetDefaultParameters, to the Firebase Analytics Unity SDK. This method allows developers to set parameters that will be automatically included with every subsequent event logged via LogEvent. It wraps the underlying C++ firebase::analytics::SetDefaultEventParameters and firebase::analytics::ClearDefaultEventParameters functions. The implementation includes handling for clearing default parameters when a null or empty dictionary is provided. The PR also includes updates to the test applications (manual and automated) to demonstrate and verify the basic functionality of this new API.

Highlights

  • New API: SetDefaultParameters: Adds a new public static method FirebaseAnalytics.SetDefaultParameters to the Unity SDK. Allows setting default parameters that are automatically attached to all subsequent logged events.
  • C++ Interop: Wraps the native C++ firebase::analytics::SetDefaultEventParameters and ClearDefaultEventParameters functions.
  • Parameter Handling: Converts C# IDictionary<string, object> to C++ vectors of strings and variants using a new helper function in the SWIG interface.
  • Test Coverage: Adds manual and automated tests in the sample applications (UIHandler.cs and UIHandlerAutomated.cs) to exercise the new API.

Changelog

Click here to see the changelog
  • analytics/src/FirebaseAnalytics.cs
    • Added the public static method SetDefaultParameters (lines 260-273) to expose the functionality to Unity developers.
    • Implemented logic to convert the input dictionary to internal list types and call the appropriate internal C++ wrapper function (ClearDefaultEventParameters or SetDefaultEventParametersHelper).
  • analytics/src/swig/analytics.i
    • Added a C++ helper function SetDefaultEventParametersHelper (lines 91-106) to facilitate converting vector inputs from C# (via SWIG) into a std::map for the native C++ SetDefaultEventParameters function.
    • Added %ignore directives for the original C++ SetDefaultEventParameters (lines 121-123) to prevent direct SWIG wrapping.
    • Added %include directives for the new SetDefaultEventParametersHelper and the existing ClearDefaultEventParameters (lines 145-148) to ensure they are wrapped by SWIG.
  • analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandler.cs
    • Added a new public method TestSetDefaultParameters (lines 165-189) to demonstrate the usage of the new API in the manual test app.
    • Added a button to the GUI (lines 286-288) to trigger the TestSetDefaultParameters method.
  • analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandlerAutomated.cs
    • Added a new automated test method TestSetDefaultParametersAutomated (lines 113-138) to programmatically test the new API.
    • Added TestSetDefaultParametersAutomated to the list of tests executed by the automated test runner (line 43).
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


Parameters set,
With every event they fly,
Analytics flow.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the SetDefaultParameters API to the Firebase Analytics Unity SDK, providing a valuable feature for setting default parameters for all analytics events. The changes are well-structured, with corresponding C++ bindings and additions to both manual and automated test applications.

The implementation in C# and C++ appears correct for the happy path, and the SWIG interface changes are appropriate. The tests effectively exercise the new API surface.

One area for consideration is the robustness of the C# SetDefaultParameters method when encountering parameter values of unsupported types.

Summary of Findings

  • Robustness to Invalid Parameter Types: The C# SetDefaultParameters method converts object values to Firebase.Variant. If Firebase.Variant.FromObject throws an exception for an unsupported type, the current implementation might lead to an unhandled exception. It's recommended to add error handling to skip problematic parameters and log a warning, ensuring the method behaves more gracefully with diverse inputs. The behavior when all provided parameters are invalid also warrants clarification (e.g., whether to clear existing defaults or preserve them).
  • Code Quality and Testing: The overall code quality is good, with clear implementation and appropriate C++/SWIG bindings. The addition of both manual and automated tests is commendable and helps ensure the API surface is exercised.

Merge Readiness

The pull request introduces a useful feature and is generally well-implemented. However, there is a medium-severity concern regarding error handling for unsupported parameter types in FirebaseAnalytics.cs (detailed in the review comment).

I recommend addressing or clarifying the behavior for this scenario before merging to enhance the robustness of the new API. As I am an AI assistant, I am not authorized to approve pull requests; please ensure further review and approval from authorized maintainers after addressing the feedback. With the suggested improvement, the PR would be in a strong position for merging.

Comment on lines 267 to 270
foreach (var kvp in parameters) {
parameterNames.Add(kvp.Key);
parameterValues.Add(Firebase.Variant.FromObject(kvp.Value));
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation iterates through the parameters dictionary and converts values using Firebase.Variant.FromObject(kvp.Value). If Firebase.Variant.FromObject encounters an unsupported type or fails to convert a value, it might throw an exception.

Consider how such exceptions should be handled:

  1. If an exception is thrown and not caught within this loop, the SetDefaultParameters call will terminate abruptly, potentially leaving the default parameters in an unchanged state (if the exception occurs before SetDefaultEventParametersHelper is called) or partially processed if this method were part of a larger try-catch. This could be disruptive to the calling application.
  2. A more robust approach might be to catch exceptions for individual parameter conversions, log a warning, and skip that specific parameter, allowing the rest of the valid parameters to be set.

Additionally, what is the intended behavior if the parameters dictionary is non-empty, but all parameters within it fail conversion and are skipped?

  • With the suggested try-catch below, if parameterNames and parameterValues end up empty, FirebaseAnalyticsInternal.SetDefaultEventParametersHelper would be called with empty lists. This would then call the native SetDefaultEventParameters with an empty map, which typically clears all existing default parameters.
  • Is clearing all defaults the desired outcome if the new set of parameters is entirely invalid? Or would it be preferable to preserve the existing default parameters in such a case (e.g., by not calling SetDefaultEventParametersHelper if parameterNames is empty after processing a non-empty input parameters dictionary)?

Could we enhance this part to gracefully handle potential conversion errors for individual parameters?

      foreach (var kvp in parameters) {
        try {
          // Attempt to convert the value to a Variant.
          Firebase.Variant variantValue = Firebase.Variant.FromObject(kvp.Value);
          // Note: If Variant.FromObject can return an invalid/null state for unsupported types
          // without throwing, an additional check for variantValue's validity might be needed here
          // (e.g., if (!variantValue.IsValid) { LogWarningAndSkip(); continue; } ).

          parameterNames.Add(kvp.Key);
          parameterValues.Add(variantValue);
        } catch (System.Exception e) { // Catch exceptions from FromObject (e.g., for unsupported types)
          // Log a warning and skip this parameter. Using UnityEngine.Debug.LogWarning for broad compatibility.
          UnityEngine.Debug.LogWarning(
              $"Firebase Analytics: Default parameter '{kvp.Key}' (value type: {kvp.Value?.GetType().FullName ?? "null"}) " +
              $"could not be converted and will be skipped. Error: {e.Message}");
        }
      }

I've renamed the public C# method for setting default event parameters from `FirebaseAnalytics.SetDefaultParameters` to `FirebaseAnalytics.SetDefaultEventParameters`.

This change aligns the C# API name with the corresponding C++ function `firebase::analytics::SetDefaultEventParameters` for better consistency across SDKs.

I updated the following files:
- `analytics/src/FirebaseAnalytics.cs`: I renamed the public static method.
- `analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandler.cs`: I updated the manual test app to call the renamed method, renamed the test method, and updated the UI button label.
- `analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandlerAutomated.cs`: I updated the automated test app to call the renamed method and renamed the corresponding automated test method.
Updates logging in the `FirebaseAnalytics.SetDefaultEventParameters` method to use `ModuleLogger` instead of `UnityEngine.Debug.LogX` calls.

This change aligns the Analytics module's logging practices with other Firebase Unity SDK modules (e.g., Firebase Storage), providing more consistent and filterable logging output.

Key changes:
- Added a static `ModuleLogger` instance to the `FirebaseAnalytics` class.
- Replaced calls to `UnityEngine.Debug.Log`, `LogWarning`, and `LogError` within `SetDefaultEventParameters` with their respective `logger.LogMessage(LogLevel, ...)` equivalents.
- Removed the "Firebase Analytics: " prefix from log messages as `ModuleLogger` typically handles module identification.

namespace Firebase.Analytics {

public static partial class FirebaseAnalytics {

private static readonly Firebase.Platform.ModuleLogger logger = new Firebase.Platform.ModuleLogger(typeof(FirebaseAnalytics).ToString());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's hard code the tag instead of using typeof().ToString.

/// These parameters are logged with all events, in addition to the parameters passed to the
/// LogEvent() call. They are useful for logging common parameters with all events.
/// Default event parameters are overridden by event-specific parameters if the names are the
/// same. Default parameters are removed if the dictionary is null or empty.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's change it so that default parameters are only cleared if the dictionary is null. Individual parameters will be removed (by the underlying implementation) if the value of a given key is null.

/// If null, clears all default parameters.
public static void SetDefaultEventParameters(
System.Collections.Generic.IDictionary<string, object> parameters) {
if (parameters == null || parameters.Count == 0) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't do this if count = 0, only if it's null.

}
}

if (parameterNames.Count == 0 && originalCount > 0) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need this originalCount logic any more if we change it so an empty dictionary is just passed through verbatim.

foreach (var kvp in parameters) {
try {
parameterNames.Add(kvp.Key);
parameterValues.Add(Firebase.Variant.FromObject(kvp.Value));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be cleaner to do the conversion first, and then add the name and value only once the conversion succeeds? This will prevent us from having to remove the value in the exception handler below.

@@ -100,6 +118,9 @@ void SetConsentWithInts(const std::map<int, int>& settings) {
%ignore firebase::analytics::LogEvent(const char*, const Parameter*, size_t);
// Ignore SetConsent, in order to convert the types with our own function.
%ignore firebase::analytics::SetConsent;
// Ignore SetDefaultEventParameters and ClearDefaultEventParameters, as we handle them
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is outdated as we don't ignore ClearDefaultEventParameters.

FirebaseAnalytics.SetDefaultEventParameters(new Dictionary<string, object>
{
{ "auto_default_param_int", 789 },
{ "auto_default_param_double", 12.34 },
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also test with a value of null to make sure that that's passed through correctly.

foreach (var kvp in parameters) {
try {
parameterNames.Add(kvp.Key);
parameterValues.Add(Firebase.Variant.FromObject(kvp.Value));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also can we just confirm that Firebase.Variant.FromObject supports null properly, and will output a wrapped Variant::Null()?

Incorporates multiple changes to `SetDefaultEventParameters` and related files based on code review feedback.

Key changes:

1.  **`FirebaseAnalytics.cs` (`SetDefaultEventParameters` method):**
    *   `ModuleLogger` now uses a hardcoded tag "FirebaseAnalytics".
    *   If `parameters` dictionary is `null`, `ClearDefaultEventParameters()` is called.
    *   If `parameters` dictionary is empty (not null), `SetDefaultEventParametersHelper` is called with empty lists, which results in the C++ SDK clearing all default parameters (aligning with C++ behavior for an empty map).
    *   Parameter conversion loop:
        *   `Firebase.Variant.FromObject()` is called before adding keys/values to lists.
        *   Exceptions during conversion are caught, a warning is logged (including value type and error message), and the problematic parameter is skipped.
    *   If all parameters from a non-empty input dictionary fail conversion, a warning is logged noting that this will also result in clearing all default parameters (due to empty lists being passed to the helper).

2.  **`analytics/src/swig/analytics.i`:**
    *   Updated an outdated SWIG comment regarding `ClearDefaultEventParameters` to accurately reflect its handling.

3.  **`analytics/testapp/Assets/Firebase/Sample/Analytics/UIHandlerAutomated.cs`:**
    *   Added a test case to `TestSetDefaultEventParametersAutomated` that calls `SetDefaultEventParameters` with a dictionary containing a parameter with a `null` value, ensuring this path is exercised.

These changes improve robustness, align behavior more closely with C++ SDK expectations (especially regarding empty maps), enhance logging, and expand test coverage.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant