chromium/chromeos/ash/components/network/metrics/connection_info_metrics_logger.h

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_METRICS_CONNECTION_INFO_METRICS_LOGGER_H_
#define CHROMEOS_ASH_COMPONENTS_NETWORK_METRICS_CONNECTION_INFO_METRICS_LOGGER_H_

#include <optional>

#include "base/component_export.h"
#include "base/containers/flat_map.h"
#include "base/memory/raw_ptr.h"
#include "base/observer_list.h"
#include "chromeos/ash/components/network/network_connection_observer.h"
#include "chromeos/ash/components/network/network_state_handler_observer.h"

namespace ash {

class NetworkConnectionHandler;
class NetworkState;
class NetworkStateHandler;

// Class for tracking general connection information about networks.
//
// This class adds observers on network state and makes the following
// measurements on all networks:
// 1. Success rate of all connection attempts.
// 2. Success rate of user initiated connection attempts.
// 3. Connected states and non-user initiated disconnections.
//
// Note: This class does not start logging metrics until Init() is
// invoked.
class COMPONENT_EXPORT(CHROMEOS_NETWORK) ConnectionInfoMetricsLogger
    : public NetworkStateHandlerObserver,
      public NetworkConnectionObserver {
 public:
  class Observer : public base::CheckedObserver {
   public:
    ~Observer() override = default;

    // Invoked when a connection result finishes, i.e. a network becomes
    // connected from a non-connected state or a network goes from a connecting
    // state to a disconnected state. In the latter situation, |shill_error|
    // will be non-empty.
    virtual void OnConnectionResult(
        const std::string& guid,
        const std::optional<std::string>& shill_error) = 0;
  };

  ConnectionInfoMetricsLogger();
  ConnectionInfoMetricsLogger(const ConnectionInfoMetricsLogger&) = delete;
  ConnectionInfoMetricsLogger& operator=(const ConnectionInfoMetricsLogger&) =
      delete;
  ~ConnectionInfoMetricsLogger() override;

  void Init(NetworkStateHandler* network_state_handler,
            NetworkConnectionHandler* network_connection_handler);

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

 private:
  friend class ConnectionInfoMetricsLoggerTest;

  // Stores connection related information for a network.
  struct ConnectionInfo {
   public:
    enum class Status {
      // The network is not connected, connecting, or disconnecting.
      kDisconnected = 0,

      // The network is being connected to.
      kConnecting = 1,

      // The network is connected.
      kConnected = 2,

      // The network is disconnecting.
      kDisconnecting = 3,

      // The network is in failure state which mapped to the corresponding
      // shill error.
      kFailure = 4,
    };

    explicit ConnectionInfo(const NetworkState* network,
                            bool is_user_initiated);
    ~ConnectionInfo();

    bool operator==(const ConnectionInfo& other) const;

    Status status;
    std::string guid;
    std::string shill_error;
    bool is_user_initiated;
  };

  // NetworkStateHandlerObserver::
  void ConnectToNetworkRequested(const std::string& service_path) override;
  void NetworkListChanged() override;
  void NetworkConnectionStateChanged(const NetworkState* network) override;
  void OnShuttingDown() override;

  // NetworkConnectionObserver::
  void ConnectSucceeded(const std::string& service_path) override;
  void ConnectFailed(const std::string& service_path,
                     const std::string& error_name) override;

  void UpdateConnectionInfo(const NetworkState* network);
  void ConnectionAttemptFinished(const std::optional<ConnectionInfo>& prev_info,
                                 const ConnectionInfo& curr_info) const;
  void AttemptLogConnectionStateResult(
      const std::optional<ConnectionInfo>& prev_info,
      const ConnectionInfo& curr_info) const;
  std::optional<ConnectionInfo> GetCachedInfo(const std::string& guid) const;
  void NotifyConnectionResult(
      const std::string& guid,
      const std::optional<std::string>& shill_error) const;

  raw_ptr<NetworkStateHandler> network_state_handler_ = nullptr;
  raw_ptr<NetworkConnectionHandler> network_connection_handler_ = nullptr;

  NetworkStateHandlerScopedObservation network_state_handler_observer_{this};

  // Stores connection information for all networks.
  base::flat_map<std::string, ConnectionInfo> guid_to_connection_info_;

  base::ObserverList<Observer> observers_;
};

}  // namespace ash

#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_METRICS_CONNECTION_INFO_METRICS_LOGGER_H_