Skip to content

Commit 0f2ec04

Browse files
Mobile Ads Developer Relationscopybara-github
authored andcommitted
Change RCS encoding from JSON to JSPB.
PiperOrigin-RevId: 828649088
1 parent f421175 commit 0f2ec04

File tree

3 files changed

+175
-8
lines changed

3 files changed

+175
-8
lines changed

source/plugin/Assets/GoogleMobileAds/Common/GlobalExceptionHandler.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ public void ReportTrappedException(Exception e, string name = null)
121121
stacktrace_hash = Sha256Hash(e.StackTrace ?? ""),
122122
};
123123
Enqueue(report);
124+
if (Debug.isDebugBuild)
125+
{
126+
Debug.Log("Trapped exception queued for batch.");
127+
}
124128
}
125129
#endregion
126130

@@ -147,6 +151,10 @@ internal void OnLogMessageReceivedThreaded(string logString, string stackTrace,
147151
stacktrace_hash = Sha256Hash(stackTrace ?? ""),
148152
};
149153
Enqueue(report);
154+
if (Debug.isDebugBuild)
155+
{
156+
Debug.Log("Untrapped exception queued for batch.");
157+
}
150158
}
151159

152160
private string Sha256Hash(string rawData)
@@ -177,6 +185,12 @@ private string Sha256Hash(string rawData)
177185
/// </summary>
178186
protected override void SendBatch(List<ExceptionReport> batch)
179187
{
188+
if (Debug.isDebugBuild)
189+
{
190+
Debug.Log(string.Format("Processing and sending a batch of {0} exceptions...",
191+
batch.Count));
192+
}
193+
180194
var staticMetadata = RcsPayload.GetStaticMetadata();
181195
var dynamicMetadata = RcsPayload.GetDynamicMetadata();
182196

@@ -213,9 +227,11 @@ protected override void SendBatch(List<ExceptionReport> batch)
213227
binary_name = 21, // UNITY_GMA_SDK
214228
}
215229
};
216-
// TODO(jochac): Use http://go/jspb-wireformat#message-layout instead.
217-
string jsonPayload = JsonUtility.ToJson(request);
218-
SendToRcs(jsonPayload);
230+
string jspbPayload = JspbConverter.ToJspb(request);
231+
if (jspbPayload != null)
232+
{
233+
SendToRcs(jspbPayload);
234+
}
219235
}
220236
#endregion
221237
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
using System.Collections.Generic;
2+
using System.Text;
3+
using UnityEngine;
4+
5+
namespace GoogleMobileAds.Common
6+
{
7+
/// <summary>
8+
/// A helper class to serialize objects to JSPB format.
9+
/// </summary>
10+
internal static class JspbConverter
11+
{
12+
internal static string ToJspb<TPayload>(LoggableRemoteCaptureRequest<TPayload> request)
13+
{
14+
var payloads = new List<string>();
15+
if (request.payloads != null)
16+
{
17+
foreach (var payload in request.payloads)
18+
{
19+
if (payload is ExceptionLoggablePayload)
20+
{
21+
payloads.Add(ToJspb((ExceptionLoggablePayload)(object)payload));
22+
}
23+
else
24+
{
25+
Debug.LogError("JspbConverter encountered an unknown payload type: " +
26+
payload.GetType());
27+
}
28+
}
29+
}
30+
if (payloads.Count == 0)
31+
{
32+
Debug.LogError("No payloads found in the request.");
33+
return null;
34+
}
35+
return string.Format("[[{0}],{1}]",
36+
string.Join(",", payloads.ToArray()),
37+
ToJspb(request.client_ping_metadata));
38+
}
39+
40+
// VisibleForTesting
41+
internal static string ToJspb(ClientPingMetadata metadata)
42+
{
43+
return string.Format("[{0}]", metadata.binary_name);
44+
}
45+
46+
// VisibleForTesting
47+
internal static string QuoteString(string s)
48+
{
49+
if (s == null) return "null";
50+
51+
StringBuilder sb = new StringBuilder();
52+
sb.Append("\"");
53+
foreach (char c in s)
54+
{
55+
switch (c)
56+
{
57+
// Escape quotes and slashes.
58+
case '\"':
59+
sb.Append("\\\"");
60+
break;
61+
case '\\':
62+
sb.Append("\\\\");
63+
break;
64+
case '/':
65+
sb.Append("\\/");
66+
break;
67+
// Escape control characters.
68+
case '\b':
69+
sb.Append("\\b");
70+
break;
71+
case '\f':
72+
sb.Append("\\f");
73+
break;
74+
case '\n':
75+
sb.Append("\\n");
76+
break;
77+
case '\r':
78+
sb.Append("\\r");
79+
break;
80+
case '\t':
81+
sb.Append("\\t");
82+
break;
83+
default:
84+
// Characters within the printable ASCII range (32-126) are appended
85+
// directly. Other characters (control characters or outside ASCII) are
86+
// escaped as Unicode.
87+
int i = (int)c;
88+
if (i < 32 || i > 126)
89+
{
90+
sb.AppendFormat("\\u{0:X4}", i);
91+
}
92+
else
93+
{
94+
sb.Append(c);
95+
}
96+
break;
97+
}
98+
}
99+
sb.Append("\"");
100+
return sb.ToString();
101+
}
102+
103+
#region Exceptions handling
104+
// VisibleForTesting
105+
internal static string ToJspb(ExceptionLoggablePayload payload)
106+
{
107+
if (payload.unity_gma_sdk_exception_message == null) return "[]";
108+
109+
// unity_gma_sdk_exception_message has field index 35.
110+
return string.Format("[{{\"35\":{0}}}]",
111+
ToJspb(payload.unity_gma_sdk_exception_message));
112+
}
113+
114+
// VisibleForTesting
115+
internal static string ToJspb(ExceptionReport report)
116+
{
117+
return string.Format(
118+
"[{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18}]",
119+
QuoteString(report.time_msec),
120+
report.trapped.ToString().ToLower(),
121+
QuoteString(report.name),
122+
QuoteString(report.exception_class),
123+
QuoteString(report.top_exception),
124+
QuoteString(report.stacktrace),
125+
QuoteString(report.stacktrace_hash),
126+
QuoteString(report.session_id),
127+
QuoteString(report.app_id),
128+
QuoteString(report.app_version_name),
129+
QuoteString(report.platform),
130+
QuoteString(report.unity_version),
131+
QuoteString(report.os_version),
132+
QuoteString(report.device_model),
133+
QuoteString(report.country),
134+
report.total_cpu,
135+
QuoteString(report.total_memory_bytes),
136+
QuoteString(report.network_type),
137+
QuoteString(report.orientation));
138+
}
139+
#endregion
140+
}
141+
}

source/plugin/Assets/GoogleMobileAds/Common/RcsClient.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,13 @@ protected string GetEpochMillis()
9898
/// <summary>
9999
/// Sends the batch of items to RCS.
100100
/// </summary>
101-
protected void SendToRcs(string jsonPayload)
101+
protected void SendToRcs(string jspbPayload)
102102
{
103-
StartCoroutine(PostRequest(ProdRcsUrl, jsonPayload));
103+
if (Debug.isDebugBuild)
104+
{
105+
Debug.Log("RCS JSPB payload: " + jspbPayload);
106+
}
107+
StartCoroutine(PostRequest(ProdRcsUrl, jspbPayload));
104108
}
105109

106110
/// <summary>
@@ -134,13 +138,13 @@ private void ResetBatchTimer()
134138
}
135139

136140
/// <summary>
137-
/// Coroutine to send a JSON payload via HTTP POST.
141+
/// Coroutine to send a JSPB payload via HTTP POST.
138142
/// </summary>
139-
private IEnumerator PostRequest(string url, string jsonPayload)
143+
private IEnumerator PostRequest(string url, string jspbPayload)
140144
{
141145
using (UnityWebRequest uwr = new UnityWebRequest(url, "POST"))
142146
{
143-
byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonPayload);
147+
byte[] bodyRaw = Encoding.UTF8.GetBytes(jspbPayload);
144148
uwr.uploadHandler = new UploadHandlerRaw(bodyRaw);
145149
uwr.downloadHandler = new DownloadHandlerBuffer();
146150
uwr.SetRequestHeader("Content-Type", "application/json");
@@ -157,6 +161,12 @@ private IEnumerator PostRequest(string url, string jsonPayload)
157161
"Error sending batch: {0} | Response code: {1}.",
158162
uwr.error, uwr.responseCode));
159163
}
164+
else if (Debug.isDebugBuild)
165+
{
166+
// This only guarantees transport, not that the request is fully processed as
167+
// RCS will just drop unknown fields if it can't otherwise parse them.
168+
Debug.Log("Batch sent successfully.");
169+
}
160170
}
161171
}
162172

0 commit comments

Comments
 (0)