Joey Perrott d1ea1f4c7f build: update license headers to reference Google LLC (#37205)
Update the license headers throughout the repository to reference Google LLC
rather than Google Inc, for the required license headers.

PR Close #37205
2020-05-26 14:26:58 -04:00

114 lines
3.4 KiB
TypeScript

/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Adapter} from './adapter';
import {Debuggable, DebugLogger} from './api';
const DEBUG_LOG_BUFFER_SIZE = 100;
interface DebugMessage {
time: number;
value: string;
context: string;
}
export class DebugHandler implements DebugLogger {
// There are two debug log message arrays. debugLogA records new debugging messages.
// Once it reaches DEBUG_LOG_BUFFER_SIZE, the array is moved to debugLogB and a new
// array is assigned to debugLogA. This ensures that insertion to the debug log is
// always O(1) no matter the number of logged messages, and that the total number
// of messages in the log never exceeds 2 * DEBUG_LOG_BUFFER_SIZE.
private debugLogA: DebugMessage[] = [];
private debugLogB: DebugMessage[] = [];
constructor(readonly driver: Debuggable, readonly adapter: Adapter) {}
async handleFetch(req: Request): Promise<Response> {
const [state, versions, idle] = await Promise.all([
this.driver.debugState(),
this.driver.debugVersions(),
this.driver.debugIdleState(),
]);
const msgState = `NGSW Debug Info:
Driver state: ${state.state} (${state.why})
Latest manifest hash: ${state.latestHash || 'none'}
Last update check: ${this.since(state.lastUpdateCheck)}`;
const msgVersions = versions
.map(version => `=== Version ${version.hash} ===
Clients: ${version.clients.join(', ')}`)
.join('\n\n');
const msgIdle = `=== Idle Task Queue ===
Last update tick: ${this.since(idle.lastTrigger)}
Last update run: ${this.since(idle.lastRun)}
Task queue:
${idle.queue.map(v => ' * ' + v).join('\n')}
Debug log:
${this.formatDebugLog(this.debugLogB)}
${this.formatDebugLog(this.debugLogA)}
`;
return this.adapter.newResponse(
`${msgState}
${msgVersions}
${msgIdle}`,
{headers: this.adapter.newHeaders({'Content-Type': 'text/plain'})});
}
since(time: number|null): string {
if (time === null) {
return 'never';
}
let age = this.adapter.time - time;
const days = Math.floor(age / 86400000);
age = age % 86400000;
const hours = Math.floor(age / 3600000);
age = age % 3600000;
const minutes = Math.floor(age / 60000);
age = age % 60000;
const seconds = Math.floor(age / 1000);
const millis = age % 1000;
return '' + (days > 0 ? `${days}d` : '') + (hours > 0 ? `${hours}h` : '') +
(minutes > 0 ? `${minutes}m` : '') + (seconds > 0 ? `${seconds}s` : '') +
(millis > 0 ? `${millis}u` : '');
}
log(value: string|Error, context: string = ''): void {
// Rotate the buffers if debugLogA has grown too large.
if (this.debugLogA.length === DEBUG_LOG_BUFFER_SIZE) {
this.debugLogB = this.debugLogA;
this.debugLogA = [];
}
// Convert errors to string for logging.
if (typeof value !== 'string') {
value = this.errorToString(value);
}
// Log the message.
this.debugLogA.push({value, time: this.adapter.time, context});
}
private errorToString(err: Error): string {
return `${err.name}(${err.message}, ${err.stack})`;
}
private formatDebugLog(log: DebugMessage[]): string {
return log.map(entry => `[${this.since(entry.time)}] ${entry.value} ${entry.context}`)
.join('\n');
}
}