diff --git a/platform/telemetry/src/TelemetryCapability.js b/platform/telemetry/src/TelemetryCapability.js index eb963a21af..cbba2e440c 100644 --- a/platform/telemetry/src/TelemetryCapability.js +++ b/platform/telemetry/src/TelemetryCapability.js @@ -255,8 +255,11 @@ define( // If a telemetryService is not available, // getTelemetryService() should reject, and this should // bubble through subsequent then calls. - return telemetryService - && requestTelemetryFromService().then(getRelevantResponse); + if (!telemetryService) { + return Promise.reject(new Error('TelemetryService is not available')); + } + + return requestTelemetryFromService().then(getRelevantResponse); } else { return telemetryAPI.request(domainObject, fullRequest).then(function (telemetry) { return asSeries(telemetry, defaultDomain, defaultRange, sourceMap); diff --git a/platform/telemetry/test/TelemetryCapabilitySpec.js b/platform/telemetry/test/TelemetryCapabilitySpec.js index 6ad7001d2e..b34a2dac3c 100644 --- a/platform/telemetry/test/TelemetryCapabilitySpec.js +++ b/platform/telemetry/test/TelemetryCapabilitySpec.js @@ -41,6 +41,9 @@ define( return { then: function (callback) { return mockPromise(callback(value)); + }, + catch: (rejected) => { + return Promise.reject(rejected); } }; } @@ -225,19 +228,6 @@ define( }); }); - it("warns if no telemetry service can be injected", function () { - mockInjector.get.and.callFake(function () { - throw ""; - }); - - // Verify precondition - expect(mockLog.warn).not.toHaveBeenCalled(); - - telemetry.requestData(); - - expect(mockLog.info).toHaveBeenCalled(); - }); - it("if a new style telemetry source is available, use it", function () { var mockProvider = {}; mockTelemetryAPI.findSubscriptionProvider.and.returnValue(mockProvider); diff --git a/src/api/telemetry/TelemetryAPI.js b/src/api/telemetry/TelemetryAPI.js index 16527fa1f0..45fff447a9 100644 --- a/src/api/telemetry/TelemetryAPI.js +++ b/src/api/telemetry/TelemetryAPI.js @@ -137,15 +137,17 @@ define([ */ function TelemetryAPI(openmct) { this.openmct = openmct; - this.requestProviders = []; - this.subscriptionProviders = []; - this.metadataProviders = [new DefaultMetadataProvider(this.openmct)]; + + this.formatMapCache = new WeakMap(); + this.formatters = new Map(); this.limitProviders = []; this.metadataCache = new WeakMap(); - this.formatMapCache = new WeakMap(); - this.valueFormatterCache = new WeakMap(); - this.formatters = new Map(); + this.metadataProviders = [new DefaultMetadataProvider(this.openmct)]; + this.noRequestProviderForAllObjects = false; this.requestAbortControllers = new Set(); + this.requestProviders = []; + this.subscriptionProviders = []; + this.valueFormatterCache = new WeakMap(); } TelemetryAPI.prototype.abortAllRequests = function () { @@ -314,6 +316,10 @@ define([ * telemetry data */ TelemetryAPI.prototype.request = function (domainObject) { + if (this.noRequestProviderForAllObjects) { + return Promise.resolve([]); + } + if (arguments.length === 1) { arguments.length = 2; arguments[1] = {}; @@ -326,19 +332,22 @@ define([ this.standardizeRequestOptions(arguments[1]); const provider = this.findRequestProvider.apply(this, arguments); if (!provider) { - return Promise.reject('No provider found'); + this.requestAbortControllers.delete(abortController); + + return this.handleMissingRequestProvider(domainObject); } - return provider.request.apply(provider, arguments).catch((rejected) => { - if (rejected.name !== 'AbortError') { - this.openmct.notifications.error('Error requesting telemetry data, see console for details'); - console.error(rejected); - } + return provider.request.apply(provider, arguments) + .catch((rejected) => { + if (rejected.name !== 'AbortError') { + this.openmct.notifications.error('Error requesting telemetry data, see console for details'); + console.error(rejected); + } - return Promise.reject(rejected); - }).finally(() => { - this.requestAbortControllers.delete(abortController); - }); + return Promise.reject(rejected); + }).finally(() => { + this.requestAbortControllers.delete(abortController); + }); }; /** @@ -495,6 +504,36 @@ define([ return this.formatMapCache.get(metadata); }; + /** + * Error Handling: Missing Request provider + * + * @returns Promise + */ + TelemetryAPI.prototype.handleMissingRequestProvider = function (domainObject) { + this.noRequestProviderForAllObjects = this.requestProviders.every(requestProvider => { + const supportsRequest = requestProvider.supportsRequest.apply(requestProvider, arguments); + const hasRequestProvider = Object.hasOwn(requestProvider, 'request'); + + return supportsRequest && hasRequestProvider; + }); + + let message = ''; + let detailMessage = ''; + if (this.noRequestProviderForAllObjects) { + message = 'Missing request providers, see console for details'; + detailMessage = 'Missing request provider for all request providers'; + } else { + message = 'Missing request provider, see console for details'; + const { name, identifier } = domainObject; + detailMessage = `Missing request provider for domainObject, name: ${name}, identifier: ${JSON.stringify(identifier)}`; + } + + this.openmct.notifications.error(message); + console.error(detailMessage); + + return Promise.resolve([]); + }; + /** * Register a new telemetry data formatter. * @param {Format} format the diff --git a/src/api/telemetry/TelemetryAPISpec.js b/src/api/telemetry/TelemetryAPISpec.js index 1be6907822..c79e652782 100644 --- a/src/api/telemetry/TelemetryAPISpec.js +++ b/src/api/telemetry/TelemetryAPISpec.js @@ -24,7 +24,6 @@ import TelemetryAPI from './TelemetryAPI'; const { TelemetryCollection } = require("./TelemetryCollection"); describe('Telemetry API', function () { - const NO_PROVIDER = 'No provider found'; let openmct; let telemetryAPI; @@ -66,6 +65,12 @@ describe('Telemetry API', function () { }, type: 'sample-type' }; + + openmct.notifications = { + error: () => { + console.log('sample error notification'); + } + }; }); it('provides consistent results without providers', function (done) { @@ -73,12 +78,11 @@ describe('Telemetry API', function () { expect(unsubscribe).toEqual(jasmine.any(Function)); - telemetryAPI.request(domainObject).then( - () => {}, - (error) => { - expect(error).toBe(NO_PROVIDER); - } - ).finally(done); + telemetryAPI.request(domainObject) + .then((data) => { + expect(data).toEqual([]); + }) + .finally(done); }); it('skips providers that do not match', function (done) { @@ -98,8 +102,6 @@ describe('Telemetry API', function () { expect(telemetryProvider.supportsRequest) .toHaveBeenCalledWith(domainObject, jasmine.any(Object)); expect(telemetryProvider.request).not.toHaveBeenCalled(); - }, (error) => { - expect(error).toBe(NO_PROVIDER); }).finally(done); });