blob: e63497038a73d5e4ad1b9df59bee0d693096c6bc [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COBALT_SRC_LOGGER_PROJECT_CONTEXT_H_
#define COBALT_SRC_LOGGER_PROJECT_CONTEXT_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <google/protobuf/repeated_field.h>
#include "src/lib/util/status_builder.h"
#include "src/public/lib/registry_identifiers.h"
#include "src/public/lib/statusor/statusor.h"
#include "src/registry/cobalt_registry.pb.h"
#include "src/registry/metric_definition.pb.h"
#include "src/registry/project.pb.h"
#include "src/registry/project_configs.h"
namespace cobalt::logger {
// A pair (metric ID, report ID).
using MetricReportId = std::pair<uint32_t, uint32_t>;
// A reference object that gives access to the names and IDs of a Metric and
// its owning Project and Customer. One way to obtain a MetricRef is the method
// ProjectContext::RefMetric().
class MetricRef {
public:
// A MetricRef is constructed from a Project and a MetricDefinition. The
// Project and MetricDefinition must remain valid as long as the MetricRef is
// being used.
MetricRef(const Project* project, const MetricDefinition* metric_definition);
[[nodiscard]] const Project& project() const;
[[nodiscard]] std::string ProjectDebugString() const;
[[nodiscard]] uint32_t metric_id() const;
[[nodiscard]] const MetricDefinition* metric_definition() const;
[[nodiscard]] const std::string& metric_name() const;
// Returns the string <customer_name>.<project_name>.<metric_name>
[[nodiscard]] std::string FullyQualifiedName() const;
private:
friend class ProjectContext;
const Project* project_;
const MetricDefinition* metric_definition_;
};
// ProjectContext stores the metrics registration data for a single Cobalt
// project and makes it conveniently available on the client.
//
// The underlying data comes from a |ProjectConfig| proto message which
// represents a single project within the Cobalt Registry. An instance of
// ProjectContext does not copy the data from a |ProjectConfig|, but rather
// maintains a pointer to an instance of |ProjectConfig|. An instance of
// ProjectContext may or may not own its underlying |ProjectConfig|, depending
// on which constructor is used.
class ProjectContext {
public:
// Constructs an instance of ProjectContext that does own the
// underlying |ProjectConfig|.
//
// |customer_id| The id of the customer this project is for.
//
// |customer_name| The name of the customer this project is for.
//
// |project_config| The |ProjectConfig| containing the project data.
ProjectContext(uint32_t customer_id, const std::string& customer_name,
std::unique_ptr<ProjectConfig> project_config);
// Constructs an instance of ProjectContext that does not own the
// underlying |ProjectConfig|.
//
// |customer_id| The id of the customer this project is for.
//
// |customer_name| The name of the customer this project is for.
//
// |project_config| The |ProjectConfig| containing the project data.
ProjectContext(uint32_t customer_id, const std::string& customer_name,
const ProjectConfig* project_config);
// Returns the MetricDefinition for the metric with the given name, or
// nullptr if there is no such metric.
const MetricDefinition* GetMetric(const std::string& metric_name) const;
// Returns the MetricDefinition for the metric with the given ID, or
// nullptr if there is no such metric.
const MetricDefinition* GetMetric(uint32_t metric_id) const;
const MetricDefinition* GetMetric(lib::MetricIdentifier metric) const {
return GetMetric(metric.metric_id());
}
// Makes a MetricRef that wraps this ProjectContext's Project and the given
// metric_definition (which should have been obtained via GetMetric()).
// The Project and MetricDefinition must remain valid as long as the returned
// MetricRef is being used.
MetricRef RefMetric(const MetricDefinition* metric_definition) const;
// Gives access to the metadata for the project.
const Project& project() const { return project_; }
// Gives access to the list of all MetricDefinitions for the project.
const google::protobuf::RepeatedPtrField<MetricDefinition>& metrics() const {
return project_config_->metrics();
}
std::string DebugString() const;
// Returns the string <customer_name>(<id>).<project_name>(<id>)
std::string static FullyQualifiedName(const Project& project);
// Returns the string
// <customer_name>(<id>).<project_name>(<id>).<metric_name>(<id>)
std::string static FullMetricName(const Project& project, const MetricDefinition& metric);
// Returns the string <customer_name>(<id>).<project_name>(<id>)
std::string FullyQualifiedName() const;
// Returns the string
// <customer_name>(<id>).<project_name>(<id>).<metric_name>(<id>)
std::string FullMetricName(const MetricDefinition& metric_definition) const;
// ListMetrics returns a list of metric identifiers that are present in this project.
std::vector<lib::MetricIdentifier> ListMetrics() const;
[[nodiscard]] lib::ProjectIdentifier Identifier() const;
private:
// Constructs an instance of ProjectContext that may or may not own the
// underlying |ProjectConfig|.
//
// |customer_id| The id of the customer this project is for.
//
// |customer_name| The name of the customer this project is for.
//
// |owned_project_config| Exactly one of |owned_project_config| or
// |project_config| must be not null or we will CHECK fail.
//
// |project_config| Exactly one of |owned_project_config| or
// |project_config| must be not null or we will CHECK fail.
ProjectContext(uint32_t customer_id, const std::string& customer_name,
const ProjectConfig* project_config,
std::unique_ptr<ProjectConfig> owned_project_config);
Project project_;
// This pointer is always non-null and points either to
// maybe_null_project_config_ or to an instance of ProjectConfig
// not owned by this object. Access the underlying ProjectConfig through
// this pointer and never through maybe_null_project_config_;
const ProjectConfig* project_config_;
// An instance of ProjectContext may or may not own the underlying
// ProjectConfig, so this may or may not be null. Never access this
// variable directly after it is initialized in the constructor. Instead
// access |project_config_|.
const std::unique_ptr<ProjectConfig> maybe_null_project_config_;
std::map<const std::string, const MetricDefinition*> metrics_by_name_;
std::map<const uint32_t, const MetricDefinition*> metrics_by_id_;
};
} // namespace cobalt::logger
namespace cobalt::util {
// Specialization of ContextFormatter for logger::MetricRef to give it default formatting and
// allow it to be passed to StatusBuilder::WithContexts.
//
// Will print Metric=<FullyQualifiedName()> by default.
template <>
class ContextFormatter<logger::MetricRef> {
public:
explicit ContextFormatter(const logger::MetricRef& v) : v_(v) {}
inline static std::string default_key() { return "Metric"; }
inline void write_value(std::ostream& stream) { stream << v_.FullyQualifiedName(); }
private:
const logger::MetricRef& v_;
};
// Specialization of ContextFormatter for logger::ProjectContext to give it default formatting and
// allow it to be passed to StatusBuilder::WithContexts.
//
// Will print Project=<FullyQualifiedName()> by default.
template <>
class ContextFormatter<logger::ProjectContext> {
public:
explicit ContextFormatter(const logger::ProjectContext& v) : v_(v) {}
static std::string default_key() { return "Project"; }
void write_value(std::ostream& stream) { stream << v_.FullyQualifiedName(); }
private:
const logger::ProjectContext& v_;
};
} // namespace cobalt::util
#endif // COBALT_SRC_LOGGER_PROJECT_CONTEXT_H_