| OLD | NEW |
| 1 /* | 1 /* |
| 2 Copyright 2016 The LUCI Authors. All rights reserved. | 2 Copyright 2016 The LUCI Authors. All rights reserved. |
| 3 Use of this source code is governed under the Apache License, Version 2.0 | 3 Use of this source code is governed under the Apache License, Version 2.0 |
| 4 that can be found in the LICENSE file. | 4 that can be found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 ///<reference path="../logdog-stream/logdog.ts" /> | 7 ///<reference path="../logdog-stream/logdog.ts" /> |
| 8 ///<reference path="../luci-operation/operation.ts" /> | 8 ///<reference path="../luci-operation/operation.ts" /> |
| 9 ///<reference path="../luci-sleep-promise/promise.ts" /> | 9 ///<reference path="../luci-sleep-promise/promise.ts" /> |
| 10 ///<reference path="../rpc/client.ts" /> | 10 ///<reference path="../rpc/client.ts" /> |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 private currentOperation: luci.Operation|null = null; | 185 private currentOperation: luci.Operation|null = null; |
| 186 private currentFetchPromise: Promise<void>|null = null; | 186 private currentFetchPromise: Promise<void>|null = null; |
| 187 | 187 |
| 188 /** Are we in automatic mode? */ | 188 /** Are we in automatic mode? */ |
| 189 private automatic = false; | 189 private automatic = false; |
| 190 /** Are we tailing? */ | 190 /** Are we tailing? */ |
| 191 private fetchFromTail = false; | 191 private fetchFromTail = false; |
| 192 /** Are we in the middle of rendering logs? */ | 192 /** Are we in the middle of rendering logs? */ |
| 193 private rendering = true; | 193 private rendering = true; |
| 194 | 194 |
| 195 private cachedLogStreamUrl: string|undefined = undefined; |
| 196 |
| 195 private loadingStateValue: LoadingState = LoadingState.NONE; | 197 private loadingStateValue: LoadingState = LoadingState.NONE; |
| 196 private streamStatusValue: StreamStatusEntry[]; | 198 private streamStatusValue: StreamStatusEntry[]; |
| 197 | 199 |
| 198 /** | 200 /** |
| 199 * When rendering a Promise that will resolve when the render completes. We | 201 * When rendering a Promise that will resolve when the render completes. We |
| 200 * use this to pipeline parallel data fetching and rendering. | 202 * use this to pipeline parallel data fetching and rendering. |
| 201 */ | 203 */ |
| 202 private renderPromise: Promise<void>|null; | 204 private renderPromise: Promise<void>|null; |
| 203 | 205 |
| 204 constructor( | 206 constructor( |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 this.streamStatusValue = st; | 349 this.streamStatusValue = st; |
| 348 this.updateControls(); | 350 this.updateControls(); |
| 349 } | 351 } |
| 350 | 352 |
| 351 private updateControls() { | 353 private updateControls() { |
| 352 this.view.updateControls({ | 354 this.view.updateControls({ |
| 353 canSplit: this.providerCanSplit, | 355 canSplit: this.providerCanSplit, |
| 354 split: this.isSplit, | 356 split: this.isSplit, |
| 355 bottom: !this.fetchedEndOfStream, | 357 bottom: !this.fetchedEndOfStream, |
| 356 fullyLoaded: (this.fetchedFullStream && (!this.rendering)), | 358 fullyLoaded: (this.fetchedFullStream && (!this.rendering)), |
| 359 logStreamUrl: this.logStreamUrl, |
| 357 loadingState: this.loadingState, | 360 loadingState: this.loadingState, |
| 358 streamStatus: this.streamStatus, | 361 streamStatus: this.streamStatus, |
| 359 }); | 362 }); |
| 360 } | 363 } |
| 361 | 364 |
| 362 /** | 365 /** |
| 363 * Note that the authentication state for the client has changed. This will | 366 * Note that the authentication state for the client has changed. This will |
| 364 * trigger an automatic fetch retry if our previous fetch failed due to | 367 * trigger an automatic fetch retry if our previous fetch failed due to |
| 365 * lack of authentication. | 368 * lack of authentication. |
| 366 */ | 369 */ |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 return (!!(split && split.isSplit())); | 628 return (!!(split && split.isSplit())); |
| 626 } | 629 } |
| 627 | 630 |
| 628 private get fetchedEndOfStream(): boolean { | 631 private get fetchedEndOfStream(): boolean { |
| 629 return (this.provider.fetchedEndOfStream()); | 632 return (this.provider.fetchedEndOfStream()); |
| 630 } | 633 } |
| 631 | 634 |
| 632 private get fetchedFullStream(): boolean { | 635 private get fetchedFullStream(): boolean { |
| 633 return (this.fetchedEndOfStream && (!this.isSplit)); | 636 return (this.fetchedEndOfStream && (!this.isSplit)); |
| 634 } | 637 } |
| 638 |
| 639 private get logStreamUrl(): string|undefined { |
| 640 if (!this.cachedLogStreamUrl) { |
| 641 this.cachedLogStreamUrl = this.provider.getLogStreamUrl(); |
| 642 } |
| 643 return this.cachedLogStreamUrl; |
| 644 } |
| 635 } | 645 } |
| 636 | 646 |
| 637 /** Generic interface for a log provider. */ | 647 /** Generic interface for a log provider. */ |
| 638 interface LogProvider { | 648 interface LogProvider { |
| 639 setStreamStatusCallback(cb: StreamStatusCallback): void; | 649 setStreamStatusCallback(cb: StreamStatusCallback): void; |
| 640 fetch(op: luci.Operation, l: Location): Promise<BufferedLogs>; | 650 fetch(op: luci.Operation, l: Location): Promise<BufferedLogs>; |
| 651 getLogStreamUrl(): string|undefined; |
| 641 | 652 |
| 642 /** Will return null if this LogProvider doesn't support splitting. */ | 653 /** Will return null if this LogProvider doesn't support splitting. */ |
| 643 split(): SplitLogProvider|null; | 654 split(): SplitLogProvider|null; |
| 644 fetchedEndOfStream(): boolean; | 655 fetchedEndOfStream(): boolean; |
| 645 } | 656 } |
| 646 | 657 |
| 647 /** Additional methods for log stream splitting, if supported. */ | 658 /** Additional methods for log stream splitting, if supported. */ |
| 648 interface SplitLogProvider { | 659 interface SplitLogProvider { |
| 649 canSplit(): boolean; | 660 canSplit(): boolean; |
| 650 isSplit(): boolean; | 661 isSplit(): boolean; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 try { | 752 try { |
| 742 let logs = await getLogs; | 753 let logs = await getLogs; |
| 743 this.initialFetch = false; | 754 this.initialFetch = false; |
| 744 this.statusChanged(); | 755 this.statusChanged(); |
| 745 return new BufferedLogs(logs); | 756 return new BufferedLogs(logs); |
| 746 } catch (err) { | 757 } catch (err) { |
| 747 throw resolveErr(err); | 758 throw resolveErr(err); |
| 748 } | 759 } |
| 749 } | 760 } |
| 750 | 761 |
| 762 get descriptor() { |
| 763 return this.fetcher.desc; |
| 764 } |
| 765 |
| 766 getLogStreamUrl(): string|undefined { |
| 767 let desc = this.descriptor; |
| 768 if (desc) { |
| 769 return (desc.tags || {})['logdog.viewer_url']; |
| 770 } |
| 771 return undefined; |
| 772 } |
| 773 |
| 751 setStreamStatusCallback(cb: StreamStatusCallback) { | 774 setStreamStatusCallback(cb: StreamStatusCallback) { |
| 752 this.streamStatusCallback = cb; | 775 this.streamStatusCallback = cb; |
| 753 } | 776 } |
| 754 | 777 |
| 755 private statusChanged() { | 778 private statusChanged() { |
| 756 if (this.streamStatusCallback) { | 779 if (this.streamStatusCallback) { |
| 757 this.streamStatusCallback([this.getStreamStatus()]); | 780 this.streamStatusCallback([this.getStreamStatus()]); |
| 758 } | 781 } |
| 759 } | 782 } |
| 760 | 783 |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1066 private statusChanged() { | 1089 private statusChanged() { |
| 1067 if (this.streamStatusCallback) { | 1090 if (this.streamStatusCallback) { |
| 1068 // Iterate through our composite stream statuses and pick the one that | 1091 // Iterate through our composite stream statuses and pick the one that |
| 1069 // we want to report. | 1092 // we want to report. |
| 1070 this.streamStatusCallback(this.streams.map((entry): LogStreamStatus => { | 1093 this.streamStatusCallback(this.streams.map((entry): LogStreamStatus => { |
| 1071 return entry.status; | 1094 return entry.status; |
| 1072 })); | 1095 })); |
| 1073 } | 1096 } |
| 1074 } | 1097 } |
| 1075 | 1098 |
| 1099 getLogStreamUrl(): string|undefined { |
| 1100 // Return the first log stream viewer URL. IF we have a shared prefix, |
| 1101 // this will always work. Otherwise, returning something is better than |
| 1102 // nothing, so if any of the base streams have a URL, we will return it. |
| 1103 for (let s of this.streams) { |
| 1104 let url = s.ls.getLogStreamUrl(); |
| 1105 if (url) { |
| 1106 return url; |
| 1107 } |
| 1108 } |
| 1109 return undefined; |
| 1110 } |
| 1111 |
| 1076 /** | 1112 /** |
| 1077 * Implements LogProvider.next | 1113 * Implements LogProvider.next |
| 1078 */ | 1114 */ |
| 1079 async fetch(op: luci.Operation, _: Location) { | 1115 async fetch(op: luci.Operation, _: Location) { |
| 1080 // If we're already are fetching the next buffer, this is an error. | 1116 // If we're already are fetching the next buffer, this is an error. |
| 1081 if (this.currentNextPromise) { | 1117 if (this.currentNextPromise) { |
| 1082 throw new Error('In-progress next(), cannot start another.'); | 1118 throw new Error('In-progress next(), cannot start another.'); |
| 1083 } | 1119 } |
| 1084 | 1120 |
| 1085 // Filter out any finished streams from our active list. A stream is | 1121 // Filter out any finished streams from our active list. A stream is |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1295 | 1331 |
| 1296 // Get the next log and increment our index. | 1332 // Get the next log and increment our index. |
| 1297 let log = this.logs[this.index++]; | 1333 let log = this.logs[this.index++]; |
| 1298 if (this.index >= this.logs.length) { | 1334 if (this.index >= this.logs.length) { |
| 1299 this.logs = null; | 1335 this.logs = null; |
| 1300 } | 1336 } |
| 1301 return log; | 1337 return log; |
| 1302 } | 1338 } |
| 1303 } | 1339 } |
| 1304 } | 1340 } |
| OLD | NEW |