public void Initialize( string applicationId, string applicationVersion, bool uploadEnabled, Configuration configuration, string dataDir ) { /* * // Glean initialization must be called on the main thread, or lifecycle * // registration may fail. This is also enforced at build time by the * // @MainThread decorator, but this run time check is also performed to * // be extra certain. * ThreadUtils.assertOnUiThread() * * // In certain situations Glean.initialize may be called from a process other than the main * // process. In this case we want initialize to be a no-op and just return. * if (!isMainProcess(applicationContext)) { * Log.e(LOG_TAG, "Attempted to initialize Glean on a process other than the main process") * return * } * * this.applicationContext = applicationContext*/ if (IsInitialized()) { Log.Error("Glean should not be initialized multiple times"); return; } this.configuration = configuration; this.applicationVersion = applicationVersion; httpClient = new BaseUploader(configuration.httpClient); // this.gleanDataDir = File(applicationContext.applicationInfo.dataDir, GLEAN_DATA_DIR) Dispatchers.ExecuteTask(() => { RegisterPings(Pings); IntPtr maxEventsPtr = IntPtr.Zero; if (configuration.maxEvents != null) { maxEventsPtr = Marshal.AllocHGlobal(sizeof(int)); // It's safe to call `configuration.maxEvents.Value` because we know // `configuration.maxEvents` is not null. Marshal.WriteInt32(maxEventsPtr, configuration.maxEvents.Value); } LibGleanFFI.FfiConfiguration cfg = new LibGleanFFI.FfiConfiguration { data_dir = dataDir, package_name = applicationId, language_binding_name = LanguageBindingName, upload_enabled = uploadEnabled, max_events = maxEventsPtr, delay_ping_lifetime_io = false }; // To work around a bug in the version of Mono shipped with Unity 2019.4.1f1, // copy the FFI configuration structure to unmanaged memory and pass that over // to glean-core, otherwise calling `glean_initialize` will crash and have // `__icall_wrapper_mono_struct_delete_old` in the stack. See bug 1648784 for // more details. IntPtr ptrCfg = Marshal.AllocHGlobal(Marshal.SizeOf(cfg)); Marshal.StructureToPtr(cfg, ptrCfg, false); initialized = LibGleanFFI.glean_initialize(ptrCfg) != 0; // This is safe to call even if `maxEventsPtr = IntPtr.Zero`. Marshal.FreeHGlobal(maxEventsPtr); // We were able to call `glean_initialize`, free the memory allocated for the // FFI configuration object. Marshal.FreeHGlobal(ptrCfg); // If initialization of Glean fails we bail out and don't initialize further. if (!initialized) { return; } // If any pings were registered before initializing, do so now. // We're not clearing this queue in case Glean is reset by tests. lock (this) { foreach (var ping in pingTypeQueue) { RegisterPingType(ping); } } // If this is the first time ever the Glean SDK runs, make sure to set // some initial core metrics in case we need to generate early pings. // The next times we start, we would have them around already. bool isFirstRun = LibGleanFFI.glean_is_first_run() != 0; if (isFirstRun) { InitializeCoreMetrics(); } // Deal with any pending events so we can start recording new ones bool pingSubmitted = LibGleanFFI.glean_on_ready_to_submit_pings() != 0; // We need to enqueue the BaseUploader in these cases: // 1. Pings were submitted through Glean and it is ready to upload those pings; // 2. Upload is disabled, to upload a possible deletion-request ping. if (pingSubmitted || !uploadEnabled) { httpClient.TriggerUpload(configuration); } /* * // Set up information and scheduling for Glean owned pings. Ideally, the "metrics" * // ping startup check should be performed before any other ping, since it relies * // on being dispatched to the API context before any other metric. * metricsPingScheduler = MetricsPingScheduler(applicationContext) * metricsPingScheduler.schedule() * * // Check if the "dirty flag" is set. That means the product was probably * // force-closed. If that's the case, submit a 'baseline' ping with the * // reason "dirty_startup". We only do that from the second run. * if (!isFirstRun && LibGleanFFI.INSTANCE.glean_is_dirty_flag_set().toBoolean()) { * submitPingByNameSync("baseline", "dirty_startup") * // Note: while in theory we should set the "dirty flag" to true * // here, in practice it's not needed: if it hits this branch, it * // means the value was `true` and nothing needs to be done. * }*/ // From the second time we run, after all startup pings are generated, // make sure to clear `lifetime: application` metrics and set them again. // Any new value will be sent in newly generated pings after startup. if (!isFirstRun) { LibGleanFFI.glean_clear_application_lifetime_metrics(); InitializeCoreMetrics(); } // Signal Dispatcher that init is complete Dispatchers.FlushQueuedInitialTasks(); /* * // At this point, all metrics and events can be recorded. * // This should only be called from the main thread. This is enforced by * // the @MainThread decorator and the `assertOnUiThread` call. * MainScope().launch { * ProcessLifecycleOwner.get().lifecycle.addObserver(gleanLifecycleObserver) * }*/ }); this.initFinished = true; }
public void Initialize( string applicationId, string applicationVersion, bool uploadEnabled, Configuration configuration, string dataDir ) { /* * // Glean initialization must be called on the main thread, or lifecycle * // registration may fail. This is also enforced at build time by the * // @MainThread decorator, but this run time check is also performed to * // be extra certain. * ThreadUtils.assertOnUiThread() * * // In certain situations Glean.initialize may be called from a process other than the main * // process. In this case we want initialize to be a no-op and just return. * if (!isMainProcess(applicationContext)) { * Log.e(LOG_TAG, "Attempted to initialize Glean on a process other than the main process") * return * } * * if (isInitialized()) { * Log.e(LOG_TAG, "Glean should not be initialized multiple times") * return * } * * this.applicationContext = applicationContext*/ this.configuration = configuration; httpClient = new BaseUploader(configuration.httpClient); // this.gleanDataDir = File(applicationContext.applicationInfo.dataDir, GLEAN_DATA_DIR) SetUploadEnabled(uploadEnabled); Dispatchers.ExecuteTask(() => { RegisterPings(GleanInternalPings); LibGleanFFI.FfiConfiguration cfg = new LibGleanFFI.FfiConfiguration { data_dir = dataDir, package_name = applicationId, upload_enabled = uploadEnabled, max_events = configuration.maxEvents ?? null, delay_ping_lifetime_io = false }; initialized = LibGleanFFI.glean_initialize(cfg) != 0; // If initialization of Glean fails we bail out and don't initialize further. if (!initialized) { return; } // If any pings were registered before initializing, do so now. // We're not clearing this queue in case Glean is reset by tests. lock (this) { foreach (var ping in pingTypeQueue) { RegisterPingType(ping); } } // If this is the first time ever the Glean SDK runs, make sure to set // some initial core metrics in case we need to generate early pings. // The next times we start, we would have them around already. bool isFirstRun = LibGleanFFI.glean_is_first_run() != 0; if (isFirstRun) { InitializeCoreMetrics(); } // Deal with any pending events so we can start recording new ones bool pingSubmitted = LibGleanFFI.glean_on_ready_to_submit_pings() != 0; // We need to enqueue the BaseUploader in these cases: // 1. Pings were submitted through Glean and it is ready to upload those pings; // 2. Upload is disabled, to upload a possible deletion-request ping. if (pingSubmitted || !uploadEnabled) { httpClient.TriggerUpload(configuration); } /* * // Set up information and scheduling for Glean owned pings. Ideally, the "metrics" * // ping startup check should be performed before any other ping, since it relies * // on being dispatched to the API context before any other metric. * metricsPingScheduler = MetricsPingScheduler(applicationContext) * metricsPingScheduler.schedule() * * // Check if the "dirty flag" is set. That means the product was probably * // force-closed. If that's the case, submit a 'baseline' ping with the * // reason "dirty_startup". We only do that from the second run. * if (!isFirstRun && LibGleanFFI.INSTANCE.glean_is_dirty_flag_set().toBoolean()) { * submitPingByNameSync("baseline", "dirty_startup") * // Note: while in theory we should set the "dirty flag" to true * // here, in practice it's not needed: if it hits this branch, it * // means the value was `true` and nothing needs to be done. * }*/ // From the second time we run, after all startup pings are generated, // make sure to clear `lifetime: application` metrics and set them again. // Any new value will be sent in newly generated pings after startup. if (!isFirstRun) { LibGleanFFI.glean_clear_application_lifetime_metrics(); InitializeCoreMetrics(); } // Signal Dispatcher that init is complete Dispatchers.FlushQueuedInitialTasks(); /* * // At this point, all metrics and events can be recorded. * // This should only be called from the main thread. This is enforced by * // the @MainThread decorator and the `assertOnUiThread` call. * MainScope().launch { * ProcessLifecycleOwner.get().lifecycle.addObserver(gleanLifecycleObserver) * }*/ }); }