1+ import { Logger } from "../logging" ;
2+
13export class UTPBase {
24 type ?: string ;
35 version ?: number ;
@@ -6,12 +8,15 @@ export class UTPBase {
68 processId ?: number ;
79 severity ?: Severity ;
810 message ?: string ;
9- stacktrace ?: string ;
11+ stackTrace ?: string ;
1012 line ?: number ;
13+ lineNumber ?: number ;
1114 file ?: string ;
15+ fileName ?: string ;
1216 name ?: string ;
1317 description ?: string ;
1418 duration ?: number ;
19+ durationMicroseconds ?: number ;
1520 errors ?: unknown [ ] ;
1621}
1722
@@ -20,6 +25,87 @@ export class UTPMemoryLeak extends UTPBase {
2025 memoryLabels ?: Record < string , number > | Array < Record < string , number > > ;
2126}
2227
28+ export class UTPLogEntry extends UTPBase { }
29+
30+ export class UTPTestPlan extends UTPBase {
31+ tests ?: string [ ] ;
32+ }
33+
34+ export interface ScreenSettingsInfo {
35+ ScreenWidth ?: number ;
36+ ScreenHeight ?: number ;
37+ ScreenRefreshRate ?: number ;
38+ Fullscreen ?: boolean ;
39+ }
40+
41+ export class UTPScreenSettings extends UTPBase {
42+ ScreenSettings ?: ScreenSettingsInfo ;
43+ }
44+
45+ export interface PlayerSettingsInfo {
46+ ScriptingBackend ?: string ;
47+ MtRendering ?: boolean ;
48+ GraphicsJobs ?: boolean ;
49+ GpuSkinning ?: boolean ;
50+ GraphicsApi ?: string ;
51+ Batchmode ?: string ;
52+ StereoRenderingPath ?: string ;
53+ RenderThreadingMode ?: string ;
54+ AndroidMinimumSdkVersion ?: string ;
55+ AndroidTargetSdkVersion ?: string ;
56+ ScriptingRuntimeVersion ?: string ;
57+ AndroidTargetArchitecture ?: string ;
58+ StripEngineCode ?: boolean ;
59+ }
60+
61+ export class UTPPlayerSettings extends UTPBase {
62+ PlayerSettings ?: PlayerSettingsInfo ;
63+ }
64+
65+ export interface BuildSettingsInfo {
66+ Platform ?: string ;
67+ BuildTarget ?: string ;
68+ DevelopmentPlayer ?: boolean ;
69+ AndroidBuildSystem ?: string ;
70+ }
71+
72+ export class UTPBuildSettings extends UTPBase {
73+ BuildSettings ?: BuildSettingsInfo ;
74+ }
75+
76+ export interface PlayerSystemInfoDetails {
77+ OperatingSystem ?: string ;
78+ DeviceModel ?: string ;
79+ DeviceName ?: string ;
80+ ProcessorType ?: string ;
81+ ProcessorCount ?: number ;
82+ GraphicsDeviceName ?: string ;
83+ SystemMemorySize ?: number ;
84+ XrModel ?: string ;
85+ XrDevice ?: string ;
86+ }
87+
88+ export class UTPPlayerSystemInfo extends UTPBase {
89+ PlayerSystemInfo ?: PlayerSystemInfoDetails ;
90+ }
91+
92+ export interface QualitySettingsInfo {
93+ Vsync ?: number ;
94+ AntiAliasing ?: number ;
95+ ColorSpace ?: string ;
96+ AnisotropicFiltering ?: string ;
97+ BlendWeights ?: string ;
98+ }
99+
100+ export class UTPQualitySettings extends UTPBase {
101+ QualitySettings ?: QualitySettingsInfo ;
102+ }
103+
104+ export class UTPTestStatus extends UTPBase {
105+ state ?: number ;
106+ iteration ?: number ;
107+ }
108+
23109export interface PlayerBuildInfoStep {
24110 description ?: string ;
25111 duration ?: number ;
@@ -30,7 +116,18 @@ export class UTPPlayerBuildInfo extends UTPBase {
30116 steps ?: PlayerBuildInfoStep [ ] ;
31117}
32118
33- export type UTP = UTPBase | UTPMemoryLeak | UTPPlayerBuildInfo ;
119+ export type UTP =
120+ | UTPBase
121+ | UTPLogEntry
122+ | UTPTestPlan
123+ | UTPScreenSettings
124+ | UTPPlayerSettings
125+ | UTPBuildSettings
126+ | UTPPlayerSystemInfo
127+ | UTPQualitySettings
128+ | UTPTestStatus
129+ | UTPMemoryLeak
130+ | UTPPlayerBuildInfo ;
34131
35132export enum Phase {
36133 Begin = 'Begin' ,
@@ -44,4 +141,70 @@ export enum Severity {
44141 Error = 'Error' ,
45142 Exception = 'Exception' ,
46143 Assert = 'Assert'
144+ }
145+
146+ const allowedUtpKeys = new Set < string > ( [
147+ 'allocatedMemory' ,
148+ 'BuildSettings' ,
149+ 'description' ,
150+ 'duration' ,
151+ 'durationMicroseconds' ,
152+ 'errors' ,
153+ 'file' ,
154+ 'fileName' ,
155+ 'iteration' ,
156+ 'line' ,
157+ 'lineNumber' ,
158+ 'memoryLabels' ,
159+ 'message' ,
160+ 'name' ,
161+ 'phase' ,
162+ 'PlayerSettings' ,
163+ 'PlayerSystemInfo' ,
164+ 'processId' ,
165+ 'QualitySettings' ,
166+ 'ScreenSettings' ,
167+ 'severity' ,
168+ 'stackTrace' ,
169+ 'state' ,
170+ 'steps' ,
171+ 'tests' ,
172+ 'time' ,
173+ 'type' ,
174+ 'version' ,
175+ ] ) ;
176+
177+ /**
178+ * Normalizes UTP telemetry entries to canonical shapes and reports unexpected properties.
179+ * Accepts an optional warn callback to avoid importing logging dependencies here.
180+ */
181+ export function normalizeTelemetryEntry ( entry : unknown ) : UTP {
182+ if ( ! entry || typeof entry !== 'object' ) {
183+ return entry as UTP ;
184+ }
185+
186+ const utp = entry as UTP ;
187+ const record = entry as Record < string , unknown > ;
188+
189+ const stackTraceLegacy = record . stacktrace ;
190+ if ( utp . stackTrace === undefined && typeof stackTraceLegacy === 'string' ) {
191+ utp . stackTrace = stackTraceLegacy ;
192+ }
193+
194+ if ( ! utp . type ) {
195+ Logger . instance . warn ( 'UTP entry missing type property; telemetry entry may be ignored.' ) ;
196+ }
197+
198+ const extras : string [ ] = [ ] ;
199+ for ( const key of Object . keys ( record ) ) {
200+ if ( ! allowedUtpKeys . has ( key ) ) {
201+ extras . push ( key ) ;
202+ }
203+ }
204+
205+ if ( extras . length > 0 ) {
206+ Logger . instance . warn ( `UTP entry contains unrecognized properties: ${ extras . join ( ', ' ) } ` ) ;
207+ }
208+
209+ return utp ;
47210}
0 commit comments