summaryrefslogtreecommitdiff
path: root/src/web_service/telemetry_json.cpp
diff options
context:
space:
mode:
authorGravatar Lioncash2018-10-10 21:04:19 -0400
committerGravatar Lioncash2018-10-10 21:10:36 -0400
commita7725d354cf118b2299ed197d4b88ff48ebc1341 (patch)
tree7bf14f649e1dcd130975bde03f37877ece6c45ad /src/web_service/telemetry_json.cpp
parenttelemetry_json: Add missing override specifier to the destructor of Telemetry... (diff)
downloadyuzu-a7725d354cf118b2299ed197d4b88ff48ebc1341.tar.gz
yuzu-a7725d354cf118b2299ed197d4b88ff48ebc1341.tar.xz
yuzu-a7725d354cf118b2299ed197d4b88ff48ebc1341.zip
telemetry_json: Use the PImpl idiom to avoid unnecessary dependency exposure
Users of the web_service library shouldn't need to care about an external library like json.h. However, given it's exposed in our interface, this requires that other libraries publicly link in the JSON library. We can do better. By using the PImpl idiom, we can hide this dependency in the cpp file and remove the need to link that library in altogether.
Diffstat (limited to 'src/web_service/telemetry_json.cpp')
-rw-r--r--src/web_service/telemetry_json.cpp86
1 files changed, 53 insertions, 33 deletions
diff --git a/src/web_service/telemetry_json.cpp b/src/web_service/telemetry_json.cpp
index b24e806a8..3c5590054 100644
--- a/src/web_service/telemetry_json.cpp
+++ b/src/web_service/telemetry_json.cpp
@@ -2,93 +2,113 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <json.hpp>
5#include "common/detached_tasks.h" 6#include "common/detached_tasks.h"
6#include "web_service/telemetry_json.h" 7#include "web_service/telemetry_json.h"
7#include "web_service/web_backend.h" 8#include "web_service/web_backend.h"
8 9
9namespace WebService { 10namespace WebService {
10 11
11TelemetryJson::TelemetryJson(std::string host, std::string username, std::string token) 12struct TelemetryJson::Impl {
12 : host(std::move(host)), username(std::move(username)), token(std::move(token)) {} 13 Impl(std::string host, std::string username, std::string token)
13TelemetryJson::~TelemetryJson() = default; 14 : host{std::move(host)}, username{std::move(username)}, token{std::move(token)} {}
14 15
15template <class T> 16 nlohmann::json& TopSection() {
16void TelemetryJson::Serialize(Telemetry::FieldType type, const std::string& name, T value) { 17 return sections[static_cast<u8>(Telemetry::FieldType::None)];
17 sections[static_cast<u8>(type)][name] = value; 18 }
18}
19 19
20void TelemetryJson::SerializeSection(Telemetry::FieldType type, const std::string& name) { 20 const nlohmann::json& TopSection() const {
21 TopSection()[name] = sections[static_cast<unsigned>(type)]; 21 return sections[static_cast<u8>(Telemetry::FieldType::None)];
22} 22 }
23
24 template <class T>
25 void Serialize(Telemetry::FieldType type, const std::string& name, T value) {
26 sections[static_cast<u8>(type)][name] = value;
27 }
28
29 void SerializeSection(Telemetry::FieldType type, const std::string& name) {
30 TopSection()[name] = sections[static_cast<unsigned>(type)];
31 }
32
33 nlohmann::json output;
34 std::array<nlohmann::json, 7> sections;
35 std::string host;
36 std::string username;
37 std::string token;
38};
39
40TelemetryJson::TelemetryJson(std::string host, std::string username, std::string token)
41 : impl{std::make_unique<Impl>(std::move(host), std::move(username), std::move(token))} {}
42TelemetryJson::~TelemetryJson() = default;
23 43
24void TelemetryJson::Visit(const Telemetry::Field<bool>& field) { 44void TelemetryJson::Visit(const Telemetry::Field<bool>& field) {
25 Serialize(field.GetType(), field.GetName(), field.GetValue()); 45 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
26} 46}
27 47
28void TelemetryJson::Visit(const Telemetry::Field<double>& field) { 48void TelemetryJson::Visit(const Telemetry::Field<double>& field) {
29 Serialize(field.GetType(), field.GetName(), field.GetValue()); 49 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
30} 50}
31 51
32void TelemetryJson::Visit(const Telemetry::Field<float>& field) { 52void TelemetryJson::Visit(const Telemetry::Field<float>& field) {
33 Serialize(field.GetType(), field.GetName(), field.GetValue()); 53 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
34} 54}
35 55
36void TelemetryJson::Visit(const Telemetry::Field<u8>& field) { 56void TelemetryJson::Visit(const Telemetry::Field<u8>& field) {
37 Serialize(field.GetType(), field.GetName(), field.GetValue()); 57 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
38} 58}
39 59
40void TelemetryJson::Visit(const Telemetry::Field<u16>& field) { 60void TelemetryJson::Visit(const Telemetry::Field<u16>& field) {
41 Serialize(field.GetType(), field.GetName(), field.GetValue()); 61 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
42} 62}
43 63
44void TelemetryJson::Visit(const Telemetry::Field<u32>& field) { 64void TelemetryJson::Visit(const Telemetry::Field<u32>& field) {
45 Serialize(field.GetType(), field.GetName(), field.GetValue()); 65 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
46} 66}
47 67
48void TelemetryJson::Visit(const Telemetry::Field<u64>& field) { 68void TelemetryJson::Visit(const Telemetry::Field<u64>& field) {
49 Serialize(field.GetType(), field.GetName(), field.GetValue()); 69 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
50} 70}
51 71
52void TelemetryJson::Visit(const Telemetry::Field<s8>& field) { 72void TelemetryJson::Visit(const Telemetry::Field<s8>& field) {
53 Serialize(field.GetType(), field.GetName(), field.GetValue()); 73 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
54} 74}
55 75
56void TelemetryJson::Visit(const Telemetry::Field<s16>& field) { 76void TelemetryJson::Visit(const Telemetry::Field<s16>& field) {
57 Serialize(field.GetType(), field.GetName(), field.GetValue()); 77 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
58} 78}
59 79
60void TelemetryJson::Visit(const Telemetry::Field<s32>& field) { 80void TelemetryJson::Visit(const Telemetry::Field<s32>& field) {
61 Serialize(field.GetType(), field.GetName(), field.GetValue()); 81 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
62} 82}
63 83
64void TelemetryJson::Visit(const Telemetry::Field<s64>& field) { 84void TelemetryJson::Visit(const Telemetry::Field<s64>& field) {
65 Serialize(field.GetType(), field.GetName(), field.GetValue()); 85 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
66} 86}
67 87
68void TelemetryJson::Visit(const Telemetry::Field<std::string>& field) { 88void TelemetryJson::Visit(const Telemetry::Field<std::string>& field) {
69 Serialize(field.GetType(), field.GetName(), field.GetValue()); 89 impl->Serialize(field.GetType(), field.GetName(), field.GetValue());
70} 90}
71 91
72void TelemetryJson::Visit(const Telemetry::Field<const char*>& field) { 92void TelemetryJson::Visit(const Telemetry::Field<const char*>& field) {
73 Serialize(field.GetType(), field.GetName(), std::string(field.GetValue())); 93 impl->Serialize(field.GetType(), field.GetName(), std::string(field.GetValue()));
74} 94}
75 95
76void TelemetryJson::Visit(const Telemetry::Field<std::chrono::microseconds>& field) { 96void TelemetryJson::Visit(const Telemetry::Field<std::chrono::microseconds>& field) {
77 Serialize(field.GetType(), field.GetName(), field.GetValue().count()); 97 impl->Serialize(field.GetType(), field.GetName(), field.GetValue().count());
78} 98}
79 99
80void TelemetryJson::Complete() { 100void TelemetryJson::Complete() {
81 SerializeSection(Telemetry::FieldType::App, "App"); 101 impl->SerializeSection(Telemetry::FieldType::App, "App");
82 SerializeSection(Telemetry::FieldType::Session, "Session"); 102 impl->SerializeSection(Telemetry::FieldType::Session, "Session");
83 SerializeSection(Telemetry::FieldType::Performance, "Performance"); 103 impl->SerializeSection(Telemetry::FieldType::Performance, "Performance");
84 SerializeSection(Telemetry::FieldType::UserFeedback, "UserFeedback"); 104 impl->SerializeSection(Telemetry::FieldType::UserFeedback, "UserFeedback");
85 SerializeSection(Telemetry::FieldType::UserConfig, "UserConfig"); 105 impl->SerializeSection(Telemetry::FieldType::UserConfig, "UserConfig");
86 SerializeSection(Telemetry::FieldType::UserSystem, "UserSystem"); 106 impl->SerializeSection(Telemetry::FieldType::UserSystem, "UserSystem");
87 107
88 auto content = TopSection().dump(); 108 auto content = impl->TopSection().dump();
89 // Send the telemetry async but don't handle the errors since they were written to the log 109 // Send the telemetry async but don't handle the errors since they were written to the log
90 Common::DetachedTasks::AddTask( 110 Common::DetachedTasks::AddTask(
91 [host{this->host}, username{this->username}, token{this->token}, content]() { 111 [host{impl->host}, username{impl->username}, token{impl->token}, content]() {
92 Client{host, username, token}.PostJson("/telemetry", content, true); 112 Client{host, username, token}.PostJson("/telemetry", content, true);
93 }); 113 });
94} 114}