mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
normalize logging of dates in siteUsage across databases (#675)
Date handling for SQLite and PostgreSQL is inconsistent. This makes sure that dates in `siteUsage` logs are in a consistent format that includes time zone information.
This commit is contained in:
parent
e92e42c063
commit
bc6f550471
@ -986,6 +986,11 @@ export function buildTelemetryEventChecker(telemetryLevel: TelemetryLevel) {
|
|||||||
`but received a value of type ${typeof value}`
|
`but received a value of type ${typeof value}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (typeof value === 'string' && !hasTimezone(value)) {
|
||||||
|
throw new Error(
|
||||||
|
`Telemetry metadata ${key} of event ${event} has an ambiguous date string`
|
||||||
|
);
|
||||||
|
}
|
||||||
} else if (dataType !== typeof value) {
|
} else if (dataType !== typeof value) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Telemetry metadata ${key} of event ${event} expected a value of type ${dataType} ` +
|
`Telemetry metadata ${key} of event ${event} expected a value of type ${dataType} ` +
|
||||||
@ -996,4 +1001,11 @@ export function buildTelemetryEventChecker(telemetryLevel: TelemetryLevel) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that datetime looks like it has a timezone in it. If not,
|
||||||
|
// that could be a problem for whatever ingests the data.
|
||||||
|
function hasTimezone(isoDateString: string) {
|
||||||
|
// Use a regular expression to check for a timezone offset or 'Z'
|
||||||
|
return /([+-]\d{2}:\d{2}|Z)$/.test(isoDateString);
|
||||||
|
}
|
||||||
|
|
||||||
export type TelemetryEventChecker = (event: TelemetryEvent, metadata?: TelemetryMetadata) => void;
|
export type TelemetryEventChecker = (event: TelemetryEvent, metadata?: TelemetryMetadata) => void;
|
||||||
|
@ -13,6 +13,7 @@ import log from 'app/server/lib/log';
|
|||||||
import { IPermitStore } from 'app/server/lib/Permit';
|
import { IPermitStore } from 'app/server/lib/Permit';
|
||||||
import { optStringParam, stringParam } from 'app/server/lib/requestUtils';
|
import { optStringParam, stringParam } from 'app/server/lib/requestUtils';
|
||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
|
import moment from 'moment';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import * as Fetch from 'node-fetch';
|
import * as Fetch from 'node-fetch';
|
||||||
import { EntityManager } from 'typeorm';
|
import { EntityManager } from 'typeorm';
|
||||||
@ -185,8 +186,8 @@ export class Housekeeper {
|
|||||||
numDocs: Number(summary.num_docs),
|
numDocs: Number(summary.num_docs),
|
||||||
numWorkspaces: Number(summary.num_workspaces),
|
numWorkspaces: Number(summary.num_workspaces),
|
||||||
numMembers: Number(summary.num_members),
|
numMembers: Number(summary.num_members),
|
||||||
lastActivity: summary.last_activity,
|
lastActivity: normalizedDateTimeString(summary.last_activity),
|
||||||
earliestDocCreatedAt: summary.earliest_doc_created_at,
|
earliestDocCreatedAt: normalizedDateTimeString(summary.earliest_doc_created_at),
|
||||||
},
|
},
|
||||||
full: {
|
full: {
|
||||||
stripePlanId: summary.stripe_plan_id,
|
stripePlanId: summary.stripe_plan_id,
|
||||||
@ -398,3 +399,29 @@ export class Housekeeper {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output an ISO8601 format datetime string, with timezone.
|
||||||
|
* Any string fed in without timezone is expected to be in UTC.
|
||||||
|
*
|
||||||
|
* When connected to postgres, dates will be extracted as Date objects,
|
||||||
|
* with timezone information. The normalization done here is not
|
||||||
|
* really needed in this case.
|
||||||
|
*
|
||||||
|
* Timestamps in SQLite are stored as UTC, and read as strings
|
||||||
|
* (without timezone information). The normalization here is
|
||||||
|
* pretty important in this case.
|
||||||
|
*/
|
||||||
|
function normalizedDateTimeString(dateTime: any): string {
|
||||||
|
if (!dateTime) { return dateTime; }
|
||||||
|
if (dateTime instanceof Date) {
|
||||||
|
return moment(dateTime).toISOString();
|
||||||
|
}
|
||||||
|
if (typeof dateTime === 'string') {
|
||||||
|
// When SQLite returns a string, it will be in UTC.
|
||||||
|
// Need to make sure it actually have timezone info in it
|
||||||
|
// (will not by default).
|
||||||
|
return moment.utc(dateTime).toISOString();
|
||||||
|
}
|
||||||
|
throw new Error(`normalizedDateTimeString cannot handle ${dateTime}`);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user