@@ -42,38 +42,6 @@ export function generateReservedMetricIdentifiers(name: string): {
4242 } ;
4343}
4444
45- /**
46- * Verifies if a given value is a valid Metrics object.
47- *
48- * @param v The value to verify
49- * @returns Whether or not `v` is a valid Metrics object.
50- */
51- export function isValidInternalMetricsRepresentation ( v : unknown ) : v is Metrics {
52- if ( isObject ( v ) ) {
53- // The root keys should all be metric types.
54- for ( const metricType in v ) {
55- const metrics = v [ metricType ] ;
56- if ( isObject ( metrics ) ) {
57- for ( const metricIdentifier in metrics ) {
58- if ( ! validateMetricInternalRepresentation ( metricType , metrics [ metricIdentifier ] ) ) {
59- log (
60- LOG_TAG ,
61- `Invalid metric representation found for metric "${ metricIdentifier } "` ,
62- LoggingLevel . Debug
63- ) ;
64- return false ;
65- }
66- }
67- } else {
68- return false ;
69- }
70- }
71- return true ;
72- } else {
73- return false ;
74- }
75- }
76-
7745/**
7846 * Creates the metrics payload from a metrics object with metrics in their internal representation.
7947 *
@@ -260,24 +228,60 @@ class MetricsDatabase {
260228 * @returns The ping payload found for the given parameters or an empty object
261229 * in case no data was found or the data that was found, was invalid.
262230 */
263- private async getAndValidatePingData ( ping : string , lifetime : Lifetime ) : Promise < Metrics > {
231+ private async getCorrectedPingData ( ping : string , lifetime : Lifetime ) : Promise < Metrics > {
264232 const store = this . _chooseStore ( lifetime ) ;
265233 const data = await store . get ( [ ping ] ) ;
266234 if ( isUndefined ( data ) ) {
267235 return { } ;
268236 }
269237
270- if ( ! isValidInternalMetricsRepresentation ( data ) ) {
238+ if ( ! isObject ( data ) ) {
271239 log (
272240 LOG_TAG ,
273- `Unexpected value found for ping "${ ping } " in " ${ lifetime } " store: ${ JSON . stringify ( data ) } . Clearing .` ,
241+ `Invalid value found in storage for ping "${ ping } ". Deleting .` ,
274242 LoggingLevel . Debug
275243 ) ;
276244 await store . delete ( [ ping ] ) ;
277245 return { } ;
278246 }
279247
280- return data ;
248+ const correctedData : Metrics = { } ;
249+ // All top keys should be metric types.
250+ for ( const metricType in data ) {
251+ const metrics = data [ metricType ] ;
252+ if ( ! isObject ( metrics ) ) {
253+ log (
254+ LOG_TAG ,
255+ `Unexpected data found in storage for metrics of type "${ metricType } " in ping "${ ping } ". Deleting.` ,
256+ LoggingLevel . Debug
257+ ) ;
258+ await store . delete ( [ ping , metricType ] ) ;
259+ continue ;
260+ }
261+
262+ for ( const metricIdentifier in metrics ) {
263+ if ( ! validateMetricInternalRepresentation ( metricType , metrics [ metricIdentifier ] ) ) {
264+ log (
265+ LOG_TAG ,
266+ `Invalid value found in storage for metric "${ metricIdentifier } ". Deleting.` ,
267+ LoggingLevel . Debug
268+ ) ;
269+
270+ await store . delete ( [ ping , metricType , metricIdentifier ] ) ;
271+ continue ;
272+ }
273+
274+ if ( ! correctedData [ metricType ] ) {
275+ correctedData [ metricType ] = { } ;
276+ }
277+
278+ // Coersion is fine here, `validateMetricInternalRepresentation`
279+ // validated that this is of the correct type.
280+ correctedData [ metricType ] [ metricIdentifier ] = metrics [ metricIdentifier ] as JSONValue ;
281+ }
282+ }
283+
284+ return correctedData ;
281285 }
282286
283287 private processLabeledMetric ( snapshot : Metrics , metricType : string , metricId : string , metricData : JSONValue ) {
@@ -313,9 +317,9 @@ class MetricsDatabase {
313317 * `undefined` in case the ping doesn't contain any recorded metrics.
314318 */
315319 async getPingMetrics ( ping : string , clearPingLifetimeData : boolean ) : Promise < Metrics | undefined > {
316- const userData = await this . getAndValidatePingData ( ping , Lifetime . User ) ;
317- const pingData = await this . getAndValidatePingData ( ping , Lifetime . Ping ) ;
318- const appData = await this . getAndValidatePingData ( ping , Lifetime . Application ) ;
320+ const userData = await this . getCorrectedPingData ( ping , Lifetime . User ) ;
321+ const pingData = await this . getCorrectedPingData ( ping , Lifetime . Ping ) ;
322+ const appData = await this . getCorrectedPingData ( ping , Lifetime . Application ) ;
319323
320324 if ( clearPingLifetimeData && Object . keys ( pingData ) . length > 0 ) {
321325 await this . clear ( Lifetime . Ping , ping ) ;
0 commit comments