Beispiel #1
0
        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;
        }
Beispiel #2
0
        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)
                 * }*/
            });
        }