    async def initialize(self, *args, **kwargs):
        hub_startup_start_time = time.perf_counter()
        super().initialize(*args, **kwargs)
        if self.generate_config or self.generate_certs or self.subapp:
            return
        if self.extra_args:
            self.exit(
                f"Unrecognized command-line arguments: {' '.join(shlex.quote(arg) for arg in self.extra_args)!r}"
            )
        self._start_future = asyncio.Future()

        def record_start(f):
            startup_time = time.perf_counter() - hub_startup_start_time
            self.log.debug("It took %.3f seconds for the Hub to start", startup_time)
            HUB_STARTUP_DURATION_SECONDS.observe(startup_time)

        self._start_future.add_done_callback(record_start)

        self.load_config_file(self.config_file)
        self.init_logging()
        self.log.info("Running JupyterHub version %s", jupyterhub.__version__)
        if 'JupyterHubApp' in self.config:
            self.log.warning(
                "Use JupyterHub in config, not JupyterHubApp. Outdated config:\n%s",
                '\n'.join(
                    f'JupyterHubApp.{key} = {value!r}'
                    for key, value in self.config.JupyterHubApp.items()
                ),
            )
            cfg = self.config.copy()
            cfg.JupyterHub.merge(cfg.JupyterHubApp)
            self.update_config(cfg)
        self.write_pid_file()

        def _log_cls(name, cls):
            """Log a configured class

            Logs the class and version (if found) of Authenticator
            and Spawner
            """
            # try to guess the version from the top-level module
            # this will work often enough to be useful.
            # no need to be perfect.
            if cls.__module__:
                mod = sys.modules.get(cls.__module__.split('.')[0])
                version = getattr(mod, '__version__', '')
                if version:
                    version = f'-{version}'
            else:
                version = ''
            self.log.info(
                "Using %s: %s.%s%s", name, cls.__module__ or '', cls.__name__, version
            )

        _log_cls("Authenticator", self.authenticator_class)
        _log_cls("Spawner", self.spawner_class)
        _log_cls("Proxy", self.proxy_class)

        self.init_eventlog()
        self.init_pycurl()
        self.init_secrets()
        self.init_internal_ssl()
        self.init_db()
        self.init_hub()
        self.init_proxy()
        self.init_oauth()
        await self.init_role_creation()
        await self.init_users()
        await self.init_groups()
        self.init_services()
        await self.init_api_tokens()
        await self.init_role_assignment()
        await self.init_blocked_users()
        self.init_tornado_settings()
        self.init_handlers()
        self.init_tornado_application()

        # init_spawners can take a while
        init_spawners_timeout = self.init_spawners_timeout
        if init_spawners_timeout < 0:
            # negative timeout means forever (previous, most stable behavior)
            init_spawners_timeout = 86400

        init_start_time = time.perf_counter()
        init_spawners_future = asyncio.ensure_future(self.init_spawners())

        def log_init_time(f):
            n_spawners = f.result()
            spawner_initialization_time = time.perf_counter() - init_start_time
            INIT_SPAWNERS_DURATION_SECONDS.observe(spawner_initialization_time)
            self.log.info(
                "Initialized %i spawners in %.3f seconds",
                n_spawners,
                spawner_initialization_time,
            )

        init_spawners_future.add_done_callback(log_init_time)

        try:
            # don't allow a zero timeout because we still need to be sure
            # that the Spawner objects are defined and pending
            await gen.with_timeout(
                timedelta(seconds=max(init_spawners_timeout, 1)), init_spawners_future
            )
        except AnyTimeoutError:
            self.log.warning(
                "init_spawners did not complete within %i seconds. "
                "Allowing to complete in the background.",
                self.init_spawners_timeout,
            )

        if init_spawners_future.done():
            self.cleanup_oauth_clients()
        else:
            # schedule async operations after init_spawners finishes
            async def finish_init_spawners():
                await init_spawners_future
                # schedule cleanup after spawners are all set up
                # because it relies on the state resolved by init_spawners
                self.cleanup_oauth_clients()
                # trigger a proxy check as soon as all spawners are ready
                # because this may be *after* the check made as part of normal startup.
                # To avoid races with partially-complete start,
                # ensure that start is complete before running this check.
                await self._start_future
                await self.proxy.check_routes(self.users, self._service_map)

            asyncio.ensure_future(finish_init_spawners())
        metrics_collector = self.metrics_collector = PeriodicMetricsCollector(
            parent=self, db=self.db
        )
Log a configured class

Logs the class and version (if found) of Authenticator
and Spawner
jupyterhub/app.py