diff --git a/public/app/features/plugins/loader/packageMetrics.test.ts b/public/app/features/plugins/loader/packageMetrics.test.ts index dd69e6ba6e6..eb06454acaf 100644 --- a/public/app/features/plugins/loader/packageMetrics.test.ts +++ b/public/app/features/plugins/loader/packageMetrics.test.ts @@ -34,21 +34,53 @@ describe('trackPackageUsage', () => { }); }); - it('should log API usage and return a proxy object', () => { + it('should not log API usage and for non-grafana packages', () => { const obj = { foo: 'bar', }; - const packageName = 'your-package'; + const packageName = 'lodash'; + + const result = trackPackageUsage(obj, packageName); + + mockUsage(result.foo); + + expect(logInfoMock).toHaveBeenCalledTimes(0); + }); + + it('should log API usage and return a proxy object for @grafana/data packages', () => { + const obj = { + foo: 'bar', + }; + const packageName = '@grafana/data'; const result = trackPackageUsage(obj, packageName); mockUsage(result.foo); expect(logInfoMock).toHaveBeenCalledTimes(1); - expect(logInfoMock).toHaveBeenLastCalledWith(`Plugin using your-package.foo`, { + expect(logInfoMock).toHaveBeenLastCalledWith(`Plugin using @grafana/data.foo`, { key: 'foo', - parent: 'your-package', - packageName: 'your-package', + parent: '@grafana/data', + packageName: '@grafana/data', + }); + expect(result).toEqual(obj); + }); + + it('should log API usage and return a proxy object for app/* packages', () => { + const obj = { + foo: 'bar', + }; + const packageName = 'app/core/test'; + + const result = trackPackageUsage(obj, packageName); + + mockUsage(result.foo); + + expect(logInfoMock).toHaveBeenCalledTimes(1); + expect(logInfoMock).toHaveBeenLastCalledWith(`Plugin using app/core/test.foo`, { + key: 'foo', + parent: 'app/core/test', + packageName: 'app/core/test', }); expect(result).toEqual(obj); }); @@ -59,7 +91,7 @@ describe('trackPackageUsage', () => { bar: 'baz', }, }; - const packageName = 'your-package'; + const packageName = '@grafana/data'; const result = trackPackageUsage(obj, packageName); mockUsage(result.foo2.bar); @@ -67,15 +99,15 @@ describe('trackPackageUsage', () => { // 2 calls, one for each attribute expect(logInfoMock).toHaveBeenCalledTimes(2); - expect(logInfoMock).toHaveBeenCalledWith(`Plugin using your-package.foo2`, { + expect(logInfoMock).toHaveBeenCalledWith(`Plugin using @grafana/data.foo2`, { key: 'foo2', - parent: 'your-package', - packageName: 'your-package', + parent: '@grafana/data', + packageName: '@grafana/data', }); - expect(logInfoMock).toHaveBeenCalledWith(`Plugin using your-package.foo2.bar`, { + expect(logInfoMock).toHaveBeenCalledWith(`Plugin using @grafana/data.foo2.bar`, { key: 'bar', - parent: 'your-package.foo2', - packageName: 'your-package', + parent: '@grafana/data.foo2', + packageName: '@grafana/data', }); expect(result.foo2).toEqual(obj.foo2); @@ -86,7 +118,7 @@ describe('trackPackageUsage', () => { [Symbol('key')]: 'value', __useDefault: 'default', }; - const packageName = 'your-package'; + const packageName = '@grafana/data'; const result = trackPackageUsage(obj, packageName); @@ -100,7 +132,7 @@ describe('trackPackageUsage', () => { bar: 'baz', }, }; - const packageName = 'your-package'; + const packageName = '@grafana/data'; const result1 = trackPackageUsage(obj, packageName); const result2 = trackPackageUsage(obj, packageName); @@ -108,16 +140,16 @@ describe('trackPackageUsage', () => { mockUsage(result1.foo3); expect(logInfoMock).toHaveBeenCalledTimes(1); - expect(logInfoMock).toHaveBeenCalledWith(`Plugin using your-package.foo3`, { + expect(logInfoMock).toHaveBeenCalledWith(`Plugin using @grafana/data.foo3`, { key: 'foo3', - parent: 'your-package', - packageName: 'your-package', + parent: '@grafana/data', + packageName: '@grafana/data', }); mockUsage(result2.foo3.bar); - expect(logInfoMock).toHaveBeenCalledWith(`Plugin using your-package.foo3.bar`, { + expect(logInfoMock).toHaveBeenCalledWith(`Plugin using @grafana/data.foo3.bar`, { key: 'bar', - parent: 'your-package.foo3', - packageName: 'your-package', + parent: '@grafana/data.foo3', + packageName: '@grafana/data', }); expect(result1.foo3).toEqual(obj.foo3); @@ -133,7 +165,7 @@ describe('trackPackageUsage', () => { }, }; - const result = trackPackageUsage(obj, 'your-package'); + const result = trackPackageUsage(obj, '@grafana/data'); mockUsage(result.cacheMe); expect(logInfoMock).toHaveBeenCalledTimes(1); @@ -170,7 +202,7 @@ describe('trackPackageUsage', () => { lor: 'me', }; - const result = trackPackageUsage(obj, 'your-package'); + const result = trackPackageUsage(obj, '@grafana/data'); mockUsage(result.lor); expect(logInfoMock).not.toHaveBeenCalled(); diff --git a/public/app/features/plugins/loader/packageMetrics.ts b/public/app/features/plugins/loader/packageMetrics.ts index 690edd938b7..a8ef34e1416 100644 --- a/public/app/features/plugins/loader/packageMetrics.ts +++ b/public/app/features/plugins/loader/packageMetrics.ts @@ -32,7 +32,7 @@ function createMetricsProxy(obj: T, parentName: string, packag } } - const value = Reflect.get(target, key); + let value = Reflect.get(target, key); if (value !== null && typeof value === 'object' && !(value instanceof RegExp)) { if (!cachedMetricProxies.has(value)) { @@ -40,6 +40,11 @@ function createMetricsProxy(obj: T, parentName: string, packag } return cachedMetricProxies.get(value); } + + // proxies don't play nice with functions scopes + if (typeof value === 'function') { + value = value.bind(target); + } return value; }, }; @@ -51,6 +56,11 @@ function createMetricsProxy(obj: T, parentName: string, packag return obj; } +const trackPackagesRe = /^(@grafana|app\/)/; + export function trackPackageUsage(obj: T, packageName: string): T { - return createMetricsProxy(obj, packageName, packageName); + if (trackPackagesRe.test(packageName)) { + return createMetricsProxy(obj, packageName, packageName); + } + return obj; }