mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	common: Add a generic interface for logging telemetry fields.
This commit is contained in:
		
							parent
							
								
									c291db72e7
								
							
						
					
					
						commit
						a4760e939f
					
				@ -38,6 +38,7 @@ set(SRCS
 | 
			
		||||
            param_package.cpp
 | 
			
		||||
            scm_rev.cpp
 | 
			
		||||
            string_util.cpp
 | 
			
		||||
            telemetry.cpp
 | 
			
		||||
            thread.cpp
 | 
			
		||||
            timer.cpp
 | 
			
		||||
            )
 | 
			
		||||
@ -74,6 +75,7 @@ set(HEADERS
 | 
			
		||||
            string_util.h
 | 
			
		||||
            swap.h
 | 
			
		||||
            synchronized_wrapper.h
 | 
			
		||||
            telemetry.h
 | 
			
		||||
            thread.h
 | 
			
		||||
            thread_queue_list.h
 | 
			
		||||
            timer.h
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										40
									
								
								src/common/telemetry.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/common/telemetry.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
// Copyright 2017 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include "common/telemetry.h"
 | 
			
		||||
 | 
			
		||||
namespace Telemetry {
 | 
			
		||||
 | 
			
		||||
void FieldCollection::Accept(VisitorInterface& visitor) const {
 | 
			
		||||
    for (const auto& field : fields) {
 | 
			
		||||
        field.second->Accept(visitor);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FieldCollection::AddField(std::unique_ptr<FieldInterface> field) {
 | 
			
		||||
    fields[field->GetName()] = std::move(field);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
void Field<T>::Accept(VisitorInterface& visitor) const {
 | 
			
		||||
    visitor.Visit(*this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template class Field<bool>;
 | 
			
		||||
template class Field<double>;
 | 
			
		||||
template class Field<float>;
 | 
			
		||||
template class Field<u8>;
 | 
			
		||||
template class Field<u16>;
 | 
			
		||||
template class Field<u32>;
 | 
			
		||||
template class Field<u64>;
 | 
			
		||||
template class Field<s8>;
 | 
			
		||||
template class Field<s16>;
 | 
			
		||||
template class Field<s32>;
 | 
			
		||||
template class Field<s64>;
 | 
			
		||||
template class Field<std::string>;
 | 
			
		||||
template class Field<const char*>;
 | 
			
		||||
template class Field<std::chrono::microseconds>;
 | 
			
		||||
 | 
			
		||||
} // namespace Telemetry
 | 
			
		||||
							
								
								
									
										196
									
								
								src/common/telemetry.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								src/common/telemetry.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,196 @@
 | 
			
		||||
// Copyright 2017 Citra Emulator Project
 | 
			
		||||
// Licensed under GPLv2 or any later version
 | 
			
		||||
// Refer to the license.txt file included.
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
 | 
			
		||||
namespace Telemetry {
 | 
			
		||||
 | 
			
		||||
/// Field type, used for grouping fields together in the final submitted telemetry log
 | 
			
		||||
enum class FieldType : u8 {
 | 
			
		||||
    None = 0,     ///< No specified field group
 | 
			
		||||
    App,          ///< Citra application fields (e.g. version, branch, etc.)
 | 
			
		||||
    Session,      ///< Emulated session fields (e.g. title ID, log, etc.)
 | 
			
		||||
    Performance,  ///< Emulated performance (e.g. fps, emulated CPU speed, etc.)
 | 
			
		||||
    UserFeedback, ///< User submitted feedback (e.g. star rating, user notes, etc.)
 | 
			
		||||
    UserConfig,   ///< User configuration fields (e.g. emulated CPU core, renderer, etc.)
 | 
			
		||||
    UserSystem,   ///< User system information (e.g. host CPU type, RAM, etc.)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct VisitorInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Interface class for telemetry data fields.
 | 
			
		||||
 */
 | 
			
		||||
class FieldInterface : NonCopyable {
 | 
			
		||||
public:
 | 
			
		||||
    virtual ~FieldInterface() = default;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Accept method for the visitor pattern.
 | 
			
		||||
     * @param visitor Reference to the visitor that will visit this field.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void Accept(VisitorInterface& visitor) const = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Gets the name of this field.
 | 
			
		||||
     * @returns Name of this field as a string.
 | 
			
		||||
     */
 | 
			
		||||
    virtual const std::string& GetName() const = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Represents a telemetry data field, i.e. a unit of data that gets logged and submitted to our
 | 
			
		||||
 * telemetry web service.
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
class Field : public FieldInterface {
 | 
			
		||||
public:
 | 
			
		||||
    Field(FieldType type, std::string name, const T& value)
 | 
			
		||||
        : type(type), name(std::move(name)), value(value) {}
 | 
			
		||||
 | 
			
		||||
    Field(FieldType type, std::string name, T&& value)
 | 
			
		||||
        : type(type), name(std::move(name)), value(std::move(value)) {}
 | 
			
		||||
 | 
			
		||||
    Field(const Field& other) : Field(other.type, other.name, other.value) {}
 | 
			
		||||
 | 
			
		||||
    Field& operator=(const Field& other) {
 | 
			
		||||
        type = other.type;
 | 
			
		||||
        name = other.name;
 | 
			
		||||
        value = other.value;
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Field& operator=(Field&& other) {
 | 
			
		||||
        type = other.type;
 | 
			
		||||
        name = std::move(other.name);
 | 
			
		||||
        value = std::move(other.value);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Accept(VisitorInterface& visitor) const override;
 | 
			
		||||
 | 
			
		||||
    const std::string& GetName() const override {
 | 
			
		||||
        return name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the type of the field.
 | 
			
		||||
     */
 | 
			
		||||
    FieldType GetType() const {
 | 
			
		||||
        return type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns the value of the field.
 | 
			
		||||
     */
 | 
			
		||||
    const T& GetValue() const {
 | 
			
		||||
        return value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline bool operator==(const Field<T>& other) {
 | 
			
		||||
        return (type == other.type) && (name == other.name) && (value == other.value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline bool operator!=(const Field<T>& other) {
 | 
			
		||||
        return !(*this == other);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::string name; ///< Field name, must be unique
 | 
			
		||||
    FieldType type{}; ///< Field type, used for grouping fields together
 | 
			
		||||
    T value;          ///< Field value
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Collection of data fields that have been logged.
 | 
			
		||||
 */
 | 
			
		||||
class FieldCollection final : NonCopyable {
 | 
			
		||||
public:
 | 
			
		||||
    FieldCollection() = default;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Accept method for the visitor pattern, visits each field in the collection.
 | 
			
		||||
     * @param visitor Reference to the visitor that will visit each field.
 | 
			
		||||
     */
 | 
			
		||||
    void Accept(VisitorInterface& visitor) const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new field and adds it to the field collection.
 | 
			
		||||
     * @param type Type of the field to add.
 | 
			
		||||
     * @param name Name of the field to add.
 | 
			
		||||
     * @param value Value for the field to add.
 | 
			
		||||
     */
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    void AddField(FieldType type, const char* name, T value) {
 | 
			
		||||
        return AddField(std::make_unique<Field<T>>(type, name, std::move(value)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds a new field to the field collection.
 | 
			
		||||
     * @param field Field to add to the field collection.
 | 
			
		||||
     */
 | 
			
		||||
    void AddField(std::unique_ptr<FieldInterface> field);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::map<std::string, std::unique_ptr<FieldInterface>> fields;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Telemetry fields visitor interface class. A backend to log to a web service should implement
 | 
			
		||||
 * this interface.
 | 
			
		||||
 */
 | 
			
		||||
struct VisitorInterface : NonCopyable {
 | 
			
		||||
    virtual ~VisitorInterface() = default;
 | 
			
		||||
 | 
			
		||||
    virtual void Visit(const Field<bool>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<double>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<float>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<u8>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<u16>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<u32>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<u64>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<s8>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<s16>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<s32>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<s64>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<std::string>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<const char*>& field) = 0;
 | 
			
		||||
    virtual void Visit(const Field<std::chrono::microseconds>& field) = 0;
 | 
			
		||||
 | 
			
		||||
    /// Completion method, called once all fields have been visited
 | 
			
		||||
    virtual void Complete() = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Empty implementation of VisitorInterface that drops all fields. Used when a functional
 | 
			
		||||
 * backend implementation is not available.
 | 
			
		||||
 */
 | 
			
		||||
struct NullVisitor : public VisitorInterface {
 | 
			
		||||
    ~NullVisitor() = default;
 | 
			
		||||
 | 
			
		||||
    void Visit(const Field<bool>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<double>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<float>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<u8>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<u16>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<u32>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<u64>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<s8>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<s16>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<s32>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<s64>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<std::string>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<const char*>& /*field*/) override {}
 | 
			
		||||
    void Visit(const Field<std::chrono::microseconds>& /*field*/) override {}
 | 
			
		||||
 | 
			
		||||
    void Complete() override {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace Telemetry
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user