ionic-logging-viewer
Version:
Viewer component for logs written by ionic-logging-service
119 lines • 17.9 kB
JavaScript
import { Component, Input } from "@angular/core";
import { LoggingService, LogLevelConverter } from "ionic-logging-service";
import { LoggingViewerFilterService } from "../logging-viewer-filter.service";
import * as i0 from "@angular/core";
import * as i1 from "ionic-logging-service";
import * as i2 from "../logging-viewer-filter.service";
import * as i3 from "@angular/common";
import * as i4 from "@ionic/angular";
/**
* Component for displaying the current logs.
*
* The component can be embedded in any web page using:
*
* <ionic-logging-viewer></ionic-logging-viewer>
*/
export class LoggingViewerComponent {
/**
* Creates a new instance of the component.
*/
constructor(loggingService, loggingViewerFilterService) {
this.loggingService = loggingService;
this.loggingViewerFilterService = loggingViewerFilterService;
this.logger = loggingService.getLogger("Ionic.Logging.Viewer.Component");
const methodName = "ctor";
this.logger.entry(methodName);
this.logger.exit(methodName);
}
/**
* Initialize the component.
*
* This is done by reading the filter data from [LoggingViewerFilterService](LoggingViewerFilterService.html)
* and the log messages from [LoggingService](../../../ionic-logging-service/typedoc/index.html).
* If the localStorageKeys property is set, the messages are read from local storage.
*/
ngOnInit() {
const methodName = "ngOnInit";
this.logger.entry(methodName);
this.loadLogMessages();
this.filterLogMessages();
// subscribe to loggingService.logMessagesChanged event, to refresh, when new message is logged
this.logMessagesChangedSubscription = this.loggingService.logMessagesChanged.subscribe(async () => {
this.loadLogMessages();
this.filterLogMessages();
});
// subscribe to loggingViewerFilterService.filterChanged event, to refresh, when filter is modified
this.filterChangedSubscription = this.loggingViewerFilterService.filterChanged.subscribe(() => {
this.filterLogMessages();
});
this.logger.exit(methodName);
}
/**
* Clean up.
*/
ngOnDestroy() {
const methodName = "ngOnDestroy";
this.logger.entry(methodName);
this.logMessagesChangedSubscription.unsubscribe();
this.filterChangedSubscription.unsubscribe();
this.logger.exit(methodName);
}
/**
* Filter the log messages.
*/
filterLogMessages() {
this.logMessagesForDisplay = this.logMessages.filter((message) => this.filterLogMessagesByLevel(message) && this.filterLogMessagesBySearch(message));
}
/**
* Check if the log message's level fulfills the level condition.
*
* @param message the log message to check
* @returns true if check was successful
*/
filterLogMessagesByLevel(message) {
const levelValue = this.loggingViewerFilterService.level;
return LogLevelConverter.levelFromString(message.level) >= LogLevelConverter.levelFromString(levelValue);
}
/**
* Check if the log message fulfills the search condition.
*
* The search value gets searched in:
* - logger name
* - method name
* - message
*
* @param message the log message to check
* @returns true if check was successful
*/
filterLogMessagesBySearch(message) {
const searchValue = new RegExp(this.loggingViewerFilterService.search, "i");
return message.logger.search(searchValue) >= 0 ||
message.methodName.search(searchValue) >= 0 ||
message.message.join("|").search(searchValue) >= 0;
}
/**
* Load the current log messages.
* For unit test purposes mainly.
*/
loadLogMessages() {
if (this.localStorageKeys) {
this.logMessages = [];
for (const localStorageKey of this.localStorageKeys.split(",")) {
this.logMessages = this.logMessages.concat(this.loggingService.getLogMessagesFromLocalStorage(localStorageKey));
}
this.logMessages = this.logMessages.sort((a, b) => a.timeStamp.getTime() - b.timeStamp.getTime());
}
else {
this.logMessages = this.loggingService.getLogMessages();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.2", ngImport: i0, type: LoggingViewerComponent, deps: [{ token: i1.LoggingService }, { token: i2.LoggingViewerFilterService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.2", type: LoggingViewerComponent, selector: "ionic-logging-viewer", inputs: { localStorageKeys: "localStorageKeys" }, ngImport: i0, template: "<ion-list>\n\t<ion-item *ngFor=\"let logMessage of logMessagesForDisplay\">\n\t\t<ion-label>\n\t\t\t<p>{{ logMessage.timeStamp | date:'dd.MM.yyyy HH:mm:ss' }} {{ logMessage.level }}</p>\n\t\t\t<p>{{ logMessage.logger }}</p>\n\t\t\t<p>\n\t\t\t\t{{ logMessage.methodName }}\n\t\t\t\t<span *ngFor=\"let messagePart of logMessage.message\"> {{ messagePart }} </span>\n\t\t\t</p>\n\t\t</ion-label>\n\t</ion-item>\n</ion-list>", styles: [""], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: i4.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i4.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i4.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "pipe", type: i3.DatePipe, name: "date" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.2", ngImport: i0, type: LoggingViewerComponent, decorators: [{
type: Component,
args: [{ selector: "ionic-logging-viewer", template: "<ion-list>\n\t<ion-item *ngFor=\"let logMessage of logMessagesForDisplay\">\n\t\t<ion-label>\n\t\t\t<p>{{ logMessage.timeStamp | date:'dd.MM.yyyy HH:mm:ss' }} {{ logMessage.level }}</p>\n\t\t\t<p>{{ logMessage.logger }}</p>\n\t\t\t<p>\n\t\t\t\t{{ logMessage.methodName }}\n\t\t\t\t<span *ngFor=\"let messagePart of logMessage.message\"> {{ messagePart }} </span>\n\t\t\t</p>\n\t\t</ion-label>\n\t</ion-item>\n</ion-list>" }]
}], ctorParameters: () => [{ type: i1.LoggingService }, { type: i2.LoggingViewerFilterService }], propDecorators: { localStorageKeys: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2luZy12aWV3ZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvaW9uaWMtbG9nZ2luZy12aWV3ZXIvc3JjL2xpYi9sb2dnaW5nLXZpZXdlci9sb2dnaW5nLXZpZXdlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9pb25pYy1sb2dnaW5nLXZpZXdlci9zcmMvbGliL2xvZ2dpbmctdmlld2VyL2xvZ2dpbmctdmlld2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQXFCLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUdwRSxPQUFPLEVBQVUsY0FBYyxFQUFFLGlCQUFpQixFQUFjLE1BQU0sdUJBQXVCLENBQUM7QUFFOUYsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7Ozs7OztBQUU5RTs7Ozs7O0dBTUc7QUFNSCxNQUFNLE9BQU8sc0JBQXNCO0lBa0JsQzs7T0FFRztJQUNILFlBQ1MsY0FBOEIsRUFDOUIsMEJBQXNEO1FBRHRELG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM5QiwrQkFBMEIsR0FBMUIsMEJBQTBCLENBQTRCO1FBRTlELElBQUksQ0FBQyxNQUFNLEdBQUcsY0FBYyxDQUFDLFNBQVMsQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO1FBQ3pFLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQztRQUMxQixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUU5QixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksUUFBUTtRQUNkLE1BQU0sVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM5QixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENB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QUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNuRyxDQUFDO2FBQU0sQ0FBQztZQUNQLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN6RCxDQUFDO0lBQ0YsQ0FBQzs4R0E1SFcsc0JBQXNCO2tHQUF0QixzQkFBc0IsOEdDbkJuQyxzYUFXVzs7MkZEUUUsc0JBQXNCO2tCQUxsQyxTQUFTOytCQUNDLHNCQUFzQjs0SEFVekIsZ0JBQWdCO3NCQUR0QixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkRlc3Ryb3ksIE9uSW5pdCwgSW5wdXQgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSBcInJ4anNcIjtcblxuaW1wb3J0IHsgTG9nZ2VyLCBMb2dnaW5nU2VydmljZSwgTG9nTGV2ZWxDb252ZXJ0ZXIsIExvZ01lc3NhZ2UgfSBmcm9tIFwiaW9uaWMtbG9nZ2luZy1zZXJ2aWNlXCI7XG5cbmltcG9ydCB7IExvZ2dpbmdWaWV3ZXJGaWx0ZXJTZXJ2aWNlIH0gZnJvbSBcIi4uL2xvZ2dpbmctdmlld2VyLWZpbHRlci5zZXJ2aWNlXCI7XG5cbi8qKlxuICogQ29tcG9uZW50IGZvciBkaXNwbGF5aW5nIHRoZSBjdXJyZW50IGxvZ3MuXG4gKlxuICogVGhlIGNvbXBvbmVudCBjYW4gYmUgZW1iZWRkZWQgaW4gYW55IHdlYiBwYWdlIHVzaW5nOlxuICpcbiAqICZsdDtpb25pYy1sb2dnaW5nLXZpZXdlcj4mbHQ7L2lvbmljLWxvZ2dpbmctdmlld2VyPlxuICovXG5AQ29tcG9uZW50KHtcblx0c2VsZWN0b3I6IFwiaW9uaWMtbG9nZ2luZy12aWV3ZXJcIixcblx0dGVtcGxhdGVVcmw6IFwiLi9sb2dnaW5nLXZpZXdlci5jb21wb25lbnQuaHRtbFwiLFxuXHRzdHlsZVVybHM6IFtcIi4vbG9nZ2luZy12aWV3ZXIuY29tcG9uZW50LnNjc3NcIl1cbn0pXG5leHBvcnQgY2xhc3MgTG9nZ2luZ1ZpZXdlckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcblxuXHQvKipcblx0ICogQ29tbWEtc2VwYXJhdGVkIGxpc3Qgb2YgbG9jYWxTdG9yYWdlS2V5cy4gSWYgc2V0LCB0aGUgbG9ncyBnZXQgbG9hZGVkIGZyb20gbG9jYWxTdG9yYWdlIGluc3RlYWQgb2YgbWVtb3J5LlxuXHQgKi9cblx0QElucHV0KClcblx0cHVibGljIGxvY2FsU3RvcmFnZUtleXM6IHN0cmluZztcblxuXHQvKipcblx0ICogTG9nIG1lc3NhZ2VzIHdoaWNoIGZ1bGZpbGwgdGhlIGZpbHRlciBjb25kaXRpb24uXG5cdCAqL1xuXHRwdWJsaWMgbG9nTWVzc2FnZXNGb3JEaXNwbGF5OiBMb2dNZXNzYWdlW107XG5cblx0cHJpdmF0ZSBsb2dnZXI6IExvZ2dlcjtcblx0cHJpdmF0ZSBsb2dNZXNzYWdlczogTG9nTWVzc2FnZVtdO1xuXHRwcml2YXRlIGxvZ01lc3NhZ2VzQ2hhbmdlZFN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuXHRwcml2YXRlIGZpbHRlckNoYW5nZWRTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgY29tcG9uZW50LlxuXHQgKi9cblx0Y29uc3RydWN0b3IoXG5cdFx0cHJpdmF0ZSBsb2dnaW5nU2VydmljZTogTG9nZ2luZ1NlcnZpY2UsXG5cdFx0cHJpdmF0ZSBsb2dnaW5nVmlld2VyRmlsdGVyU2VydmljZTogTG9nZ2luZ1ZpZXdlckZpbHRlclNlcnZpY2UpIHtcblxuXHRcdHRoaXMubG9nZ2VyID0gbG9nZ2luZ1NlcnZpY2UuZ2V0TG9nZ2VyKFwiSW9uaWMuTG9nZ2luZy5WaWV3ZXIuQ29tcG9uZW50XCIpO1xuXHRcdGNvbnN0IG1ldGhvZE5hbWUgPSBcImN0b3JcIjtcblx0XHR0aGlzLmxvZ2dlci5lbnRyeShtZXRob2ROYW1lKTtcblxuXHRcdHRoaXMubG9nZ2VyLmV4aXQobWV0aG9kTmFtZSk7XG5cdH1cblxuXHQvKipcblx0ICogSW5pdGlhbGl6ZSB0aGUgY29tcG9uZW50LlxuXHQgKlxuXHQgKiBUaGlzIGlzIGRvbmUgYnkgcmVhZGluZyB0aGUgZmlsdGVyIGRhdGEgZnJvbSBbTG9nZ2luZ1ZpZXdlckZpbHRlclNlcnZpY2VdKExvZ2dpbmdWaWV3ZXJGaWx0ZXJTZXJ2aWNlLmh0bWwpXG5cdCAqIGFuZCB0aGUgbG9nIG1lc3NhZ2VzIGZyb20gW0xvZ2dpbmdTZXJ2aWNlXSguLi8uLi8uLi9pb25pYy1sb2dnaW5nLXNlcnZpY2UvdHlwZWRvYy9pbmRleC5odG1sKS5cblx0ICogSWYgdGhlIGxvY2FsU3RvcmFnZUtleXMgcHJvcGVydHkgaXMgc2V0LCB0aGUgbWVzc2FnZXMgYXJlIHJlYWQgZnJvbSBsb2NhbCBzdG9yYWdlLlxuXHQgKi9cblx0cHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuXHRcdGNvbnN0IG1ldGhvZE5hbWUgPSBcIm5nT25Jbml0XCI7XG5cdFx0dGhpcy5sb2dnZXIuZW50cnkobWV0aG9kTmFtZSk7XG5cblx0XHR0aGlzLmxvYWRMb2dNZXNzYWdlcygpO1xuXHRcdHRoaXMuZmlsdGVyTG9nTWVzc2FnZXMoKTtcblxuXHRcdC8vIHN1YnNjcmliZSB0byBsb2dnaW5nU2VydmljZS5sb2dNZXNzYWdlc0NoYW5nZWQgZXZlbnQsIHRvIHJlZnJlc2gsIHdoZW4gbmV3IG1lc3NhZ2UgaXMgbG9nZ2VkXG5cdFx0dGhpcy5sb2dNZXNzYWdlc0NoYW5nZWRTdWJzY3JpcHRpb24gPSB0aGlzLmxvZ2dpbmdTZXJ2aWNlLmxvZ01lc3NhZ2VzQ2hhbmdlZC5zdWJzY3JpYmUoYXN5bmMgKCkgPT4ge1xuXHRcdFx0dGhpcy5sb2FkTG9nTWVzc2FnZXMoKTtcblx0XHRcdHRoaXMuZmlsdGVyTG9nTWVzc2FnZXMoKTtcblx0XHR9KTtcblxuXHRcdC8vIHN1YnNjcmliZSB0byBsb2dnaW5nVmlld2VyRmlsdGVyU2VydmljZS5maWx0ZXJDaGFuZ2VkIGV2ZW50LCB0byByZWZyZXNoLCB3aGVuIGZpbHRlciBpcyBtb2RpZmllZFxuXHRcdHRoaXMuZmlsdGVyQ2hhbmdlZFN1YnNjcmlwdGlvbiA9IHRoaXMubG9nZ2luZ1ZpZXdlckZpbHRlclNlcnZpY2UuZmlsdGVyQ2hhbmdlZC5zdWJzY3JpYmUoKCkgPT4ge1xuXHRcdFx0dGhpcy5maWx0ZXJMb2dNZXNzYWdlcygpO1xuXHRcdH0pO1xuXG5cdFx0dGhpcy5sb2dnZXIuZXhpdChtZXRob2ROYW1lKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDbGVhbiB1cC5cblx0ICovXG5cdHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcblx0XHRjb25zdCBtZXRob2ROYW1lID0gXCJuZ09uRGVzdHJveVwiO1xuXHRcdHRoaXMubG9nZ2VyLmVudHJ5KG1ldGhvZE5hbWUpO1xuXG5cdFx0dGhpcy5sb2dNZXNzYWdlc0NoYW5nZWRTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcblx0XHR0aGlzLmZpbHRlckNoYW5nZWRTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcblxuXHRcdHRoaXMubG9nZ2VyLmV4aXQobWV0aG9kTmFtZSk7XG5cdH1cblxuXHQvKipcblx0ICogRmlsdGVyIHRoZSBsb2cgbWVzc2FnZXMuXG5cdCAqL1xuXHRwdWJsaWMgZmlsdGVyTG9nTWVzc2FnZXMoKTogdm9pZCB7XG5cdFx0dGhpcy5sb2dNZXNzYWdlc0ZvckRpc3BsYXkgPSB0aGlzLmxvZ01lc3NhZ2VzLmZpbHRlcihcblx0XHRcdChtZXNzYWdlKSA9PiB0aGlzLmZpbHRlckxvZ01lc3NhZ2VzQnlMZXZlbChtZXNzYWdlKSAmJiB0aGlzLmZpbHRlckxvZ01lc3NhZ2VzQnlTZWFyY2gobWVzc2FnZSkpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENoZWNrIGlmIHRoZSBsb2cgbWVzc2FnZSdzIGxldmVsIGZ1bGZpbGxzIHRoZSBsZXZlbCBjb25kaXRpb24uXG5cdCAqXG5cdCAqIEBwYXJhbSBtZXNzYWdlIHRoZSBsb2cgbWVzc2FnZSB0byBjaGVja1xuXHQgKiBAcmV0dXJucyB0cnVlIGlmIGNoZWNrIHdhcyBzdWNjZXNzZnVsXG5cdCAqL1xuXHRwdWJsaWMgZmlsdGVyTG9nTWVzc2FnZXNCeUxldmVsKG1lc3NhZ2U6IExvZ01lc3NhZ2UpOiBib29sZWFuIHtcblx0XHRjb25zdCBsZXZlbFZhbHVlID0gdGhpcy5sb2dnaW5nVmlld2VyRmlsdGVyU2VydmljZS5sZXZlbDtcblx0XHRyZXR1cm4gTG9nTGV2ZWxDb252ZXJ0ZXIubGV2ZWxGcm9tU3RyaW5nKG1lc3NhZ2UubGV2ZWwpID49IExvZ0xldmVsQ29udmVydGVyLmxldmVsRnJvbVN0cmluZyhsZXZlbFZhbHVlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVjayBpZiB0aGUgbG9nIG1lc3NhZ2UgZnVsZmlsbHMgdGhlIHNlYXJjaCBjb25kaXRpb24uXG5cdCAqXG5cdCAqIFRoZSBzZWFyY2ggdmFsdWUgZ2V0cyBzZWFyY2hlZCBpbjpcblx0ICogLSBsb2dnZXIgbmFtZVxuXHQgKiAtIG1ldGhvZCBuYW1lXG5cdCAqIC0gbWVzc2FnZVxuXHQgKlxuXHQgKiBAcGFyYW0gbWVzc2FnZSB0aGUgbG9nIG1lc3NhZ2UgdG8gY2hlY2tcblx0ICogQHJldHVybnMgdHJ1ZSBpZiBjaGVjayB3YXMgc3VjY2Vzc2Z1bFxuXHQgKi9cblx0cHVibGljIGZpbHRlckxvZ01lc3NhZ2VzQnlTZWFyY2gobWVzc2FnZTogTG9nTWVzc2FnZSk6IGJvb2xlYW4ge1xuXHRcdGNvbnN0IHNlYXJjaFZhbHVlID0gbmV3IFJlZ0V4cCh0aGlzLmxvZ2dpbmdWaWV3ZXJGaWx0ZXJTZXJ2aWNlLnNlYXJjaCwgXCJpXCIpO1xuXHRcdHJldHVybiBtZXNzYWdlLmxvZ2dlci5zZWFyY2goc2VhcmNoVmFsdWUpID49IDAgfHxcblx0XHRcdG1lc3NhZ2UubWV0aG9kTmFtZS5zZWFyY2goc2VhcmNoVmFsdWUpID49IDAgfHxcblx0XHRcdG1lc3NhZ2UubWVzc2FnZS5qb2luKFwifFwiKS5zZWFyY2goc2VhcmNoVmFsdWUpID49IDA7XG5cdH1cblxuXHQvKipcblx0ICogTG9hZCB0aGUgY3VycmVudCBsb2cgbWVzc2FnZXMuXG5cdCAqIEZvciB1bml0IHRlc3QgcHVycG9zZXMgbWFpbmx5LlxuXHQgKi9cblx0cHVibGljIGxvYWRMb2dNZXNzYWdlcygpOiB2b2lkIHtcblx0XHRpZiAodGhpcy5sb2NhbFN0b3JhZ2VLZXlzKSB7XG5cdFx0XHR0aGlzLmxvZ01lc3NhZ2VzID0gW107XG5cdFx0XHRmb3IgKGNvbnN0IGxvY2FsU3RvcmFnZUtleSBvZiB0aGlzLmxvY2FsU3RvcmFnZUtleXMuc3BsaXQoXCIsXCIpKSB7XG5cdFx0XHRcdHRoaXMubG9nTWVzc2FnZXMgPSB0aGlzLmxvZ01lc3NhZ2VzLmNvbmNhdCh0aGlzLmxvZ2dpbmdTZXJ2aWNlLmdldExvZ01lc3NhZ2VzRnJvbUxvY2FsU3RvcmFnZShsb2NhbFN0b3JhZ2VLZXkpKTtcblx0XHRcdH1cblx0XHRcdHRoaXMubG9nTWVzc2FnZXMgPSB0aGlzLmxvZ01lc3NhZ2VzLnNvcnQoKGEsIGIpID0+IGEudGltZVN0YW1wLmdldFRpbWUoKSAtIGIudGltZVN0YW1wLmdldFRpbWUoKSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMubG9nTWVzc2FnZXMgPSB0aGlzLmxvZ2dpbmdTZXJ2aWNlLmdldExvZ01lc3NhZ2VzKCk7XG5cdFx0fVxuXHR9XG59XG4iLCI8aW9uLWxpc3Q+XG5cdDxpb24taXRlbSAqbmdGb3I9XCJsZXQgbG9nTWVzc2FnZSBvZiBsb2dNZXNzYWdlc0ZvckRpc3BsYXlcIj5cblx0XHQ8aW9uLWxhYmVsPlxuXHRcdFx0PHA+e3sgbG9nTWVzc2FnZS50aW1lU3RhbXAgfCBkYXRlOidkZC5NTS55eXl5IEhIOm1tOnNzJyB9fSB7eyBsb2dNZXNzYWdlLmxldmVsIH19PC9wPlxuXHRcdFx0PHA+e3sgbG9nTWVzc2FnZS5sb2dnZXIgfX08L3A+XG5cdFx0XHQ8cD5cblx0XHRcdFx0e3sgbG9nTWVzc2FnZS5tZXRob2ROYW1lIH19XG5cdFx0XHRcdDxzcGFuICpuZ0Zvcj1cImxldCBtZXNzYWdlUGFydCBvZiBsb2dNZXNzYWdlLm1lc3NhZ2VcIj4ge3sgbWVzc2FnZVBhcnQgfX0gPC9zcGFuPlxuXHRcdFx0PC9wPlxuXHRcdDwvaW9uLWxhYmVsPlxuXHQ8L2lvbi1pdGVtPlxuPC9pb24tbGlzdD4iXX0=