Prechádzať zdrojové kódy

feat(core): Apply Instrumentation to all services & key helper classes

Michael Bromley 8 mesiacov pred
rodič
commit
4b3f5265c2
53 zmenil súbory, kde vykonal 163 pridanie a 398 odobranie
  1. 0 1
      packages/core/package.json
  2. 2 11
      packages/core/src/api/middleware/asset-interceptor-plugin.ts
  3. 0 8
      packages/core/src/app.module.ts
  4. 2 33
      packages/core/src/cache/cache.service.ts
  5. 18 2
      packages/core/src/common/instrument-decorator.ts
  6. 1 8
      packages/core/src/config/config.service.ts
  7. 3 2
      packages/core/src/config/default-config.ts
  8. 0 1
      packages/core/src/config/index.ts
  9. 3 1
      packages/core/src/config/system/instrumentation-strategy.ts
  10. 7 0
      packages/core/src/config/system/noop-instrumentation-strategy.ts
  11. 2 7
      packages/core/src/event-bus/event-bus.ts
  12. 0 11
      packages/core/src/instrumentation.ts
  13. 4 11
      packages/core/src/job-queue/job-queue.service.ts
  14. 2 13
      packages/core/src/job-queue/job-queue.ts
  15. 2 25
      packages/core/src/plugin/default-cache-plugin/sql-cache-strategy.ts
  16. 2 0
      packages/core/src/service/helpers/list-query-builder/list-query-builder.ts
  17. 2 0
      packages/core/src/service/helpers/order-calculator/order-calculator.ts
  18. 4 2
      packages/core/src/service/helpers/order-modifier/order-modifier.ts
  19. 2 9
      packages/core/src/service/services/administrator.service.ts
  20. 2 26
      packages/core/src/service/services/asset.service.ts
  21. 2 6
      packages/core/src/service/services/auth.service.ts
  22. 5 21
      packages/core/src/service/services/channel.service.ts
  23. 2 26
      packages/core/src/service/services/collection.service.ts
  24. 2 8
      packages/core/src/service/services/country.service.ts
  25. 2 10
      packages/core/src/service/services/customer-group.service.ts
  26. 2 3
      packages/core/src/service/services/customer.service.ts
  27. 3 1
      packages/core/src/service/services/facet-value.service.ts
  28. 24 33
      packages/core/src/service/services/facet.service.ts
  29. 4 3
      packages/core/src/service/services/fulfillment.service.ts
  30. 2 0
      packages/core/src/service/services/global-settings.service.ts
  31. 2 1
      packages/core/src/service/services/history.service.ts
  32. 3 1
      packages/core/src/service/services/order-testing.service.ts
  33. 4 2
      packages/core/src/service/services/order.service.ts
  34. 2 0
      packages/core/src/service/services/payment-method.service.ts
  35. 5 4
      packages/core/src/service/services/payment.service.ts
  36. 3 1
      packages/core/src/service/services/product-option-group.service.ts
  37. 2 0
      packages/core/src/service/services/product-option.service.ts
  38. 2 29
      packages/core/src/service/services/product-variant.service.ts
  39. 0 70
      packages/core/src/service/services/product.service.ts
  40. 3 3
      packages/core/src/service/services/promotion.service.ts
  41. 2 0
      packages/core/src/service/services/province.service.ts
  42. 2 0
      packages/core/src/service/services/role.service.ts
  43. 2 1
      packages/core/src/service/services/seller.service.ts
  44. 2 0
      packages/core/src/service/services/session.service.ts
  45. 2 0
      packages/core/src/service/services/shipping-method.service.ts
  46. 2 0
      packages/core/src/service/services/stock-level.service.ts
  47. 2 0
      packages/core/src/service/services/stock-location.service.ts
  48. 3 3
      packages/core/src/service/services/stock-movement.service.ts
  49. 6 1
      packages/core/src/service/services/tag.service.ts
  50. 2 0
      packages/core/src/service/services/tax-category.service.ts
  51. 2 0
      packages/core/src/service/services/tax-rate.service.ts
  52. 2 0
      packages/core/src/service/services/user.service.ts
  53. 2 0
      packages/core/src/service/services/zone.service.ts

+ 0 - 1
packages/core/package.json

@@ -50,7 +50,6 @@
         "@nestjs/terminus": "~11.0.0",
         "@nestjs/typeorm": "~11.0.0",
         "@vendure/common": "3.2.2",
-        "@vendure/telemetry": "3.2.2",
         "bcrypt": "^5.1.1",
         "body-parser": "^1.20.2",
         "cookie-session": "^2.1.0",

+ 2 - 11
packages/core/src/api/middleware/asset-interceptor-plugin.ts

@@ -1,16 +1,16 @@
 import { ApolloServerPlugin, GraphQLRequestListener, GraphQLServerContext } from '@apollo/server';
-import { getActiveSpan } from '@vendure/telemetry';
 import { DocumentNode, GraphQLNamedType, isUnionType } from 'graphql';
 
+import { Instrument } from '../../common/instrument-decorator';
 import { AssetStorageStrategy } from '../../config/asset-storage-strategy/asset-storage-strategy';
 import { ConfigService } from '../../config/config.service';
-import { Span } from '../../instrumentation';
 import { GraphqlValueTransformer } from '../common/graphql-value-transformer';
 
 /**
  * Transforms outputs so that any Asset instances are run through the {@link AssetStorageStrategy.toAbsoluteUrl}
  * method before being returned in the response.
  */
+@Instrument()
 export class AssetInterceptorPlugin implements ApolloServerPlugin {
     private graphqlValueTransformer: GraphqlValueTransformer;
     private readonly toAbsoluteUrl: AssetStorageStrategy['toAbsoluteUrl'] | undefined;
@@ -43,14 +43,10 @@ export class AssetInterceptorPlugin implements ApolloServerPlugin {
         };
     }
 
-    @Span('vendure.asset-interceptor-plugin.prefix-asset-urls')
     private prefixAssetUrls(request: any, document: DocumentNode, data?: Record<string, unknown> | null) {
-        const span = getActiveSpan();
         const typeTree = this.graphqlValueTransformer.getOutputTypeTree(document);
         const toAbsoluteUrl = this.toAbsoluteUrl;
         if (!toAbsoluteUrl || !data) {
-            span?.addEvent('no-data');
-            span?.end();
             return;
         }
         this.graphqlValueTransformer.transformValues(typeTree, data, (value, type) => {
@@ -62,18 +58,13 @@ export class AssetInterceptorPlugin implements ApolloServerPlugin {
             if (isAssetType || isUnionWithAssetType) {
                 if (value && !Array.isArray(value)) {
                     if (value.preview) {
-                        span?.setAttribute('preview_relative_url', value.preview);
                         value.preview = toAbsoluteUrl(request, value.preview);
-                        span?.setAttribute('preview_absolute_url', value.preview);
                     }
                     if (value.source) {
-                        span?.setAttribute('source_relative_url', value.source);
                         value.source = toAbsoluteUrl(request, value.source);
-                        span?.setAttribute('source_absolute_url', value.source);
                     }
                 }
             }
-            span?.end();
             return value;
         });
     }

+ 0 - 8
packages/core/src/app.module.ts

@@ -1,5 +1,4 @@
 import { MiddlewareConsumer, Module, NestModule, OnApplicationShutdown } from '@nestjs/common';
-import { getActiveSpan } from '@vendure/telemetry';
 import cookieSession from 'cookie-session';
 
 import { ApiModule } from './api/api.module';
@@ -11,7 +10,6 @@ import { ConnectionModule } from './connection/connection.module';
 import { HealthCheckModule } from './health-check/health-check.module';
 import { I18nModule } from './i18n/i18n.module';
 import { I18nService } from './i18n/i18n.service';
-import { Span } from './instrumentation';
 import { PluginModule } from './plugin/plugin.module';
 import { ProcessContextModule } from './process-context/process-context.module';
 import { ServiceModule } from './service/service.module';
@@ -34,9 +32,7 @@ export class AppModule implements NestModule, OnApplicationShutdown {
         private i18nService: I18nService,
     ) {}
 
-    @Span('vendure.app-module.configure')
     configure(consumer: MiddlewareConsumer) {
-        const currentSpan = getActiveSpan();
         const { adminApiPath, shopApiPath, middleware } = this.configService.apiOptions;
         const { cookieOptions } = this.configService.authOptions;
 
@@ -46,9 +42,6 @@ export class AppModule implements NestModule, OnApplicationShutdown {
             { handler: i18nextHandler, route: shopApiPath },
         ];
 
-        currentSpan?.setAttribute('middleware.adminApiPath', adminApiPath);
-        currentSpan?.setAttribute('middleware.shopApiPath', shopApiPath);
-
         const allMiddleware = defaultMiddleware.concat(middleware);
 
         // If the Admin API and Shop API should have specific cookies names, we need to create separate cookie sessions
@@ -71,7 +64,6 @@ export class AppModule implements NestModule, OnApplicationShutdown {
         for (const [route, handlers] of Object.entries(middlewareByRoute)) {
             consumer.apply(...handlers).forRoutes(route);
         }
-        currentSpan?.end();
     }
 
     async onApplicationShutdown(signal?: string) {

+ 2 - 33
packages/core/src/cache/cache.service.ts

@@ -1,11 +1,10 @@
 import { Injectable } from '@nestjs/common';
 import { JsonCompatible } from '@vendure/common/lib/shared-types';
-import { getActiveSpan } from '@vendure/telemetry';
 
+import { Instrument } from '../common';
 import { ConfigService } from '../config/config.service';
 import { Logger } from '../config/index';
 import { CacheStrategy, SetCacheKeyOptions } from '../config/system/cache-strategy';
-import { Span } from '../instrumentation';
 
 import { Cache, CacheConfig } from './cache';
 
@@ -20,6 +19,7 @@ import { Cache, CacheConfig } from './cache';
  * @docsCategory cache
  */
 @Injectable()
+@Instrument()
 export class CacheService {
     protected cacheStrategy: CacheStrategy;
 
@@ -34,10 +34,7 @@ export class CacheService {
      * The `Cache` instance provides a convenience wrapper around the `CacheService`
      * methods.
      */
-    @Span('CacheService.createCache')
     createCache(config: CacheConfig): Cache {
-        const span = getActiveSpan();
-        span?.setAttribute('cache.config', JSON.stringify(config));
         return new Cache(config, this);
     }
 
@@ -46,21 +43,14 @@ export class CacheService {
      * Gets an item from the cache, or returns undefined if the key is not found, or the
      * item has expired.
      */
-    @Span('CacheService.get')
     async get<T extends JsonCompatible<T>>(key: string): Promise<T | undefined> {
-        const span = getActiveSpan();
-
         try {
             const result = await this.cacheStrategy.get(key);
             if (result) {
-                span?.setAttribute('cache.hit', true);
-                span?.addEvent('cache.hit', { key });
                 Logger.debug(`CacheService hit for key [${key}]`);
             }
             return result as T;
         } catch (e: any) {
-            span?.setAttribute('cache.hit', false);
-            span?.addEvent('cache.miss', { key });
             Logger.error(`Could not get key [${key}] from CacheService`, undefined, e.stack);
         }
     }
@@ -73,22 +63,15 @@ export class CacheService {
      * Optionally a "time to live" (ttl) can be specified, which means that the key will
      * be considered stale after that many milliseconds.
      */
-    @Span('CacheService.set')
     async set<T extends JsonCompatible<T>>(
         key: string,
         value: T,
         options?: SetCacheKeyOptions,
     ): Promise<void> {
-        const span = getActiveSpan();
-        span?.setAttribute('cache.key', key);
         try {
             await this.cacheStrategy.set(key, value, options);
-            span?.setAttribute('cache.set', true);
-            span?.end();
             Logger.debug(`Set key [${key}] in CacheService`);
         } catch (e: any) {
-            span?.setAttribute('cache.set', false);
-            span?.end();
             Logger.error(`Could not set key [${key}] in CacheService`, undefined, e.stack);
         }
     }
@@ -97,18 +80,11 @@ export class CacheService {
      * @description
      * Deletes an item from the cache.
      */
-    @Span('CacheService.delete')
     async delete(key: string): Promise<void> {
-        const span = getActiveSpan();
-        span?.setAttribute('cache.key', key);
         try {
             await this.cacheStrategy.delete(key);
-            span?.setAttribute('cache.deleted', true);
-            span?.end();
             Logger.debug(`Deleted key [${key}] from CacheService`);
         } catch (e: any) {
-            span?.setAttribute('cache.deleted', false);
-            span?.end();
             Logger.error(`Could not delete key [${key}] from CacheService`, undefined, e.stack);
         }
     }
@@ -117,18 +93,11 @@ export class CacheService {
      * @description
      * Deletes all items from the cache which contain at least one matching tag.
      */
-    @Span('CacheService.invalidateTags')
     async invalidateTags(tags: string[]): Promise<void> {
-        const span = getActiveSpan();
-        span?.setAttribute('cache.tags', tags.join(', '));
         try {
             await this.cacheStrategy.invalidateTags(tags);
-            span?.setAttribute('cache.invalidated', true);
-            span?.end();
             Logger.debug(`Invalidated tags [${tags.join(', ')}] from CacheService`);
         } catch (e: any) {
-            span?.setAttribute('cache.invalidated', false);
-            span?.end();
             Logger.error(
                 `Could not invalidate tags [${tags.join(', ')}] from CacheService`,
                 undefined,

+ 18 - 2
packages/core/src/common/instrument-decorator.ts

@@ -1,9 +1,18 @@
-import { getConfig } from '../config';
+import { getConfig } from '../config/config-helpers';
+
+export const ENABLE_INSTRUMENTATION_ENV_VAR = 'VENDURE_ENABLE_INSTRUMENTATION';
 
 const INSTRUMENTED_CLASS = Symbol('InstrumentedClassTarget');
 
 export function Instrument(): ClassDecorator {
     return function (target: any) {
+        // Since the instrumentation is not "free" (it will wrap all instrumented classes in a
+        // Proxy, which has some overhead), we will only do this if explicitly requested by the
+        // presence of this env var. The `@vendure/telemetry` package sets this in its configuration,
+        // which will be run before any of the Vendure code is loaded.
+        if (process.env[ENABLE_INSTRUMENTATION_ENV_VAR] == null) {
+            return target;
+        }
         const InstrumentedClass = class extends (target as new (...args: any[]) => any) {
             constructor(...args: any[]) {
                 // eslint-disable-next-line constructor-super
@@ -13,16 +22,23 @@ export function Instrument(): ClassDecorator {
                 if (!instrumentationStrategy) {
                     return this;
                 }
+                // eslint-disable-next-line @typescript-eslint/no-this-alias
+                const instance = this;
                 return new Proxy(this, {
                     get: (obj, prop) => {
                         const original = obj[prop as string];
                         if (typeof original === 'function') {
                             return function (...methodArgs: any[]) {
+                                const applyOriginalFunction =
+                                    original.constructor.name === 'AsyncFunction'
+                                        ? async () => await original.apply(obj, methodArgs)
+                                        : () => original.apply(obj, methodArgs);
                                 const wrappedMethodArgs = {
+                                    instance,
                                     target,
                                     methodName: String(prop),
                                     args: methodArgs,
-                                    applyOriginalFunction: () => original.apply(obj, methodArgs),
+                                    applyOriginalFunction,
                                 };
                                 return instrumentationStrategy.wrapMethod(wrappedMethodArgs);
                             };

+ 1 - 8
packages/core/src/config/config.service.ts

@@ -1,10 +1,7 @@
 import { DynamicModule, Injectable, Type } from '@nestjs/common';
 import { LanguageCode } from '@vendure/common/lib/generated-types';
-import { getActiveSpan } from '@vendure/telemetry';
 import { DataSourceOptions, getMetadataArgsStorage } from 'typeorm';
 
-import { Span } from '../instrumentation';
-
 import { getConfig } from './config-helpers';
 import { CustomFields } from './custom-field/custom-field-types';
 import { EntityIdStrategy } from './entity/entity-id-strategy';
@@ -123,12 +120,10 @@ export class ConfigService implements VendureConfig {
         return this.activeConfig.systemOptions;
     }
 
-    @Span('vendure.config.get-custom-fields-for-all-entities')
     private getCustomFieldsForAllEntities(): Required<CustomFields> {
         const definedCustomFields = this.activeConfig.customFields;
         const metadataArgsStorage = getMetadataArgsStorage();
-        const span = getActiveSpan();
-        span?.setAttribute('customFields', JSON.stringify(definedCustomFields));
+
         // We need to check for any entities which have a "customFields" property but which are not
         // explicitly defined in the customFields config. This is because the customFields object
         // only includes the built-in entities. Any custom entities which have a "customFields"
@@ -146,12 +141,10 @@ export class ConfigService implements VendureConfig {
                             .find(c => c.propertyName === 'languageCode');
                     if (hasCustomFields && !isTranslationEntity) {
                         definedCustomFields[entity.name] = [];
-                        span?.addEvent('removed-custom-fields', { entity: entity.name });
                     }
                 }
             }
         }
-        span?.end();
         return definedCustomFields;
     }
 

+ 3 - 2
packages/core/src/config/default-config.ts

@@ -1,9 +1,9 @@
 import { LanguageCode } from '@vendure/common/lib/generated-types';
 import {
     DEFAULT_AUTH_TOKEN_HEADER_KEY,
+    DEFAULT_CHANNEL_TOKEN_KEY,
     SUPER_ADMIN_USER_IDENTIFIER,
     SUPER_ADMIN_USER_PASSWORD,
-    DEFAULT_CHANNEL_TOKEN_KEY,
 } from '@vendure/common/lib/shared-constants';
 import { randomBytes } from 'crypto';
 
@@ -24,7 +24,6 @@ import { DefaultProductVariantPriceCalculationStrategy } from './catalog/default
 import { DefaultProductVariantPriceSelectionStrategy } from './catalog/default-product-variant-price-selection-strategy';
 import { DefaultProductVariantPriceUpdateStrategy } from './catalog/default-product-variant-price-update-strategy';
 import { DefaultStockDisplayStrategy } from './catalog/default-stock-display-strategy';
-import { DefaultStockLocationStrategy } from './catalog/default-stock-location-strategy';
 import { MultiChannelStockLocationStrategy } from './catalog/multi-channel-stock-location-strategy';
 import { AutoIncrementIdStrategy } from './entity/auto-increment-id-strategy';
 import { DefaultMoneyStrategy } from './entity/default-money-strategy';
@@ -52,6 +51,7 @@ import { defaultShippingCalculator } from './shipping-method/default-shipping-ca
 import { defaultShippingEligibilityChecker } from './shipping-method/default-shipping-eligibility-checker';
 import { DefaultShippingLineAssignmentStrategy } from './shipping-method/default-shipping-line-assignment-strategy';
 import { InMemoryCacheStrategy } from './system/in-memory-cache-strategy';
+import { NoopInstrumentationStrategy } from './system/noop-instrumentation-strategy';
 import { DefaultTaxLineCalculationStrategy } from './tax/default-tax-line-calculation-strategy';
 import { DefaultTaxZoneStrategy } from './tax/default-tax-zone-strategy';
 import { RuntimeVendureConfig } from './vendure-config';
@@ -236,5 +236,6 @@ export const defaultConfig: RuntimeVendureConfig = {
         cacheStrategy: new InMemoryCacheStrategy({ cacheSize: 10_000 }),
         healthChecks: [new TypeORMHealthCheckStrategy()],
         errorHandlers: [],
+        instrumentationStrategy: new NoopInstrumentationStrategy(),
     },
 };

+ 0 - 1
packages/core/src/config/index.ts

@@ -45,7 +45,6 @@ export * from './job-queue/inspectable-job-queue-strategy';
 export * from './job-queue/job-queue-strategy';
 export * from './logger/default-logger';
 export * from './logger/noop-logger';
-export * from './logger/otel-logger';
 export * from './logger/vendure-logger';
 export * from './merge-config';
 export * from './order/active-order-strategy';

+ 3 - 1
packages/core/src/config/system/instrumentation-strategy.ts

@@ -1,7 +1,9 @@
-import { Type } from '../../common/types/common-types';
+import { Type } from '@vendure/common/lib/shared-types';
+
 import { InjectableStrategy } from '../../common/types/injectable-strategy';
 
 export interface WrappedMethodArgs {
+    instance: any;
     target: Type<any>;
     methodName: string;
     args: any[];

+ 7 - 0
packages/core/src/config/system/noop-instrumentation-strategy.ts

@@ -0,0 +1,7 @@
+import { InstrumentationStrategy } from './instrumentation-strategy';
+
+export class NoopInstrumentationStrategy implements InstrumentationStrategy {
+    async wrapMethod() {
+        // no-op
+    }
+}

+ 2 - 7
packages/core/src/event-bus/event-bus.ts

@@ -1,16 +1,15 @@
 import { Injectable, OnModuleDestroy } from '@nestjs/common';
 import { Type } from '@vendure/common/lib/shared-types';
 import { notNullOrUndefined } from '@vendure/common/lib/shared-utils';
-import { getActiveSpan } from '@vendure/telemetry';
 import { Observable, Subject } from 'rxjs';
 import { filter, mergeMap, takeUntil } from 'rxjs/operators';
 import { EntityManager } from 'typeorm';
 
 import { RequestContext } from '../api/common/request-context';
 import { TRANSACTION_MANAGER_KEY } from '../common/constants';
+import { Instrument } from '../common/instrument-decorator';
 import { Logger } from '../config/logger/vendure-logger';
 import { TransactionSubscriber, TransactionSubscriberError } from '../connection/transaction-subscriber';
-import { Span } from '../instrumentation';
 
 import { VendureEvent } from './vendure-event';
 
@@ -97,6 +96,7 @@ export type BlockingEventHandlerOptions<T extends VendureEvent> = {
  * @docsCategory events
  * */
 @Injectable()
+@Instrument()
 export class EventBus implements OnModuleDestroy {
     private eventStream = new Subject<VendureEvent>();
     private destroy$ = new Subject<void>();
@@ -113,14 +113,9 @@ export class EventBus implements OnModuleDestroy {
      * await eventBus.publish(new SomeEvent());
      * ```
      */
-    @Span('vendure.event-bus publish')
     async publish<T extends VendureEvent>(event: T): Promise<void> {
-        const span = getActiveSpan();
-        span?.setAttribute('event', event.constructor.name);
-        span?.setAttribute('event-timestamp', event.createdAt.toISOString());
         this.eventStream.next(event);
         await this.executeBlockingEventHandlers(event);
-        span?.end();
     }
 
     /**

+ 0 - 11
packages/core/src/instrumentation.ts

@@ -1,11 +0,0 @@
-import { trace } from '@opentelemetry/api';
-import { logs } from '@opentelemetry/api-logs';
-import { createSpanDecorator } from '@vendure/telemetry';
-
-import { VENDURE_VERSION } from './version';
-
-export const tracer = trace.getTracer('@vendure/core', VENDURE_VERSION);
-
-export const otelLogger = logs.getLogger('@vendure/core', VENDURE_VERSION);
-
-export const Span = createSpanDecorator(tracer);

+ 4 - 11
packages/core/src/job-queue/job-queue.service.ts

@@ -1,9 +1,8 @@
 import { Injectable, OnModuleDestroy } from '@nestjs/common';
 import { JobQueue as GraphQlJobQueue } from '@vendure/common/lib/generated-types';
-import { getActiveSpan } from '@vendure/telemetry';
 
+import { Instrument } from '../common';
 import { ConfigService, JobQueueStrategy, Logger } from '../config';
-import { Span } from '../instrumentation';
 
 import { loggerCtx } from './constants';
 import { Job } from './job';
@@ -48,6 +47,7 @@ import { CreateQueueOptions, JobData } from './types';
  * @docsCategory JobQueue
  */
 @Injectable()
+@Instrument()
 export class JobQueueService implements OnModuleDestroy {
     private queues: Array<JobQueue<any>> = [];
     private hasStarted = false;
@@ -71,7 +71,6 @@ export class JobQueueService implements OnModuleDestroy {
      * @description
      * Configures and creates a new {@link JobQueue} instance.
      */
-    @Span('vendure.job-queue.create-queue')
     async createQueue<Data extends JobData<Data>>(
         options: CreateQueueOptions<Data>,
     ): Promise<JobQueue<Data>> {
@@ -81,29 +80,23 @@ export class JobQueueService implements OnModuleDestroy {
         const wrappedProcessFn = this.createWrappedProcessFn(options.process);
         options = { ...options, process: wrappedProcessFn };
 
-        const span = getActiveSpan();
-        span?.setAttribute('job-queue.name', options.name);
-
         const queue = new JobQueue(options, this.jobQueueStrategy, this.jobBufferService);
         if (this.hasStarted && this.shouldStartQueue(queue.name)) {
             await queue.start();
         }
         this.queues.push(queue);
 
-        span?.end();
-
         return queue;
     }
 
-    @Span('vendure.job-queue.start')
     async start(): Promise<void> {
         this.hasStarted = true;
         for (const queue of this.queues) {
             if (!queue.started && this.shouldStartQueue(queue.name)) {
                 Logger.info(`Starting queue: ${queue.name}`, loggerCtx);
                 await queue.start();
-                const span = getActiveSpan();
-                span?.setAttribute('job-queue.name', queue.name);
+                // const span = getActiveSpan();
+                // span?.setAttribute('job-queue.name', queue.name);
             }
         }
     }

+ 2 - 13
packages/core/src/job-queue/job-queue.ts

@@ -1,7 +1,5 @@
-import { getActiveSpan } from '@vendure/telemetry';
-
+import { Instrument } from '../common';
 import { JobQueueStrategy } from '../config';
-import { Span } from '../instrumentation';
 
 import { Job } from './job';
 import { JobBufferService } from './job-buffer/job-buffer.service';
@@ -20,6 +18,7 @@ import { CreateQueueOptions, JobData, JobOptions } from './types';
  *
  * @docsCategory JobQueue
  */
+@Instrument()
 export class JobQueue<Data extends JobData<Data> = object> {
     private running = false;
 
@@ -88,24 +87,16 @@ export class JobQueue<Data extends JobData<Data> = object> {
      *   .catch(err => err.message);
      * ```
      */
-    @Span('vendure.job-queue.add')
     async add(data: Data, options?: JobOptions<Data>): Promise<SubscribableJob<Data>> {
         const job = new Job<any>({
             data,
             queueName: this.options.name,
             retries: options?.retries ?? 0,
         });
-        const span = getActiveSpan();
-        span?.setAttribute('job.data', JSON.stringify(data));
-        span?.setAttribute('job.retries', options?.retries ?? 0);
-        span?.setAttribute('job.queueName', this.options.name);
-        span?.setAttribute('job.id', job.id ?? 'unknown');
 
         const isBuffered = await this.jobBufferService.add(job);
         if (!isBuffered) {
             const addedJob = await this.jobQueueStrategy.add(job, options);
-            span?.setAttribute('job.buffered', false);
-            span?.end();
             return new SubscribableJob(addedJob, this.jobQueueStrategy);
         } else {
             const bufferedJob = new Job({
@@ -113,8 +104,6 @@ export class JobQueue<Data extends JobData<Data> = object> {
                 data: job.data,
                 id: 'buffered',
             });
-            span?.setAttribute('job.buffered', true);
-            span?.end();
             return new SubscribableJob(bufferedJob, this.jobQueueStrategy);
         }
     }

+ 2 - 25
packages/core/src/plugin/default-cache-plugin/sql-cache-strategy.ts

@@ -1,12 +1,11 @@
 import { JsonCompatible } from '@vendure/common/lib/shared-types';
-import { getActiveSpan } from '@vendure/telemetry';
 
 import { CacheTtlProvider, DefaultCacheTtlProvider } from '../../cache/cache-ttl-provider';
 import { Injector } from '../../common/injector';
+import { Instrument } from '../../common/instrument-decorator';
 import { ConfigService, Logger } from '../../config/index';
 import { CacheStrategy, SetCacheKeyOptions } from '../../config/system/cache-strategy';
 import { TransactionalConnection } from '../../connection/index';
-import { Span } from '../../instrumentation';
 
 import { CacheItem } from './cache-item.entity';
 import { CacheTag } from './cache-tag.entity';
@@ -19,6 +18,7 @@ import { CacheTag } from './cache-tag.entity';
  * @since 3.1.0
  * @docsCategory cache
  */
+@Instrument()
 export class SqlCacheStrategy implements CacheStrategy {
     protected cacheSize = 10_000;
     protected ttlProvider: CacheTtlProvider;
@@ -38,11 +38,7 @@ export class SqlCacheStrategy implements CacheStrategy {
         this.configService = injector.get(ConfigService);
     }
 
-    @Span('vendure.sql-cache-strategy.get')
     async get<T extends JsonCompatible<T>>(key: string): Promise<T | undefined> {
-        const span = getActiveSpan();
-        span?.setAttribute('cache.key', key);
-
         const hit = await this.connection.rawConnection.getRepository(CacheItem).findOne({
             where: {
                 key,
@@ -52,30 +48,19 @@ export class SqlCacheStrategy implements CacheStrategy {
         if (hit) {
             if (!hit.expiresAt || (hit.expiresAt && this.ttlProvider.getTime() < hit.expiresAt.getTime())) {
                 try {
-                    span?.setAttribute('cache.hit', true);
-                    span?.setAttribute('cache.hit.expiresAt', hit.expiresAt?.toISOString() ?? 'never');
-                    span?.end();
                     return JSON.parse(hit.value);
                 } catch (e: any) {
                     /* */
                 }
             } else {
-                span?.setAttribute('cache.hit', false);
-                span?.addEvent('cache.delete', {
-                    key,
-                });
                 await this.connection.rawConnection.getRepository(CacheItem).delete({
                     key,
                 });
             }
         }
-        span?.end();
     }
 
-    @Span('vendure.sql-cache-strategy.set')
     async set<T extends JsonCompatible<T>>(key: string, value: T, options?: SetCacheKeyOptions) {
-        const span = getActiveSpan();
-        span?.setAttribute('cache.key', key);
         const cacheSize = await this.connection.rawConnection.getRepository(CacheItem).count();
         if (cacheSize >= this.cacheSize) {
             // evict oldest
@@ -130,21 +115,13 @@ export class SqlCacheStrategy implements CacheStrategy {
         }
     }
 
-    @Span('vendure.sql-cache-strategy.delete')
     async delete(key: string) {
-        const span = getActiveSpan();
-        span?.setAttribute('cache.key', key);
-
         await this.connection.rawConnection.getRepository(CacheItem).delete({
             key,
         });
     }
 
-    @Span('vendure.sql-cache-strategy.invalidate-tags')
     async invalidateTags(tags: string[]) {
-        const span = getActiveSpan();
-        span?.setAttribute('cache.tags', tags.join(', '));
-
         await this.connection.withTransaction(async ctx => {
             const itemIds = await this.connection
                 .getRepository(ctx, CacheTag)

+ 2 - 0
packages/core/src/service/helpers/list-query-builder/list-query-builder.ts

@@ -21,6 +21,7 @@ import {
     SortParameter,
     UserInputError,
 } from '../../../common';
+import { Instrument } from '../../../common/instrument-decorator';
 import { ConfigService, CustomFields, Logger } from '../../../config';
 import { TransactionalConnection } from '../../../connection';
 import { VendureEntity } from '../../../entity';
@@ -198,6 +199,7 @@ export type ExtendedListQueryOptions<T extends VendureEntity> = {
  * @docsWeight 0
  */
 @Injectable()
+@Instrument()
 export class ListQueryBuilder implements OnApplicationBootstrap {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 0
packages/core/src/service/helpers/order-calculator/order-calculator.ts

@@ -7,6 +7,7 @@ import { RequestContext } from '../../../api/common/request-context';
 import { RequestContextCacheService } from '../../../cache/request-context-cache.service';
 import { CacheKey } from '../../../common/constants';
 import { InternalServerError } from '../../../common/error/errors';
+import { Instrument } from '../../../common/instrument-decorator';
 import { idsAreEqual } from '../../../common/utils';
 import { ConfigService } from '../../../config/config.service';
 import { OrderLine, TaxRate } from '../../../entity';
@@ -32,6 +33,7 @@ import { prorate } from './prorate';
  * @docsCategory service-helpers
  */
 @Injectable()
+@Instrument()
 export class OrderCalculator {
     constructor(
         private configService: ConfigService,

+ 4 - 2
packages/core/src/service/helpers/order-modifier/order-modifier.ts

@@ -33,16 +33,17 @@ import {
     NegativeQuantityError,
     OrderLimitError,
 } from '../../../common/error/generated-graphql-shop-errors';
+import { Instrument } from '../../../common/instrument-decorator';
 import { idsAreEqual } from '../../../common/utils';
 import { ConfigService } from '../../../config/config.service';
 import { CustomFieldConfig } from '../../../config/custom-field/custom-field-types';
 import { TransactionalConnection } from '../../../connection/transactional-connection';
 import { VendureEntity } from '../../../entity/base/base.entity';
-import { Order } from '../../../entity/order/order.entity';
-import { OrderLine } from '../../../entity/order-line/order-line.entity';
 import { FulfillmentLine } from '../../../entity/order-line-reference/fulfillment-line.entity';
 import { OrderModificationLine } from '../../../entity/order-line-reference/order-modification-line.entity';
+import { OrderLine } from '../../../entity/order-line/order-line.entity';
 import { OrderModification } from '../../../entity/order-modification/order-modification.entity';
+import { Order } from '../../../entity/order/order.entity';
 import { Payment } from '../../../entity/payment/payment.entity';
 import { ProductVariant } from '../../../entity/product-variant/product-variant.entity';
 import { ShippingLine } from '../../../entity/shipping-line/shipping-line.entity';
@@ -80,6 +81,7 @@ import { patchEntity } from '../utils/patch-entity';
  * @docsCategory service-helpers
  */
 @Injectable()
+@Instrument()
 export class OrderModifier {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 9
packages/core/src/service/services/administrator.service.ts

@@ -9,6 +9,7 @@ import { In, IsNull } from 'typeorm';
 
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
+import { Instrument } from '../../common';
 import { EntityNotFoundError, InternalServerError, UserInputError } from '../../common/error/errors';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound, idsAreEqual, normalizeEmailAddress } from '../../common/utils';
@@ -21,7 +22,6 @@ import { User } from '../../entity/user/user.entity';
 import { EventBus } from '../../event-bus';
 import { AdministratorEvent } from '../../event-bus/events/administrator-event';
 import { RoleChangeEvent } from '../../event-bus/events/role-change-event';
-import { Span } from '../../instrumentation';
 import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
 import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { PasswordCipher } from '../helpers/password-cipher/password-cipher';
@@ -39,6 +39,7 @@ import { UserService } from './user.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class AdministratorService {
     constructor(
         private connection: TransactionalConnection,
@@ -61,7 +62,6 @@ export class AdministratorService {
      * @description
      * Get a paginated list of Administrators.
      */
-    @Span('AdministratorService.findAll')
     findAll(
         ctx: RequestContext,
         options?: ListQueryOptions<Administrator>,
@@ -84,7 +84,6 @@ export class AdministratorService {
      * @description
      * Get an Administrator by id.
      */
-    @Span('AdministratorService.findOne')
     findOne(
         ctx: RequestContext,
         administratorId: ID,
@@ -106,7 +105,6 @@ export class AdministratorService {
      * @description
      * Get an Administrator based on the User id.
      */
-    @Span('AdministratorService.findOneByUserId')
     findOneByUserId(
         ctx: RequestContext,
         userId: ID,
@@ -128,7 +126,6 @@ export class AdministratorService {
      * @description
      * Create a new Administrator.
      */
-    @Span('AdministratorService.create')
     async create(ctx: RequestContext, input: CreateAdministratorInput): Promise<Administrator> {
         await this.checkActiveUserCanGrantRoles(ctx, input.roleIds);
         const administrator = new Administrator(input);
@@ -154,7 +151,6 @@ export class AdministratorService {
      * @description
      * Update an existing Administrator.
      */
-    @Span('AdministratorService.update')
     async update(ctx: RequestContext, input: UpdateAdministratorInput): Promise<Administrator> {
         const administrator = await this.findOne(ctx, input.id);
         if (!administrator) {
@@ -257,7 +253,6 @@ export class AdministratorService {
      * @description
      * Soft deletes an Administrator (sets the `deletedAt` field).
      */
-    @Span('AdministratorService.softDelete')
     async softDelete(ctx: RequestContext, id: ID) {
         const administrator = await this.connection.getEntityOrThrow(ctx, Administrator, id, {
             relations: ['user'],
@@ -280,7 +275,6 @@ export class AdministratorService {
      * Resolves to `true` if the administrator ID belongs to the only Administrator
      * with SuperAdmin permissions.
      */
-    @Span('AdministratorService.isSoleSuperadmin')
     private async isSoleSuperadmin(ctx: RequestContext, id: ID) {
         const superAdminRole = await this.roleService.getSuperAdminRole(ctx);
         const allAdmins = await this.connection.getRepository(ctx, Administrator).find({
@@ -303,7 +297,6 @@ export class AdministratorService {
      *
      * @internal
      */
-    @Span('AdministratorService.ensureSuperAdminExists')
     private async ensureSuperAdminExists() {
         const { superadminCredentials } = this.configService.authOptions;
 

+ 2 - 26
packages/core/src/service/services/asset.service.ts

@@ -27,6 +27,7 @@ import { camelCase } from 'typeorm/util/StringUtils';
 
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
+import { Instrument } from '../../common';
 import { isGraphQlErrorResult } from '../../common/error/error-result';
 import { ForbiddenError, InternalServerError } from '../../common/error/errors';
 import { MimeTypeError } from '../../common/error/generated-graphql-admin-errors';
@@ -44,7 +45,6 @@ import { Product } from '../../entity/product/product.entity';
 import { EventBus } from '../../event-bus/event-bus';
 import { AssetChannelEvent } from '../../event-bus/events/asset-channel-event';
 import { AssetEvent } from '../../event-bus/events/asset-event';
-import { Span } from '../../instrumentation';
 import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
 import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { patchEntity } from '../helpers/utils/patch-entity';
@@ -89,6 +89,7 @@ export interface EntityAssetInput {
  * @docsWeight 0
  */
 @Injectable()
+@Instrument()
 export class AssetService {
     private permittedMimeTypes: Array<{ type: string; subtype: string }> = [];
 
@@ -111,7 +112,6 @@ export class AssetService {
             });
     }
 
-    @Span('AssetService.findOne')
     findOne(ctx: RequestContext, id: ID, relations?: RelationPaths<Asset>): Promise<Asset | undefined> {
         return this.connection
             .findOneInChannel(ctx, Asset, id, ctx.channelId, {
@@ -120,7 +120,6 @@ export class AssetService {
             .then(result => result ?? undefined);
     }
 
-    @Span('AssetService.findAll')
     findAll(
         ctx: RequestContext,
         options?: AssetListOptions,
@@ -156,7 +155,6 @@ export class AssetService {
         }));
     }
 
-    @Span('AssetService.getFeaturedAsset')
     async getFeaturedAsset<T extends Omit<EntityWithAssets, 'assets'>>(
         ctx: RequestContext,
         entity: T,
@@ -196,7 +194,6 @@ export class AssetService {
      * Returns the Assets of an entity which has a well-ordered list of Assets, such as Product,
      * ProductVariant or Collection.
      */
-    @Span('AssetService.getEntityAssets')
     async getEntityAssets<T extends EntityWithAssets>(
         ctx: RequestContext,
         entity: T,
@@ -240,7 +237,6 @@ export class AssetService {
         return orderableAssets.sort((a, b) => a.position - b.position).map(a => a.asset);
     }
 
-    @Span('AssetService.updateFeaturedAsset')
     async updateFeaturedAsset<T extends EntityWithAssets>(
         ctx: RequestContext,
         entity: T,
@@ -295,7 +291,6 @@ export class AssetService {
      *
      * See the [Uploading Files docs](/guides/developer-guide/uploading-files) for an example of usage.
      */
-    @Span('AssetService.create')
     async create(ctx: RequestContext, input: CreateAssetInput): Promise<CreateAssetResult> {
         return new Promise(async (resolve, reject) => {
             const { createReadStream, filename, mimetype } = await input.file;
@@ -329,7 +324,6 @@ export class AssetService {
      * @description
      * Updates the name, focalPoint, tags & custom fields of an Asset.
      */
-    @Span('AssetService.update')
     async update(ctx: RequestContext, input: UpdateAssetInput): Promise<Asset> {
         const asset = await this.connection.getEntityOrThrow(ctx, Asset, input.id);
         if (input.focalPoint) {
@@ -352,7 +346,6 @@ export class AssetService {
      * Deletes an Asset after performing checks to ensure that the Asset is not currently in use
      * by a Product, ProductVariant or Collection.
      */
-    @Span('AssetService.delete')
     async delete(
         ctx: RequestContext,
         ids: ID[],
@@ -418,7 +411,6 @@ export class AssetService {
         return this.deleteUnconditional(ctx, assets);
     }
 
-    @Span('AssetService.assignToChannel')
     async assignToChannel(ctx: RequestContext, input: AssignAssetsToChannelInput): Promise<Asset[]> {
         const hasPermission = await this.roleService.userHasPermissionOnChannel(
             ctx,
@@ -462,7 +454,6 @@ export class AssetService {
         filePath: string,
         ctx?: RequestContext,
     ): Promise<CreateAssetResult>;
-    @Span('AssetService.createFromFileStream')
     async createFromFileStream(
         stream: ReadStream | Readable,
         maybeFilePathOrCtx?: string | RequestContext,
@@ -488,7 +479,6 @@ export class AssetService {
         }
     }
 
-    @Span('AssetService.getMimeType')
     private getMimeType(stream: Readable, filename: string): string {
         if (stream instanceof IncomingMessage) {
             const contentType = stream.headers['content-type'];
@@ -504,7 +494,6 @@ export class AssetService {
      * Unconditionally delete given assets.
      * Does not remove assets from channels
      */
-    @Span('AssetService.deleteUnconditional')
     private async deleteUnconditional(ctx: RequestContext, assets: Asset[]): Promise<DeletionResponse> {
         for (const asset of assets) {
             // Create a new asset so that the id is still available
@@ -527,7 +516,6 @@ export class AssetService {
     /**
      * Check if current user has permissions to delete assets from all channels
      */
-    @Span('AssetService.hasDeletePermissionForChannels')
     private async hasDeletePermissionForChannels(ctx: RequestContext, channelIds: ID[]): Promise<boolean> {
         const permissions = await Promise.all(
             channelIds.map(async channelId => {
@@ -537,7 +525,6 @@ export class AssetService {
         return !permissions.includes(false);
     }
 
-    @Span('AssetService.createAssetInternal')
     private async createAssetInternal(
         ctx: RequestContext,
         stream: Stream,
@@ -586,7 +573,6 @@ export class AssetService {
         return this.connection.getRepository(ctx, Asset).save(asset);
     }
 
-    @Span('AssetService.getSourceFileName')
     private async getSourceFileName(ctx: RequestContext, fileName: string): Promise<string> {
         const { assetOptions } = this.configService;
         return this.generateUniqueName(fileName, (name, conflict) =>
@@ -594,7 +580,6 @@ export class AssetService {
         );
     }
 
-    @Span('AssetService.getPreviewFileName')
     private async getPreviewFileName(ctx: RequestContext, fileName: string): Promise<string> {
         const { assetOptions } = this.configService;
         return this.generateUniqueName(fileName, (name, conflict) =>
@@ -602,7 +587,6 @@ export class AssetService {
         );
     }
 
-    @Span('AssetService.generateUniqueName')
     private async generateUniqueName(
         inputFileName: string,
         generateNameFn: (fileName: string, conflictName?: string) => string,
@@ -615,7 +599,6 @@ export class AssetService {
         return outputFileName;
     }
 
-    @Span('AssetService.getDimensions')
     private getDimensions(imageFile: Buffer): { width: number; height: number } {
         try {
             const { width, height } = sizeOf(imageFile);
@@ -626,7 +609,6 @@ export class AssetService {
         }
     }
 
-    @Span('AssetService.createOrderableAssets')
     private createOrderableAssets(
         ctx: RequestContext,
         entity: EntityWithAssets,
@@ -636,7 +618,6 @@ export class AssetService {
         return this.connection.getRepository(ctx, orderableAssets[0].constructor).save(orderableAssets);
     }
 
-    @Span('AssetService.getOrderableAsset')
     private getOrderableAsset(
         ctx: RequestContext,
         entity: EntityWithAssets,
@@ -652,7 +633,6 @@ export class AssetService {
         });
     }
 
-    @Span('AssetService.removeExistingOrderableAssets')
     private async removeExistingOrderableAssets(ctx: RequestContext, entity: EntityWithAssets) {
         const propertyName = this.getHostEntityIdProperty(entity);
         const orderableAssetType = this.getOrderableAssetType(ctx, entity);
@@ -661,7 +641,6 @@ export class AssetService {
         });
     }
 
-    @Span('AssetService.getOrderableAssetType')
     private getOrderableAssetType(ctx: RequestContext, entity: EntityWithAssets): Type<OrderableAsset> {
         const assetRelation = this.connection
             .getRepository(ctx, entity.constructor)
@@ -672,7 +651,6 @@ export class AssetService {
         return assetRelation.type as Type<OrderableAsset>;
     }
 
-    @Span('AssetService.getHostEntityIdProperty')
     private getHostEntityIdProperty(entity: EntityWithAssets): string {
         const entityName = entity.constructor.name;
         switch (entityName) {
@@ -687,7 +665,6 @@ export class AssetService {
         }
     }
 
-    @Span('AssetService.validateMimeType')
     private validateMimeType(mimeType: string): boolean {
         const [type, subtype] = mimeType.split('/');
         const typeMatches = this.permittedMimeTypes.filter(t => t.type === type);
@@ -703,7 +680,6 @@ export class AssetService {
     /**
      * Find the entities which reference the given Asset as a featuredAsset.
      */
-    @Span('AssetService.findAssetUsages')
     private async findAssetUsages(
         ctx: RequestContext,
         asset: Asset,

+ 2 - 6
packages/core/src/service/services/auth.service.ts

@@ -9,6 +9,7 @@ import {
     NotVerifiedError,
     InvalidCredentialsError as ShopInvalidCredentialsError,
 } from '../../common/error/generated-graphql-shop-errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { AuthenticationStrategy } from '../../config/auth/authentication-strategy';
 import {
     NATIVE_AUTH_STRATEGY_NAME,
@@ -24,7 +25,6 @@ import { EventBus } from '../../event-bus/event-bus';
 import { AttemptedLoginEvent } from '../../event-bus/events/attempted-login-event';
 import { LoginEvent } from '../../event-bus/events/login-event';
 import { LogoutEvent } from '../../event-bus/events/logout-event';
-import { Span } from '../../instrumentation';
 
 import { SessionService } from './session.service';
 
@@ -35,6 +35,7 @@ import { SessionService } from './session.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class AuthService {
     constructor(
         private connection: TransactionalConnection,
@@ -47,7 +48,6 @@ export class AuthService {
      * @description
      * Authenticates a user's credentials and if okay, creates a new {@link AuthenticatedSession}.
      */
-    @Span('AuthService.authenticate')
     async authenticate(
         ctx: RequestContext,
         apiType: ApiType,
@@ -74,7 +74,6 @@ export class AuthService {
         return this.createAuthenticatedSessionForUser(ctx, authenticateResult, authenticationStrategy.name);
     }
 
-    @Span('AuthService.createAuthenticatedSessionForUser')
     async createAuthenticatedSessionForUser(
         ctx: RequestContext,
         user: User,
@@ -116,7 +115,6 @@ export class AuthService {
      * Verify the provided password against the one we have for the given user. Requires
      * the {@link NativeAuthenticationStrategy} to be configured.
      */
-    @Span('AuthService.verifyUserPassword')
     async verifyUserPassword(
         ctx: RequestContext,
         userId: ID,
@@ -137,7 +135,6 @@ export class AuthService {
      * @description
      * Deletes all sessions for the user associated with the given session token.
      */
-    @Span('AuthService.destroyAuthenticatedSession')
     async destroyAuthenticatedSession(ctx: RequestContext, sessionToken: string): Promise<void> {
         const session = await this.connection.getRepository(ctx, AuthenticatedSession).findOne({
             where: { token: sessionToken },
@@ -162,7 +159,6 @@ export class AuthService {
         method: typeof NATIVE_AUTH_STRATEGY_NAME,
     ): NativeAuthenticationStrategy;
     private getAuthenticationStrategy(apiType: ApiType, method: string): AuthenticationStrategy;
-    @Span('AuthService.getAuthenticationStrategy')
     private getAuthenticationStrategy(apiType: ApiType, method: string): AuthenticationStrategy {
         const { authOptions } = this.configService;
         const strategies =

+ 5 - 21
packages/core/src/service/services/channel.service.ts

@@ -11,7 +11,6 @@ import {
 import { DEFAULT_CHANNEL_CODE } from '@vendure/common/lib/shared-constants';
 import { ID, PaginatedList, Type } from '@vendure/common/lib/shared-types';
 import { unique } from '@vendure/common/lib/unique';
-import { getActiveSpan } from '@vendure/telemetry';
 import { FindOptionsWhere } from 'typeorm';
 
 import { RelationPaths } from '../../api';
@@ -24,6 +23,7 @@ import {
     UserInputError,
 } from '../../common/error/errors';
 import { LanguageNotAvailableError } from '../../common/error/generated-graphql-admin-errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { createSelfRefreshingCache, SelfRefreshingCache } from '../../common/self-refreshing-cache';
 import { ChannelAware, ListQueryOptions } from '../../common/types/common-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
@@ -40,7 +40,6 @@ import { Zone } from '../../entity/zone/zone.entity';
 import { EventBus } from '../../event-bus';
 import { ChangeChannelEvent } from '../../event-bus/events/change-channel-event';
 import { ChannelEvent } from '../../event-bus/events/channel-event';
-import { Span } from '../../instrumentation';
 import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
 import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { patchEntity } from '../helpers/utils/patch-entity';
@@ -53,6 +52,7 @@ import { GlobalSettingsService } from './global-settings.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class ChannelService {
     private allChannels: SelfRefreshingCache<Channel[], [RequestContext]>;
 
@@ -81,7 +81,6 @@ export class ChannelService {
      *
      * @internal
      */
-    @Span('ChannelService.createCache')
     async createCache(): Promise<SelfRefreshingCache<Channel[], [RequestContext]>> {
         return createSelfRefreshingCache({
             name: 'ChannelService.allChannels',
@@ -116,7 +115,6 @@ export class ChannelService {
      * specified in the RequestContext. This method will not save the entity to the database, but
      * assigns the `channels` property of the entity.
      */
-    @Span('ChannelService.assignToCurrentChannel')
     async assignToCurrentChannel<T extends ChannelAware & VendureEntity>(
         entity: T,
         ctx: RequestContext,
@@ -139,7 +137,6 @@ export class ChannelService {
      * @returns A promise that resolves to an array of objects, each containing a channel ID.
      * @private
      */
-    @Span('ChannelService.getAssignedEntityChannels')
     private async getAssignedEntityChannels<T extends ChannelAware & VendureEntity>(
         ctx: RequestContext,
         entityType: Type<T>,
@@ -178,7 +175,6 @@ export class ChannelService {
      * @description
      * Assigns the entity to the given Channels and saves all changes to the database.
      */
-    @Span('ChannelService.assignToChannels')
     async assignToChannels<T extends ChannelAware & VendureEntity>(
         ctx: RequestContext,
         entityType: Type<T>,
@@ -222,7 +218,6 @@ export class ChannelService {
      * @description
      * Removes the entity from the given Channels and saves.
      */
-    @Span('ChannelService.removeFromChannels')
     async removeFromChannels<T extends ChannelAware & VendureEntity>(
         ctx: RequestContext,
         entityType: Type<T>,
@@ -265,22 +260,21 @@ export class ChannelService {
      */
     async getChannelFromToken(token: string): Promise<Channel>;
     async getChannelFromToken(ctx: RequestContext, token: string): Promise<Channel>;
-    @Span('ChannelService.getChannelFromToken')
     async getChannelFromToken(ctxOrToken: RequestContext | string, token?: string): Promise<Channel> {
         const [ctx, channelToken] =
             // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
             ctxOrToken instanceof RequestContext ? [ctxOrToken, token!] : [undefined, ctxOrToken];
 
-        const span = getActiveSpan();
+        // const span = getActiveSpan();
         const allChannels = await this.allChannels.value(ctx);
 
         if (allChannels.length === 1 || channelToken === '') {
             // there is only the default channel, so return it
-            span?.setAttribute('channel.token', 'default');
+            // span?.setAttribute('channel.token', 'default');
             return this.getDefaultChannel(ctx);
         }
 
-        span?.setAttribute('channel.token', channelToken);
+        // span?.setAttribute('channel.token', channelToken);
         const channel = allChannels.find(c => c.token === channelToken);
         if (!channel) {
             throw new ChannelNotFoundError(channelToken);
@@ -292,7 +286,6 @@ export class ChannelService {
      * @description
      * Returns the default Channel.
      */
-    @Span('ChannelService.getDefaultChannel')
     async getDefaultChannel(ctx?: RequestContext): Promise<Channel> {
         const allChannels = await this.allChannels.value(ctx);
         const defaultChannel = allChannels.find(channel => channel.code === DEFAULT_CHANNEL_CODE);
@@ -303,7 +296,6 @@ export class ChannelService {
         return defaultChannel;
     }
 
-    @Span('ChannelService.findAll')
     findAll(
         ctx: RequestContext,
         options?: ListQueryOptions<Channel>,
@@ -321,7 +313,6 @@ export class ChannelService {
             }));
     }
 
-    @Span('ChannelService.findOne')
     findOne(ctx: RequestContext, id: ID): Promise<Channel | undefined> {
         return this.connection
             .getRepository(ctx, Channel)
@@ -329,7 +320,6 @@ export class ChannelService {
             .then(result => result ?? undefined);
     }
 
-    @Span('ChannelService.create')
     async create(
         ctx: RequestContext,
         input: CreateChannelInput,
@@ -375,7 +365,6 @@ export class ChannelService {
         return newChannel;
     }
 
-    @Span('ChannelService.update')
     async update(
         ctx: RequestContext,
         input: UpdateChannelInput,
@@ -472,7 +461,6 @@ export class ChannelService {
         return assertFound(this.findOne(ctx, channel.id));
     }
 
-    @Span('ChannelService.delete')
     async delete(ctx: RequestContext, id: ID): Promise<DeletionResponse> {
         const channel = await this.connection.getEntityOrThrow(ctx, Channel, id);
         if (channel.code === DEFAULT_CHANNEL_CODE)
@@ -499,7 +487,6 @@ export class ChannelService {
      * Type guard method which returns true if the given entity is an
      * instance of a class which implements the {@link ChannelAware} interface.
      */
-    @Span('ChannelService.isChannelAware')
     public isChannelAware(entity: VendureEntity): entity is VendureEntity & ChannelAware {
         const entityType = Object.getPrototypeOf(entity).constructor;
         return !!this.connection.rawConnection
@@ -510,7 +497,6 @@ export class ChannelService {
     /**
      * Ensures channel cache exists. If not, this method creates one.
      */
-    @Span('ChannelService.ensureCacheExists')
     private async ensureCacheExists() {
         if (this.allChannels) {
             return;
@@ -523,7 +509,6 @@ export class ChannelService {
      * There must always be a default Channel. If none yet exists, this method creates one.
      * Also ensures the default Channel token matches the defaultChannelToken config setting.
      */
-    @Span('ChannelService.ensureDefaultChannelExists')
     private async ensureDefaultChannelExists() {
         const { defaultChannelToken } = this.configService;
         let defaultChannel = await this.connection.rawConnection.getRepository(Channel).findOne({
@@ -561,7 +546,6 @@ export class ChannelService {
         }
     }
 
-    @Span('ChannelService.validateDefaultLanguageCode')
     private async validateDefaultLanguageCode(
         ctx: RequestContext,
         input: CreateChannelInput | UpdateChannelInput,

+ 2 - 26
packages/core/src/service/services/collection.service.ts

@@ -25,6 +25,7 @@ import { In, IsNull } from 'typeorm';
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
 import { ForbiddenError, IllegalOperationError, UserInputError } from '../../common/error/errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { Translated } from '../../common/types/locale-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
@@ -39,7 +40,6 @@ import { CollectionEvent } from '../../event-bus/events/collection-event';
 import { CollectionModificationEvent } from '../../event-bus/events/collection-modification-event';
 import { ProductEvent } from '../../event-bus/events/product-event';
 import { ProductVariantEvent } from '../../event-bus/events/product-variant-event';
-import { Span } from '../../instrumentation';
 import { JobQueue } from '../../job-queue/job-queue';
 import { JobQueueService } from '../../job-queue/job-queue.service';
 import { ConfigArgService } from '../helpers/config-arg/config-arg.service';
@@ -75,6 +75,7 @@ export type ApplyCollectionFiltersJobData = {
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class CollectionService implements OnModuleInit {
     private rootCollection: Translated<Collection> | undefined;
     private applyFiltersQueue: JobQueue<ApplyCollectionFiltersJobData>;
@@ -189,7 +190,6 @@ export class CollectionService implements OnModuleInit {
         });
     }
 
-    @Span('CollectionService.findAll')
     async findAll(
         ctx: RequestContext,
         options?: ListQueryOptions<Collection> & { topLevelOnly?: boolean },
@@ -220,7 +220,6 @@ export class CollectionService implements OnModuleInit {
         });
     }
 
-    @Span('CollectionService.findOne')
     async findOne(
         ctx: RequestContext,
         collectionId: ID,
@@ -242,7 +241,6 @@ export class CollectionService implements OnModuleInit {
         return this.translator.translate(collection, ctx, ['parent']);
     }
 
-    @Span('CollectionService.findByIds')
     async findByIds(
         ctx: RequestContext,
         ids: ID[],
@@ -257,7 +255,6 @@ export class CollectionService implements OnModuleInit {
         );
     }
 
-    @Span('CollectionService.findOneBySlug')
     async findOneBySlug(
         ctx: RequestContext,
         slug: string,
@@ -289,12 +286,10 @@ export class CollectionService implements OnModuleInit {
      * @description
      * Returns all configured CollectionFilters, as specified by the {@link CatalogOptions}.
      */
-    @Span('CollectionService.getAvailableFilters')
     getAvailableFilters(ctx: RequestContext): ConfigurableOperationDefinition[] {
         return this.configService.catalogOptions.collectionFilters.map(f => f.toGraphQlType(ctx));
     }
 
-    @Span('CollectionService.getParent')
     async getParent(ctx: RequestContext, collectionId: ID): Promise<Collection | undefined> {
         const parent = await this.connection
             .getRepository(ctx, Collection)
@@ -318,7 +313,6 @@ export class CollectionService implements OnModuleInit {
      * @description
      * Returns all child Collections of the Collection with the given id.
      */
-    @Span('CollectionService.getChildren')
     async getChildren(ctx: RequestContext, collectionId: ID): Promise<Collection[]> {
         return this.getDescendants(ctx, collectionId, 1);
     }
@@ -328,7 +322,6 @@ export class CollectionService implements OnModuleInit {
      * Returns an array of name/id pairs representing all ancestor Collections up
      * to the Root Collection.
      */
-    @Span('CollectionService.getBreadcrumbs')
     async getBreadcrumbs(
         ctx: RequestContext,
         collection: Collection,
@@ -352,7 +345,6 @@ export class CollectionService implements OnModuleInit {
      * @description
      * Returns all Collections which are associated with the given Product ID.
      */
-    @Span('CollectionService.getCollectionsByProductId')
     async getCollectionsByProductId(
         ctx: RequestContext,
         productId: ID,
@@ -380,7 +372,6 @@ export class CollectionService implements OnModuleInit {
      * Returns the descendants of a Collection as a flat array. The depth of the traversal can be limited
      * with the maxDepth argument. So to get only the immediate children, set maxDepth = 1.
      */
-    @Span('CollectionService.getDescendants')
     async getDescendants(
         ctx: RequestContext,
         rootId: ID,
@@ -446,7 +437,6 @@ export class CollectionService implements OnModuleInit {
             });
     }
 
-    @Span('CollectionService.previewCollectionVariants')
     async previewCollectionVariants(
         ctx: RequestContext,
         input: PreviewCollectionVariantsInput,
@@ -487,7 +477,6 @@ export class CollectionService implements OnModuleInit {
         }));
     }
 
-    @Span('CollectionService.create')
     async create(ctx: RequestContext, input: CreateCollectionInput): Promise<Translated<Collection>> {
         await this.slugValidator.validateSlugs(ctx, input, CollectionTranslation);
         const collection = await this.translatableSaver.create({
@@ -520,7 +509,6 @@ export class CollectionService implements OnModuleInit {
         return assertFound(this.findOne(ctx, collection.id));
     }
 
-    @Span('CollectionService.update')
     async update(ctx: RequestContext, input: UpdateCollectionInput): Promise<Translated<Collection>> {
         await this.slugValidator.validateSlugs(ctx, input, CollectionTranslation);
         const collection = await this.translatableSaver.update({
@@ -550,7 +538,6 @@ export class CollectionService implements OnModuleInit {
         return assertFound(this.findOne(ctx, collection.id));
     }
 
-    @Span('CollectionService.delete')
     async delete(ctx: RequestContext, id: ID): Promise<DeletionResponse> {
         const collection = await this.connection.getEntityOrThrow(ctx, Collection, id, {
             channelId: ctx.channelId,
@@ -586,7 +573,6 @@ export class CollectionService implements OnModuleInit {
      * Moves a Collection by specifying the parent Collection ID, and an index representing the order amongst
      * its siblings.
      */
-    @Span('CollectionService.move')
     async move(ctx: RequestContext, input: MoveCollectionInput): Promise<Translated<Collection>> {
         const target = await this.connection.getEntityOrThrow(ctx, Collection, input.collectionId, {
             channelId: ctx.channelId,
@@ -635,7 +621,6 @@ export class CollectionService implements OnModuleInit {
      *
      * @since 3.1.3
      */
-    @Span('CollectionService.setApplyAllFiltersOnProductUpdates')
     setApplyAllFiltersOnProductUpdates(applyAllFiltersOnProductUpdates: boolean) {
         this.applyAllFiltersOnProductUpdates = applyAllFiltersOnProductUpdates;
     }
@@ -649,7 +634,6 @@ export class CollectionService implements OnModuleInit {
      *
      * @since 3.1.3
      */
-    @Span('CollectionService.triggerApplyFiltersJob')
     async triggerApplyFiltersJob(
         ctx: RequestContext,
         options?: { collectionIds?: ID[]; applyToChangedVariantsOnly?: boolean },
@@ -667,7 +651,6 @@ export class CollectionService implements OnModuleInit {
         );
     }
 
-    @Span('CollectionService.getCollectionFiltersFromInput')
     private getCollectionFiltersFromInput(
         input: CreateCollectionInput | UpdateCollectionInput | PreviewCollectionVariantsInput,
     ): ConfigurableOperation[] {
@@ -692,7 +675,6 @@ export class CollectionService implements OnModuleInit {
     /**
      * Applies the CollectionFilters and returns the IDs of ProductVariants that need to be added or removed.
      */
-    @Span('CollectionService.applyCollectionFiltersInternal')
     private async applyCollectionFiltersInternal(
         collection: Collection,
         applyToChangedVariantsOnly = true,
@@ -808,7 +790,6 @@ export class CollectionService implements OnModuleInit {
      * Gets all filters of ancestor Collections while respecting the `inheritFilters` setting of each.
      * As soon as `inheritFilters === false` is encountered, the collected filters are returned.
      */
-    @Span('CollectionService.getAncestorFilters')
     private async getAncestorFilters(collection: Collection): Promise<ConfigurableOperation[]> {
         const ancestorFilters: ConfigurableOperation[] = [];
         if (collection.inheritFilters) {
@@ -826,7 +807,6 @@ export class CollectionService implements OnModuleInit {
     /**
      * Returns the IDs of the Collection's ProductVariants.
      */
-    @Span('CollectionService.getCollectionProductVariantIds')
     async getCollectionProductVariantIds(collection: Collection, ctx?: RequestContext): Promise<ID[]> {
         if (collection.productVariants) {
             return collection.productVariants.map(v => v.id);
@@ -845,7 +825,6 @@ export class CollectionService implements OnModuleInit {
     /**
      * Returns the next position value in the given parent collection.
      */
-    @Span('CollectionService.getNextPositionInParent')
     private async getNextPositionInParent(ctx: RequestContext, maybeParentId?: ID): Promise<number> {
         const parentId = maybeParentId || (await this.getRootCollection(ctx)).id;
         const result = await this.connection
@@ -877,7 +856,6 @@ export class CollectionService implements OnModuleInit {
         }
     }
 
-    @Span('CollectionService.getRootCollection')
     private async getRootCollection(ctx: RequestContext): Promise<Collection> {
         const cachedRoot = this.rootCollection;
 
@@ -928,7 +906,6 @@ export class CollectionService implements OnModuleInit {
      * @description
      * Assigns Collections to the specified Channel
      */
-    @Span('CollectionService.assignCollectionsToChannel')
     async assignCollectionsToChannel(
         ctx: RequestContext,
         input: AssignCollectionsToChannelInput,
@@ -973,7 +950,6 @@ export class CollectionService implements OnModuleInit {
      * @description
      * Remove Collections from the specified Channel
      */
-    @Span('CollectionService.removeCollectionsFromChannel')
     async removeCollectionsFromChannel(
         ctx: RequestContext,
         input: RemoveCollectionsFromChannelInput,

+ 2 - 8
packages/core/src/service/services/country.service.ts

@@ -10,6 +10,7 @@ import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
 import { UserInputError } from '../../common/error/errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { Translated } from '../../common/types/locale-types';
 import { assertFound } from '../../common/utils';
@@ -19,7 +20,6 @@ import { Country } from '../../entity/region/country.entity';
 import { RegionTranslation } from '../../entity/region/region-translation.entity';
 import { EventBus } from '../../event-bus';
 import { CountryEvent } from '../../event-bus/events/country-event';
-import { Span } from '../../instrumentation';
 import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { TranslatableSaver } from '../helpers/translatable-saver/translatable-saver';
 import { TranslatorService } from '../helpers/translator/translator.service';
@@ -31,6 +31,7 @@ import { TranslatorService } from '../helpers/translator/translator.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class CountryService {
     constructor(
         private connection: TransactionalConnection,
@@ -40,7 +41,6 @@ export class CountryService {
         private translator: TranslatorService,
     ) {}
 
-    @Span('CountryService.findAll')
     findAll(
         ctx: RequestContext,
         options?: ListQueryOptions<Country>,
@@ -58,7 +58,6 @@ export class CountryService {
             });
     }
 
-    @Span('CountryService.findOne')
     findOne(
         ctx: RequestContext,
         countryId: ID,
@@ -74,7 +73,6 @@ export class CountryService {
      * @description
      * Returns an array of enabled Countries, intended for use in a public-facing (ie. Shop) API.
      */
-    @Span('CountryService.findAllAvailable')
     findAllAvailable(ctx: RequestContext): Promise<Array<Translated<Country>>> {
         return this.connection
             .getRepository(ctx, Country)
@@ -86,7 +84,6 @@ export class CountryService {
      * @description
      * Returns a Country based on its ISO country code.
      */
-    @Span('CountryService.findOneByCode')
     async findOneByCode(ctx: RequestContext, countryCode: string): Promise<Translated<Country>> {
         const country = await this.connection.getRepository(ctx, Country).findOne({
             where: {
@@ -99,7 +96,6 @@ export class CountryService {
         return this.translator.translate(country, ctx);
     }
 
-    @Span('CountryService.create')
     async create(ctx: RequestContext, input: CreateCountryInput): Promise<Translated<Country>> {
         const country = await this.translatableSaver.create({
             ctx,
@@ -111,7 +107,6 @@ export class CountryService {
         return assertFound(this.findOne(ctx, country.id));
     }
 
-    @Span('CountryService.update')
     async update(ctx: RequestContext, input: UpdateCountryInput): Promise<Translated<Country>> {
         const country = await this.translatableSaver.update({
             ctx,
@@ -123,7 +118,6 @@ export class CountryService {
         return assertFound(this.findOne(ctx, country.id));
     }
 
-    @Span('CountryService.delete')
     async delete(ctx: RequestContext, id: ID): Promise<DeletionResponse> {
         const country = await this.connection.getEntityOrThrow(ctx, Country, id);
         const addressesUsingCountry = await this.connection

+ 2 - 10
packages/core/src/service/services/customer-group.service.ts

@@ -15,6 +15,7 @@ import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
 import { UserInputError } from '../../common/error/errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { assertFound, idsAreEqual } from '../../common/utils';
 import { TransactionalConnection } from '../../connection/transactional-connection';
 import { CustomerGroup } from '../../entity/customer-group/customer-group.entity';
@@ -22,7 +23,6 @@ import { Customer } from '../../entity/customer/customer.entity';
 import { EventBus } from '../../event-bus/event-bus';
 import { CustomerGroupChangeEvent } from '../../event-bus/events/customer-group-change-event';
 import { CustomerGroupEvent } from '../../event-bus/events/customer-group-event';
-import { Span } from '../../instrumentation';
 import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
 import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { patchEntity } from '../helpers/utils/patch-entity';
@@ -36,6 +36,7 @@ import { HistoryService } from './history.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class CustomerGroupService {
     constructor(
         private connection: TransactionalConnection,
@@ -45,7 +46,6 @@ export class CustomerGroupService {
         private customFieldRelationService: CustomFieldRelationService,
     ) {}
 
-    @Span('CustomerGroupService.findAll')
     findAll(
         ctx: RequestContext,
         options?: CustomerGroupListOptions,
@@ -57,7 +57,6 @@ export class CustomerGroupService {
             .then(([items, totalItems]) => ({ items, totalItems }));
     }
 
-    @Span('CustomerGroupService.findOne')
     findOne(
         ctx: RequestContext,
         customerGroupId: ID,
@@ -73,7 +72,6 @@ export class CustomerGroupService {
      * @description
      * Returns a {@link PaginatedList} of all the Customers in the group.
      */
-    @Span('CustomerGroupService.getGroupCustomers')
     getGroupCustomers(
         ctx: RequestContext,
         customerGroupId: ID,
@@ -90,7 +88,6 @@ export class CustomerGroupService {
             .then(([items, totalItems]) => ({ items, totalItems }));
     }
 
-    @Span('CustomerGroupService.create')
     async create(ctx: RequestContext, input: CreateCustomerGroupInput): Promise<CustomerGroup> {
         const customerGroup = new CustomerGroup(input);
 
@@ -116,7 +113,6 @@ export class CustomerGroupService {
         return assertFound(this.findOne(ctx, savedCustomerGroup.id));
     }
 
-    @Span('CustomerGroupService.update')
     async update(ctx: RequestContext, input: UpdateCustomerGroupInput): Promise<CustomerGroup> {
         const customerGroup = await this.connection.getEntityOrThrow(ctx, CustomerGroup, input.id);
         const updatedCustomerGroup = patchEntity(customerGroup, input);
@@ -131,7 +127,6 @@ export class CustomerGroupService {
         return assertFound(this.findOne(ctx, customerGroup.id));
     }
 
-    @Span('CustomerGroupService.delete')
     async delete(ctx: RequestContext, id: ID): Promise<DeletionResponse> {
         const group = await this.connection.getEntityOrThrow(ctx, CustomerGroup, id);
         try {
@@ -149,7 +144,6 @@ export class CustomerGroupService {
         }
     }
 
-    @Span('CustomerGroupService.addCustomersToGroup')
     async addCustomersToGroup(
         ctx: RequestContext,
         input: MutationAddCustomersToGroupArgs,
@@ -176,7 +170,6 @@ export class CustomerGroupService {
         return assertFound(this.findOne(ctx, group.id));
     }
 
-    @Span('CustomerGroupService.removeCustomersFromGroup')
     async removeCustomersFromGroup(
         ctx: RequestContext,
         input: MutationRemoveCustomersFromGroupArgs,
@@ -202,7 +195,6 @@ export class CustomerGroupService {
         return assertFound(this.findOne(ctx, group.id));
     }
 
-    @Span('CustomerGroupService.getCustomersFromIds')
     private getCustomersFromIds(ctx: RequestContext, ids: ID[]): Promise<Customer[]> | Customer[] {
         if (ids.length === 0) {
             return new Array<Customer>();

+ 2 - 3
packages/core/src/service/services/customer.service.ts

@@ -37,6 +37,7 @@ import {
     PasswordResetTokenInvalidError,
     PasswordValidationError,
 } from '../../common/error/generated-graphql-shop-errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound, idsAreEqual, normalizeEmailAddress } from '../../common/utils';
 import { NATIVE_AUTH_STRATEGY_NAME } from '../../config/auth/native-authentication-strategy';
@@ -59,7 +60,6 @@ import { IdentifierChangeEvent } from '../../event-bus/events/identifier-change-
 import { IdentifierChangeRequestEvent } from '../../event-bus/events/identifier-change-request-event';
 import { PasswordResetEvent } from '../../event-bus/events/password-reset-event';
 import { PasswordResetVerifiedEvent } from '../../event-bus/events/password-reset-verified-event';
-import { Span } from '../../instrumentation';
 import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
 import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { TranslatorService } from '../helpers/translator/translator.service';
@@ -78,6 +78,7 @@ import { UserService } from './user.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class CustomerService {
     constructor(
         private connection: TransactionalConnection,
@@ -92,7 +93,6 @@ export class CustomerService {
         private translator: TranslatorService,
     ) {}
 
-    @Span('CustomerService.findAll')
     findAll(
         ctx: RequestContext,
         options: ListQueryOptions<Customer> | undefined,
@@ -119,7 +119,6 @@ export class CustomerService {
             .then(([items, totalItems]) => ({ items, totalItems }));
     }
 
-    @Span('CustomerService.findOne')
     findOne(
         ctx: RequestContext,
         id: ID,

+ 3 - 1
packages/core/src/service/services/facet-value.service.ts

@@ -11,15 +11,16 @@ import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
 
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { Translated } from '../../common/types/locale-types';
 import { assertFound } from '../../common/utils';
 import { ConfigService } from '../../config/config.service';
 import { TransactionalConnection } from '../../connection/transactional-connection';
 import { Product, ProductVariant } from '../../entity';
-import { Facet } from '../../entity/facet/facet.entity';
 import { FacetValueTranslation } from '../../entity/facet-value/facet-value-translation.entity';
 import { FacetValue } from '../../entity/facet-value/facet-value.entity';
+import { Facet } from '../../entity/facet/facet.entity';
 import { EventBus } from '../../event-bus';
 import { FacetValueEvent } from '../../event-bus/events/facet-value-event';
 import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
@@ -37,6 +38,7 @@ import { ChannelService } from './channel.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class FacetValueService {
     constructor(
         private connection: TransactionalConnection,

+ 24 - 33
packages/core/src/service/services/facet.service.ts

@@ -11,12 +11,11 @@ import {
     UpdateFacetInput,
 } from '@vendure/common/lib/generated-types';
 import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
-import { getActiveSpan } from '@vendure/telemetry';
 import { In } from 'typeorm';
 
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
-import { ErrorResultUnion, FacetInUseError, ForbiddenError, UserInputError } from '../../common';
+import { ErrorResultUnion, FacetInUseError, ForbiddenError, Instrument, UserInputError } from '../../common';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { Translated } from '../../common/types/locale-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
@@ -27,7 +26,6 @@ import { FacetTranslation } from '../../entity/facet/facet-translation.entity';
 import { Facet } from '../../entity/facet/facet.entity';
 import { EventBus } from '../../event-bus';
 import { FacetEvent } from '../../event-bus/events/facet-event';
-import { Span } from '../../instrumentation';
 import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
 import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { TranslatableSaver } from '../helpers/translatable-saver/translatable-saver';
@@ -45,6 +43,7 @@ import { RoleService } from './role.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class FacetService {
     constructor(
         private connection: TransactionalConnection,
@@ -59,7 +58,6 @@ export class FacetService {
         private roleService: RoleService,
     ) {}
 
-    @Span('FacetService.findAll')
     findAll(
         ctx: RequestContext,
         options?: ListQueryOptions<Facet>,
@@ -83,7 +81,6 @@ export class FacetService {
             });
     }
 
-    @Span('FacetService.findOne')
     findOne(
         ctx: RequestContext,
         facetId: ID,
@@ -109,7 +106,6 @@ export class FacetService {
         facetCode: string,
         lang: LanguageCode,
     ): Promise<Translated<Facet> | undefined>;
-    @Span('FacetService.findByCode')
     findByCode(
         ctxOrFacetCode: RequestContext | string,
         facetCodeOrLang: string | LanguageCode,
@@ -145,7 +141,6 @@ export class FacetService {
      * @description
      * Returns the Facet which contains the given FacetValue id.
      */
-    @Span('FacetService.findByFacetValueId')
     async findByFacetValueId(ctx: RequestContext, id: ID): Promise<Translated<Facet> | undefined> {
         const facet = await this.connection
             .getRepository(ctx, Facet)
@@ -159,7 +154,6 @@ export class FacetService {
         }
     }
 
-    @Span('FacetService.create')
     async create(ctx: RequestContext, input: CreateFacetInput): Promise<Translated<Facet>> {
         const facet = await this.translatableSaver.create({
             ctx,
@@ -181,7 +175,6 @@ export class FacetService {
         return assertFound(this.findOne(ctx, facet.id));
     }
 
-    @Span('FacetService.update')
     async update(ctx: RequestContext, input: UpdateFacetInput): Promise<Translated<Facet>> {
         const facet = await this.translatableSaver.update({
             ctx,
@@ -199,10 +192,9 @@ export class FacetService {
         return assertFound(this.findOne(ctx, facet.id));
     }
 
-    @Span('FacetService.delete')
     async delete(ctx: RequestContext, id: ID, force: boolean = false): Promise<DeletionResponse> {
-        const span = getActiveSpan();
-        span?.setAttribute('force', force.toString());
+        // const span = getActiveSpan();
+        // span?.setAttribute('force', force.toString());
 
         const facet = await this.connection.getEntityOrThrow(ctx, Facet, id, {
             relations: ['values'],
@@ -230,29 +222,29 @@ export class FacetService {
             await this.connection.getRepository(ctx, Facet).remove(facet);
             await this.eventBus.publish(new FacetEvent(ctx, deletedFacet, 'deleted', id));
             result = DeletionResult.DELETED;
-            span?.addEvent('facet-deleted', {
-                facetCode: facet.code,
-                productCount,
-                variantCount,
-            });
+            // span?.addEvent('facet-deleted', {
+            //     facetCode: facet.code,
+            //     productCount,
+            //     variantCount,
+            // });
         } else if (force) {
             await this.connection.getRepository(ctx, Facet).remove(facet);
             await this.eventBus.publish(new FacetEvent(ctx, deletedFacet, 'deleted', id));
             message = ctx.translate('message.facet-force-deleted', i18nVars);
             result = DeletionResult.DELETED;
-            span?.addEvent('facet-deleted', {
-                facetCode: facet.code,
-                productCount,
-                variantCount,
-            });
+            // span?.addEvent('facet-deleted', {
+            //     facetCode: facet.code,
+            //     productCount,
+            //     variantCount,
+            // });
         } else {
             message = ctx.translate('message.facet-used', i18nVars);
             result = DeletionResult.NOT_DELETED;
-            span?.addEvent('facet-not-deleted', {
-                facetCode: facet.code,
-                productCount,
-                variantCount,
-            });
+            // span?.addEvent('facet-not-deleted', {
+            //     facetCode: facet.code,
+            //     productCount,
+            //     variantCount,
+            // });
         }
 
         return {
@@ -293,7 +285,6 @@ export class FacetService {
      * @description
      * Assigns Facets to the specified Channel
      */
-    @Span('FacetService.assignFacetsToChannel')
     async assignFacetsToChannel(
         ctx: RequestContext,
         input: AssignFacetsToChannelInput,
@@ -322,12 +313,12 @@ export class FacetService {
             ),
         ]);
 
-        const span = getActiveSpan();
+        // const span = getActiveSpan();
 
-        span?.addEvent('facets-assigned-to-channel', {
-            facetIds: facetsToAssign.map(f => f.id).join(','),
-            channelId: input.channelId,
-        });
+        // span?.addEvent('facets-assigned-to-channel', {
+        //     facetIds: facetsToAssign.map(f => f.id).join(','),
+        //     channelId: input.channelId,
+        // });
 
         return this.connection
             .findByIdsInChannel(

+ 4 - 3
packages/core/src/service/services/fulfillment.service.ts

@@ -12,19 +12,19 @@ import {
     FulfillmentStateTransitionError,
     InvalidFulfillmentHandlerError,
 } from '../../common/error/generated-graphql-admin-errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { ConfigService } from '../../config/config.service';
 import { TransactionalConnection } from '../../connection/transactional-connection';
 import { Fulfillment } from '../../entity/fulfillment/fulfillment.entity';
-import { Order } from '../../entity/order/order.entity';
-import { OrderLine } from '../../entity/order-line/order-line.entity';
 import { FulfillmentLine } from '../../entity/order-line-reference/fulfillment-line.entity';
+import { OrderLine } from '../../entity/order-line/order-line.entity';
+import { Order } from '../../entity/order/order.entity';
 import { EventBus } from '../../event-bus/event-bus';
 import { FulfillmentEvent } from '../../event-bus/events/fulfillment-event';
 import { FulfillmentStateTransitionEvent } from '../../event-bus/events/fulfillment-state-transition-event';
 import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
 import { FulfillmentState } from '../helpers/fulfillment-state-machine/fulfillment-state';
 import { FulfillmentStateMachine } from '../helpers/fulfillment-state-machine/fulfillment-state-machine';
-
 /**
  * @description
  * Contains methods relating to {@link Fulfillment} entities.
@@ -32,6 +32,7 @@ import { FulfillmentStateMachine } from '../helpers/fulfillment-state-machine/fu
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class FulfillmentService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 0
packages/core/src/service/services/global-settings.service.ts

@@ -5,6 +5,7 @@ import { RequestContext } from '../../api/common/request-context';
 import { RequestContextCacheService } from '../../cache/request-context-cache.service';
 import { CacheKey } from '../../common/constants';
 import { InternalServerError } from '../../common/error/errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { ConfigService } from '../../config/config.service';
 import { TransactionalConnection } from '../../connection/transactional-connection';
 import { GlobalSettings } from '../../entity/global-settings/global-settings.entity';
@@ -20,6 +21,7 @@ import { patchEntity } from '../helpers/utils/patch-entity';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class GlobalSettingsService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 1
packages/core/src/service/services/history.service.ts

@@ -10,6 +10,7 @@ import {
 import { ID, PaginatedList, Type } from '@vendure/common/lib/shared-types';
 
 import { RequestContext } from '../../api/common/request-context';
+import { Instrument } from '../../common/instrument-decorator';
 import { TransactionalConnection } from '../../connection/transactional-connection';
 import { Administrator } from '../../entity/administrator/administrator.entity';
 import { CustomerHistoryEntry } from '../../entity/history-entry/customer-history-entry.entity';
@@ -24,7 +25,6 @@ import { PaymentState } from '../helpers/payment-state-machine/payment-state';
 import { RefundState } from '../helpers/refund-state-machine/refund-state';
 
 import { AdministratorService } from './administrator.service';
-
 export interface CustomerHistoryEntryData {
     [HistoryEntryType.CUSTOMER_REGISTERED]: {
         strategy: string;
@@ -246,6 +246,7 @@ export interface UpdateCustomerHistoryEntryArgs<T extends keyof CustomerHistoryE
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class HistoryService {
     constructor(
         private connection: TransactionalConnection,

+ 3 - 1
packages/core/src/service/services/order-testing.service.ts

@@ -10,11 +10,12 @@ import {
 import { ID } from '@vendure/common/lib/shared-types';
 
 import { RequestContext } from '../../api/common/request-context';
+import { Instrument } from '../../common/instrument-decorator';
 import { grossPriceOf, netPriceOf } from '../../common/tax-utils';
 import { ConfigService } from '../../config/config.service';
 import { TransactionalConnection } from '../../connection/transactional-connection';
-import { Order } from '../../entity/order/order.entity';
 import { OrderLine } from '../../entity/order-line/order-line.entity';
+import { Order } from '../../entity/order/order.entity';
 import { ProductVariant } from '../../entity/product-variant/product-variant.entity';
 import { ShippingLine } from '../../entity/shipping-line/shipping-line.entity';
 import { ShippingMethod } from '../../entity/shipping-method/shipping-method.entity';
@@ -32,6 +33,7 @@ import { TranslatorService } from '../helpers/translator/translator.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class OrderTestingService {
     constructor(
         private connection: TransactionalConnection,

+ 4 - 2
packages/core/src/service/services/order.service.ts

@@ -74,6 +74,7 @@ import {
     PaymentDeclinedError,
     PaymentFailedError,
 } from '../../common/error/generated-graphql-shop-errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { grossPriceOf, netPriceOf } from '../../common/tax-utils';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
@@ -84,10 +85,10 @@ import { Channel } from '../../entity/channel/channel.entity';
 import { Customer } from '../../entity/customer/customer.entity';
 import { Fulfillment } from '../../entity/fulfillment/fulfillment.entity';
 import { HistoryEntry } from '../../entity/history-entry/history-entry.entity';
-import { Order } from '../../entity/order/order.entity';
-import { OrderLine } from '../../entity/order-line/order-line.entity';
 import { FulfillmentLine } from '../../entity/order-line-reference/fulfillment-line.entity';
+import { OrderLine } from '../../entity/order-line/order-line.entity';
 import { OrderModification } from '../../entity/order-modification/order-modification.entity';
+import { Order } from '../../entity/order/order.entity';
 import { Payment } from '../../entity/payment/payment.entity';
 import { ProductVariant } from '../../entity/product-variant/product-variant.entity';
 import { Promotion } from '../../entity/promotion/promotion.entity';
@@ -137,6 +138,7 @@ import { StockLevelService } from './stock-level.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class OrderService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 0
packages/core/src/service/services/payment-method.service.ts

@@ -16,6 +16,7 @@ import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
 import { ForbiddenError, UserInputError } from '../../common/error/errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { Translated } from '../../common/types/locale-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
@@ -44,6 +45,7 @@ import { RoleService } from './role.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class PaymentMethodService {
     constructor(
         private connection: TransactionalConnection,

+ 5 - 4
packages/core/src/service/services/payment.service.ts

@@ -12,18 +12,18 @@ import {
     RefundStateTransitionError,
 } from '../../common/error/generated-graphql-admin-errors';
 import { IneligiblePaymentMethodError } from '../../common/error/generated-graphql-shop-errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { PaymentMetadata } from '../../common/types/common-types';
 import { idsAreEqual } from '../../common/utils';
 import { Logger } from '../../config/logger/vendure-logger';
 import { PaymentMethodHandler } from '../../config/payment/payment-method-handler';
 import { TransactionalConnection } from '../../connection/transactional-connection';
 import { Fulfillment } from '../../entity/fulfillment/fulfillment.entity';
-import { Order } from '../../entity/order/order.entity';
-import { OrderLine } from '../../entity/order-line/order-line.entity';
-import { FulfillmentLine } from '../../entity/order-line-reference/fulfillment-line.entity';
 import { RefundLine } from '../../entity/order-line-reference/refund-line.entity';
-import { Payment } from '../../entity/payment/payment.entity';
+import { OrderLine } from '../../entity/order-line/order-line.entity';
+import { Order } from '../../entity/order/order.entity';
 import { PaymentMethod } from '../../entity/payment-method/payment-method.entity';
+import { Payment } from '../../entity/payment/payment.entity';
 import { Refund } from '../../entity/refund/refund.entity';
 import { EventBus } from '../../event-bus/event-bus';
 import { PaymentStateTransitionEvent } from '../../event-bus/events/payment-state-transition-event';
@@ -41,6 +41,7 @@ import { PaymentMethodService } from './payment-method.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class PaymentService {
     constructor(
         private connection: TransactionalConnection,

+ 3 - 1
packages/core/src/service/services/product-option-group.service.ts

@@ -9,14 +9,15 @@ import { FindManyOptions, IsNull, Like } from 'typeorm';
 
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
+import { Instrument } from '../../common/instrument-decorator';
 import { Translated } from '../../common/types/locale-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
 import { Logger } from '../../config/logger/vendure-logger';
 import { TransactionalConnection } from '../../connection/transactional-connection';
-import { Product } from '../../entity/product/product.entity';
 import { ProductOptionGroupTranslation } from '../../entity/product-option-group/product-option-group-translation.entity';
 import { ProductOptionGroup } from '../../entity/product-option-group/product-option-group.entity';
 import { ProductVariant } from '../../entity/product-variant/product-variant.entity';
+import { Product } from '../../entity/product/product.entity';
 import { EventBus } from '../../event-bus';
 import { ProductOptionGroupEvent } from '../../event-bus/events/product-option-group-event';
 import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
@@ -32,6 +33,7 @@ import { ProductOptionService } from './product-option.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class ProductOptionGroupService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 0
packages/core/src/service/services/product-option.service.ts

@@ -9,6 +9,7 @@ import {
 import { ID } from '@vendure/common/lib/shared-types';
 
 import { RequestContext } from '../../api/common/request-context';
+import { Instrument } from '../../common/instrument-decorator';
 import { Translated } from '../../common/types/locale-types';
 import { assertFound } from '../../common/utils';
 import { Logger } from '../../config/logger/vendure-logger';
@@ -30,6 +31,7 @@ import { TranslatorService } from '../helpers/translator/translator.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class ProductOptionService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 29
packages/core/src/service/services/product-variant.service.ts

@@ -19,6 +19,7 @@ import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
 import { RequestContextCacheService } from '../../cache/request-context-cache.service';
 import { ForbiddenError, UserInputError } from '../../common/error/errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { roundMoney } from '../../common/round-money';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { Translated } from '../../common/types/locale-types';
@@ -43,7 +44,6 @@ import { EventBus } from '../../event-bus/event-bus';
 import { ProductVariantChannelEvent } from '../../event-bus/events/product-variant-channel-event';
 import { ProductVariantEvent } from '../../event-bus/events/product-variant-event';
 import { ProductVariantPriceEvent } from '../../event-bus/events/product-variant-price-event';
-import { Span } from '../../instrumentation';
 import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
 import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { ProductPriceApplicator } from '../helpers/product-price-applicator/product-price-applicator';
@@ -68,6 +68,7 @@ import { TaxCategoryService } from './tax-category.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class ProductVariantService {
     constructor(
         private connection: TransactionalConnection,
@@ -89,7 +90,6 @@ export class ProductVariantService {
         private translator: TranslatorService,
     ) {}
 
-    @Span('ProductVariantService.findAll')
     async findAll(
         ctx: RequestContext,
         options?: ListQueryOptions<ProductVariant>,
@@ -123,7 +123,6 @@ export class ProductVariantService {
             });
     }
 
-    @Span('ProductVariantService.findOne')
     findOne(
         ctx: RequestContext,
         productVariantId: ID,
@@ -146,7 +145,6 @@ export class ProductVariantService {
             });
     }
 
-    @Span('ProductVariantService.findByIds')
     findByIds(ctx: RequestContext, ids: ID[]): Promise<Array<Translated<ProductVariant>>> {
         return this.connection
             .findByIdsInChannel(ctx, ProductVariant, ids, ctx.channelId, {
@@ -162,7 +160,6 @@ export class ProductVariantService {
             .then(variants => this.applyPricesAndTranslateVariants(ctx, variants));
     }
 
-    @Span('ProductVariantService.getVariantsByProductId')
     getVariantsByProductId(
         ctx: RequestContext,
         productId: ID,
@@ -209,7 +206,6 @@ export class ProductVariantService {
      * @description
      * Returns a {@link PaginatedList} of all ProductVariants associated with the given Collection.
      */
-    @Span('ProductVariantService.getVariantsByCollectionId')
     getVariantsByCollectionId(
         ctx: RequestContext,
         collectionId: ID,
@@ -245,7 +241,6 @@ export class ProductVariantService {
      * @description
      * Returns all Channels to which the ProductVariant is assigned.
      */
-    @Span('ProductVariantService.getProductVariantChannels')
     async getProductVariantChannels(ctx: RequestContext, productVariantId: ID): Promise<Channel[]> {
         const variant = await this.connection.getEntityOrThrow(ctx, ProductVariant, productVariantId, {
             relations: ['channels'],
@@ -254,7 +249,6 @@ export class ProductVariantService {
         return variant.channels;
     }
 
-    @Span('ProductVariantService.getProductVariantPrices')
     async getProductVariantPrices(ctx: RequestContext, productVariantId: ID): Promise<ProductVariantPrice[]> {
         return this.connection
             .getRepository(ctx, ProductVariantPrice)
@@ -268,7 +262,6 @@ export class ProductVariantService {
      * @description
      * Returns the ProductVariant associated with the given {@link OrderLine}.
      */
-    @Span('ProductVariantService.getVariantByOrderLineId')
     async getVariantByOrderLineId(ctx: RequestContext, orderLineId: ID): Promise<Translated<ProductVariant>> {
         const { productVariant } = await this.connection.getEntityOrThrow(ctx, OrderLine, orderLineId, {
             relations: ['productVariant', 'productVariant.taxCategory'],
@@ -281,7 +274,6 @@ export class ProductVariantService {
      * @description
      * Returns the {@link ProductOption}s for the given ProductVariant.
      */
-    @Span('ProductVariantService.getOptionsForVariant')
     getOptionsForVariant(ctx: RequestContext, variantId: ID): Promise<Array<Translated<ProductOption>>> {
         return this.connection
             .findOneInChannel(ctx, ProductVariant, variantId, ctx.channelId, {
@@ -290,7 +282,6 @@ export class ProductVariantService {
             .then(variant => (!variant ? [] : variant.options.map(o => this.translator.translate(o, ctx))));
     }
 
-    @Span('ProductVariantService.getFacetValuesForVariant')
     getFacetValuesForVariant(ctx: RequestContext, variantId: ID): Promise<Array<Translated<FacetValue>>> {
         return this.connection
             .findOneInChannel(ctx, ProductVariant, variantId, ctx.channelId, {
@@ -307,7 +298,6 @@ export class ProductVariantService {
      * method performs a large multi-table join with all the typical data needed for a "product detail"
      * page, this method returns only the Product itself.
      */
-    @Span('ProductVariantService.getProductForVariant')
     async getProductForVariant(ctx: RequestContext, variant: ProductVariant): Promise<Translated<Product>> {
         let product;
 
@@ -328,7 +318,6 @@ export class ProductVariantService {
      * for purchase by Customers. This is determined by the ProductVariant's `stockOnHand` value,
      * as well as the local and global `outOfStockThreshold` settings.
      */
-    @Span('ProductVariantService.getSaleableStockLevel')
     async getSaleableStockLevel(ctx: RequestContext, variant: ProductVariant): Promise<number> {
         const { outOfStockThreshold, trackInventory } = await this.globalSettingsService.getSettings(ctx);
 
@@ -367,7 +356,6 @@ export class ProductVariantService {
      * Returns the stockLevel to display to the customer, as specified by the configured
      * {@link StockDisplayStrategy}.
      */
-    @Span('ProductVariantService.getDisplayStockLevel')
     async getDisplayStockLevel(ctx: RequestContext, variant: ProductVariant): Promise<string> {
         const { stockDisplayStrategy } = this.configService.catalogOptions;
         const saleableStockLevel = await this.getSaleableStockLevel(ctx, variant);
@@ -379,7 +367,6 @@ export class ProductVariantService {
      * Returns the number of fulfillable units of the ProductVariant, equivalent to stockOnHand
      * for those variants which are tracking inventory.
      */
-    @Span('ProductVariantService.getFulfillableStockLevel')
     async getFulfillableStockLevel(ctx: RequestContext, variant: ProductVariant): Promise<number> {
         const { outOfStockThreshold, trackInventory } = await this.globalSettingsService.getSettings(ctx);
         const inventoryNotTracked =
@@ -392,7 +379,6 @@ export class ProductVariantService {
         return stockOnHand;
     }
 
-    @Span('ProductVariantService.create')
     async create(
         ctx: RequestContext,
         input: CreateProductVariantInput[],
@@ -407,7 +393,6 @@ export class ProductVariantService {
         return createdVariants;
     }
 
-    @Span('ProductVariantService.update')
     async update(
         ctx: RequestContext,
         input: UpdateProductVariantInput[],
@@ -423,7 +408,6 @@ export class ProductVariantService {
         return updatedVariants;
     }
 
-    @Span('ProductVariantService.createSingle')
     private async createSingle(ctx: RequestContext, input: CreateProductVariantInput): Promise<ID> {
         await this.validateVariantOptionIds(ctx, input.productId, input.optionIds);
         if (!input.optionIds) {
@@ -491,7 +475,6 @@ export class ProductVariantService {
         return createdVariant.id;
     }
 
-    @Span('ProductVariantService.updateSingle')
     private async updateSingle(ctx: RequestContext, input: UpdateProductVariantInput): Promise<ID> {
         const existingVariant = await this.connection.getEntityOrThrow(ctx, ProductVariant, input.id, {
             channelId: ctx.channelId,
@@ -585,7 +568,6 @@ export class ProductVariantService {
      * Creates a {@link ProductVariantPrice} for the given ProductVariant/Channel combination.
      * If the `currencyCode` is not specified, the default currency of the Channel will be used.
      */
-    @Span('ProductVariantService.createOrUpdateProductVariantPrice')
     async createOrUpdateProductVariantPrice(
         ctx: RequestContext,
         productVariantId: ID,
@@ -672,7 +654,6 @@ export class ProductVariantService {
         return targetPrice;
     }
 
-    @Span('ProductVariantService.deleteProductVariantPrice')
     async deleteProductVariantPrice(
         ctx: RequestContext,
         variantId: ID,
@@ -711,7 +692,6 @@ export class ProductVariantService {
         }
     }
 
-    @Span('ProductVariantService.softDelete')
     async softDelete(ctx: RequestContext, id: ID | ID[]): Promise<DeletionResponse> {
         const ids = Array.isArray(id) ? id : [id];
         const variants = await this.connection
@@ -735,7 +715,6 @@ export class ProductVariantService {
      *
      * Is optimized to make as few DB calls as possible using caching based on the open request.
      */
-    @Span('ProductVariantService.hydratePriceFields')
     async hydratePriceFields<F extends 'currencyCode' | 'price' | 'priceWithTax' | 'taxRateApplied'>(
         ctx: RequestContext,
         variant: ProductVariant,
@@ -782,7 +761,6 @@ export class ProductVariantService {
      * Given an array of ProductVariants from the database, this method will apply the correct price and tax
      * and translate each item.
      */
-    @Span('ProductVariantService.applyPricesAndTranslateVariants')
     private async applyPricesAndTranslateVariants(
         ctx: RequestContext,
         variants: ProductVariant[],
@@ -803,7 +781,6 @@ export class ProductVariantService {
      * @description
      * Populates the `price` field with the price for the specified channel.
      */
-    @Span('ProductVariantService.applyChannelPriceAndTax')
     async applyChannelPriceAndTax(
         variant: ProductVariant,
         ctx: RequestContext,
@@ -818,7 +795,6 @@ export class ProductVariantService {
      * Assigns the specified ProductVariants to the specified Channel. In doing so, it will create a new
      * {@link ProductVariantPrice} and also assign the associated Product and any Assets to the Channel too.
      */
-    @Span('ProductVariantService.assignProductVariantsToChannel')
     async assignProductVariantsToChannel(
         ctx: RequestContext,
         input: AssignProductVariantsToChannelInput,
@@ -869,7 +845,6 @@ export class ProductVariantService {
         return result;
     }
 
-    @Span('vendure.product-variant-service.remove-product-variants-from-channel')
     async removeProductVariantsFromChannel(
         ctx: RequestContext,
         input: RemoveProductVariantsFromChannelInput,
@@ -926,7 +901,6 @@ export class ProductVariantService {
         return result;
     }
 
-    @Span('vendure.product-variant-service.validate-variant-option-ids')
     private async validateVariantOptionIds(
         ctx: RequestContext,
         productId: ID,
@@ -991,7 +965,6 @@ export class ProductVariantService {
             .join(glue);
     }
 
-    @Span('vendure.product-variant-service.get-tax-category-for-new-variant')
     private async getTaxCategoryForNewVariant(
         ctx: RequestContext,
         taxCategoryId: ID | null | undefined,

+ 0 - 70
packages/core/src/service/services/product.service.ts

@@ -11,7 +11,6 @@ import {
 } from '@vendure/common/lib/generated-types';
 import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
 import { unique } from '@vendure/common/lib/unique';
-import { getActiveSpan } from '@vendure/telemetry';
 import { FindOptionsUtils, In, IsNull } from 'typeorm';
 
 import { RequestContext } from '../../api/common/request-context';
@@ -77,12 +76,6 @@ export class ProductService {
         options?: ListQueryOptions<Product>,
         relations?: RelationPaths<Product>,
     ): Promise<PaginatedList<Translated<Product>>> {
-        const span = getActiveSpan();
-        span?.setAttribute('channelId', ctx.channelId.toString());
-        span?.addEvent('channelId', {
-            channelId: ctx.channelId.toString(),
-        });
-
         const effectiveRelations = relations || this.relations.slice();
         const customPropertyMap: { [name: string]: string } = {};
         const hasFacetValueIdFilter = this.listQueryBuilder.filterObjectHasProperty<ProductFilterParameter>(
@@ -102,9 +95,6 @@ export class ProductService {
             customPropertyMap.sku = 'variants.sku';
         }
 
-        span?.setAttribute('hasFacetValueIdFilter', hasFacetValueIdFilter.toString());
-        span?.setAttribute('hasSkuFilter', hasSkuFilter.toString());
-
         return this.listQueryBuilder
             .build(Product, options, {
                 relations: effectiveRelations,
@@ -118,8 +108,6 @@ export class ProductService {
                 const items = products.map(product =>
                     this.translator.translate(product, ctx, ['facetValues', ['facetValues', 'facet']]),
                 );
-                span?.setAttribute('productsCount', products.length.toString());
-                span?.setAttribute('totalItems', totalItems.toString());
                 return {
                     items,
                     totalItems,
@@ -155,10 +143,6 @@ export class ProductService {
         productIds: ID[],
         relations?: RelationPaths<Product>,
     ): Promise<Array<Translated<Product>>> {
-        const span = getActiveSpan();
-        span?.setAttribute('productIds', productIds.join(','));
-        span?.setAttribute('channelId', ctx.channelId.toString());
-
         const qb = this.connection
             .getRepository(ctx, Product)
             .createQueryBuilder('product')
@@ -172,7 +156,6 @@ export class ProductService {
             .andWhere('channel.id = :channelId', { channelId: ctx.channelId })
             .getMany()
             .then(products => {
-                span?.setAttribute('foundCount', products.length.toString());
                 return products.map(product =>
                     this.translator.translate(product, ctx, ['facetValues', ['facetValues', 'facet']]),
                 );
@@ -184,21 +167,14 @@ export class ProductService {
      * Returns all Channels to which the Product is assigned.
      */
     async getProductChannels(ctx: RequestContext, productId: ID): Promise<Channel[]> {
-        const span = getActiveSpan();
-        span?.setAttribute('productId', productId.toString());
-
         const product = await this.connection.getEntityOrThrow(ctx, Product, productId, {
             relations: ['channels'],
             channelId: ctx.channelId,
         });
-        span?.setAttribute('channelsCount', product.channels.length.toString());
         return product.channels;
     }
 
     getFacetValuesForProduct(ctx: RequestContext, productId: ID): Promise<Array<Translated<FacetValue>>> {
-        const span = getActiveSpan();
-        span?.setAttribute('productId', productId.toString());
-
         return this.connection
             .getRepository(ctx, Product)
             .findOne({
@@ -207,11 +183,8 @@ export class ProductService {
             })
             .then(product => {
                 if (!product) {
-                    span?.setAttribute('found', 'false');
                     return [];
                 }
-                span?.setAttribute('found', 'true');
-                span?.setAttribute('facetValuesCount', product.facetValues.length.toString());
                 return product.facetValues.map(o => this.translator.translate(o, ctx, ['facet']));
             });
     }
@@ -221,10 +194,6 @@ export class ProductService {
         slug: string,
         relations?: RelationPaths<Product>,
     ): Promise<Translated<Product> | undefined> {
-        const span = getActiveSpan();
-        span?.setAttribute('slug', slug);
-        span?.setAttribute('channelId', ctx.channelId.toString());
-
         const qb = this.connection.getRepository(ctx, Product).createQueryBuilder('product');
         const translationQb = this.connection
             .getRepository(ctx, ProductTranslation)
@@ -248,18 +217,13 @@ export class ProductService {
         // all the joins etc.
         const result = await qb.getRawOne();
         if (result) {
-            span?.setAttribute('found', 'true');
             return this.findOne(ctx, result.id, relations);
         } else {
-            span?.setAttribute('found', 'false');
             return undefined;
         }
     }
 
     async create(ctx: RequestContext, input: CreateProductInput): Promise<Translated<Product>> {
-        const span = getActiveSpan();
-        span?.setAttribute('productName', input.translations?.[0]?.name || 'unnamed');
-
         await this.slugValidator.validateSlugs(ctx, input, ProductTranslation);
         const product = await this.translatableSaver.create({
             ctx,
@@ -278,14 +242,10 @@ export class ProductService {
         await this.assetService.updateEntityAssets(ctx, product, input);
         await this.eventBus.publish(new ProductEvent(ctx, product, 'created', input));
 
-        span?.setAttribute('newProductId', product.id.toString());
         return assertFound(this.findOne(ctx, product.id));
     }
 
     async update(ctx: RequestContext, input: UpdateProductInput): Promise<Translated<Product>> {
-        const span = getActiveSpan();
-        span?.setAttribute('productId', input.id.toString());
-
         const product = await this.connection.getEntityOrThrow(ctx, Product, input.id, {
             channelId: ctx.channelId,
             relations: ['facetValues', 'facetValues.channels'],
@@ -317,9 +277,6 @@ export class ProductService {
     }
 
     async softDelete(ctx: RequestContext, productId: ID): Promise<DeletionResponse> {
-        const span = getActiveSpan();
-        span?.setAttribute('productId', productId.toString());
-
         const product = await this.connection.getEntityOrThrow(ctx, Product, productId, {
             relationLoadStrategy: 'query',
             loadEagerRelations: false,
@@ -351,7 +308,6 @@ export class ProductService {
                 }
             }
         }
-        span?.setAttribute('result', DeletionResult.DELETED);
         return {
             result: DeletionResult.DELETED,
         };
@@ -369,11 +325,6 @@ export class ProductService {
         ctx: RequestContext,
         input: AssignProductsToChannelInput,
     ): Promise<Array<Translated<Product>>> {
-        const span = getActiveSpan();
-        span?.setAttribute('productIds', input.productIds.join(','));
-        span?.setAttribute('channelId', input.channelId.toString());
-        span?.setAttribute('productsCount', input.productIds.length.toString());
-
         const productsWithVariants = await this.connection.getRepository(ctx, Product).find({
             where: { id: In(input.productIds) },
             relations: ['variants', 'assets'],
@@ -405,11 +356,6 @@ export class ProductService {
         ctx: RequestContext,
         input: RemoveProductsFromChannelInput,
     ): Promise<Array<Translated<Product>>> {
-        const span = getActiveSpan();
-        span?.setAttribute('productIds', input.productIds.join(','));
-        span?.setAttribute('channelId', input.channelId.toString());
-        span?.setAttribute('productsCount', input.productIds.length.toString());
-
         const productsWithVariants = await this.connection.getRepository(ctx, Product).find({
             where: { id: In(input.productIds) },
             relations: ['variants'],
@@ -437,10 +383,6 @@ export class ProductService {
         productId: ID,
         optionGroupId: ID,
     ): Promise<Translated<Product>> {
-        const span = getActiveSpan();
-        span?.setAttribute('productId', productId.toString());
-        span?.setAttribute('optionGroupId', optionGroupId.toString());
-
         const product = await this.getProductWithOptionGroups(ctx, productId);
         const optionGroup = await this.connection.getRepository(ctx, ProductOptionGroup).findOne({
             where: { id: optionGroupId },
@@ -476,11 +418,6 @@ export class ProductService {
         optionGroupId: ID,
         force?: boolean,
     ): Promise<ErrorResultUnion<RemoveOptionGroupFromProductResult, Translated<Product>>> {
-        const span = getActiveSpan();
-        span?.setAttribute('productId', productId.toString());
-        span?.setAttribute('optionGroupId', optionGroupId.toString());
-        span?.setAttribute('force', Boolean(force).toString());
-
         const product = await this.getProductWithOptionGroups(ctx, productId);
         const optionGroup = product.optionGroups.find(g => idsAreEqual(g.id, optionGroupId));
         if (!optionGroup) {
@@ -526,9 +463,6 @@ export class ProductService {
     }
 
     private async getProductWithOptionGroups(ctx: RequestContext, productId: ID): Promise<Product> {
-        const span = getActiveSpan();
-        span?.setAttribute('productId', productId.toString());
-
         const product = await this.connection.getRepository(ctx, Product).findOne({
             relationLoadStrategy: 'query',
             loadEagerRelations: false,
@@ -536,12 +470,8 @@ export class ProductService {
             relations: ['optionGroups', 'variants', 'variants.options'],
         });
         if (!product) {
-            span?.setAttribute('found', 'false');
             throw new EntityNotFoundError('Product', productId);
         }
-        span?.setAttribute('found', 'true');
-        span?.setAttribute('optionGroupsCount', product.optionGroups.length.toString());
-        span?.setAttribute('variantsCount', product.variants.length.toString());
         return product;
     }
 }

+ 3 - 3
packages/core/src/service/services/promotion.service.ts

@@ -12,7 +12,6 @@ import {
     UpdatePromotionInput,
     UpdatePromotionResult,
 } from '@vendure/common/lib/generated-types';
-import { omit } from '@vendure/common/lib/omit';
 import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
 import { unique } from '@vendure/common/lib/unique';
 import { In, IsNull } from 'typeorm';
@@ -20,13 +19,14 @@ import { In, IsNull } from 'typeorm';
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
 import { ErrorResultUnion, JustErrorResults } from '../../common/error/error-result';
-import { IllegalOperationError, UserInputError } from '../../common/error/errors';
+import { UserInputError } from '../../common/error/errors';
 import { MissingConditionsError } from '../../common/error/generated-graphql-admin-errors';
 import {
     CouponCodeExpiredError,
     CouponCodeInvalidError,
     CouponCodeLimitError,
 } from '../../common/error/generated-graphql-shop-errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { AdjustmentSource } from '../../common/types/adjustment-source';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
@@ -45,7 +45,6 @@ import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-build
 import { OrderState } from '../helpers/order-state-machine/order-state';
 import { TranslatableSaver } from '../helpers/translatable-saver/translatable-saver';
 import { TranslatorService } from '../helpers/translator/translator.service';
-import { patchEntity } from '../helpers/utils/patch-entity';
 
 import { ChannelService } from './channel.service';
 
@@ -56,6 +55,7 @@ import { ChannelService } from './channel.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class PromotionService {
     availableConditions: PromotionCondition[] = [];
     availableActions: PromotionAction[] = [];

+ 2 - 0
packages/core/src/service/services/province.service.ts

@@ -9,6 +9,7 @@ import { ID, PaginatedList, Type } from '@vendure/common/lib/shared-types';
 
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { Translated } from '../../common/types/locale-types';
 import { assertFound } from '../../common/utils';
@@ -29,6 +30,7 @@ import { TranslatorService } from '../helpers/translator/translator.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class ProvinceService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 0
packages/core/src/service/services/role.service.ts

@@ -25,6 +25,7 @@ import {
     InternalServerError,
     UserInputError,
 } from '../../common/error/errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
 import { ConfigService } from '../../config/config.service';
@@ -50,6 +51,7 @@ import { ChannelService } from './channel.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class RoleService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 1
packages/core/src/service/services/seller.service.ts

@@ -8,6 +8,7 @@ import {
 import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
 
 import { RequestContext } from '../../api/common/request-context';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound } from '../../common/utils';
 import { TransactionalConnection } from '../../connection/transactional-connection';
@@ -16,7 +17,6 @@ import { EventBus, SellerEvent } from '../../event-bus/index';
 import { CustomFieldRelationService } from '../helpers/custom-field-relation/custom-field-relation.service';
 import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-builder';
 import { patchEntity } from '../helpers/utils/patch-entity';
-
 /**
  * @description
  * Contains methods relating to {@link Seller} entities.
@@ -24,6 +24,7 @@ import { patchEntity } from '../helpers/utils/patch-entity';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class SellerService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 0
packages/core/src/service/services/session.service.ts

@@ -5,6 +5,7 @@ import ms from 'ms';
 import { EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';
 
 import { RequestContext } from '../../api/common/request-context';
+import { Instrument } from '../../common/instrument-decorator';
 import { ConfigService } from '../../config/config.service';
 import { CachedSession, SessionCacheStrategy } from '../../config/session-cache/session-cache-strategy';
 import { TransactionalConnection } from '../../connection/transactional-connection';
@@ -26,6 +27,7 @@ import { OrderService } from './order.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class SessionService implements EntitySubscriberInterface {
     private sessionCacheStrategy: SessionCacheStrategy;
     private readonly sessionDurationInMs: number;

+ 2 - 0
packages/core/src/service/services/shipping-method.service.ts

@@ -16,6 +16,7 @@ import { IsNull } from 'typeorm';
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
 import { EntityNotFoundError, ForbiddenError, UserInputError } from '../../common/error/errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { Translated } from '../../common/types/locale-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
@@ -42,6 +43,7 @@ import { RoleService } from './role.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class ShippingMethodService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 0
packages/core/src/service/services/stock-level.service.ts

@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
 import { ID } from '@vendure/common/lib/shared-types';
 
 import { RequestContext } from '../../api/common/request-context';
+import { Instrument } from '../../common/instrument-decorator';
 import { AvailableStock } from '../../config/catalog/stock-location-strategy';
 import { ConfigService } from '../../config/config.service';
 import { TransactionalConnection } from '../../connection/transactional-connection';
@@ -20,6 +21,7 @@ import { StockLocationService } from './stock-location.service';
  * @since 2.0.0
  */
 @Injectable()
+@Instrument()
 export class StockLevelService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 0
packages/core/src/service/services/stock-location.service.ts

@@ -15,6 +15,7 @@ import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
 import { RequestContextCacheService } from '../../cache/request-context-cache.service';
 import { EntityNotFoundError, ForbiddenError, UserInputError } from '../../common/error/errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound, idsAreEqual } from '../../common/utils';
 import { ConfigService } from '../../config/config.service';
@@ -32,6 +33,7 @@ import { ChannelService } from './channel.service';
 import { RoleService } from './role.service';
 
 @Injectable()
+@Instrument()
 export class StockLocationService {
     constructor(
         private requestContextService: RequestContextService,

+ 3 - 3
packages/core/src/service/services/stock-movement.service.ts

@@ -9,13 +9,13 @@ import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
 import { In } from 'typeorm';
 
 import { RequestContext } from '../../api/common/request-context';
+import { Instrument } from '../../common/instrument-decorator';
 import { idsAreEqual } from '../../common/utils';
-import { ConfigService } from '../../config/config.service';
 import { ShippingCalculator } from '../../config/shipping-method/shipping-calculator';
 import { ShippingEligibilityChecker } from '../../config/shipping-method/shipping-eligibility-checker';
 import { TransactionalConnection } from '../../connection/transactional-connection';
-import { Order } from '../../entity/order/order.entity';
 import { OrderLine } from '../../entity/order-line/order-line.entity';
+import { Order } from '../../entity/order/order.entity';
 import { ProductVariant } from '../../entity/product-variant/product-variant.entity';
 import { ShippingMethod } from '../../entity/shipping-method/shipping-method.entity';
 import { Allocation } from '../../entity/stock-movement/allocation.entity';
@@ -39,6 +39,7 @@ import { StockLocationService } from './stock-location.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class StockMovementService {
     shippingEligibilityCheckers: ShippingEligibilityChecker[];
     shippingCalculators: ShippingCalculator[];
@@ -51,7 +52,6 @@ export class StockMovementService {
         private stockLevelService: StockLevelService,
         private eventBus: EventBus,
         private stockLocationService: StockLocationService,
-        private configService: ConfigService,
     ) {}
 
     /**

+ 6 - 1
packages/core/src/service/services/tag.service.ts

@@ -9,6 +9,7 @@ import { ID, PaginatedList, Type } from '@vendure/common/lib/shared-types';
 import { unique } from '@vendure/common/lib/unique';
 
 import { RequestContext } from '../../api/common/request-context';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions, Taggable } from '../../common/types/common-types';
 import { TransactionalConnection } from '../../connection/transactional-connection';
 import { VendureEntity } from '../../entity/base/base.entity';
@@ -22,8 +23,12 @@ import { ListQueryBuilder } from '../helpers/list-query-builder/list-query-build
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class TagService {
-    constructor(private connection: TransactionalConnection, private listQueryBuilder: ListQueryBuilder) {}
+    constructor(
+        private connection: TransactionalConnection,
+        private listQueryBuilder: ListQueryBuilder,
+    ) {}
 
     findAll(ctx: RequestContext, options?: ListQueryOptions<Tag>): Promise<PaginatedList<Tag>> {
         return this.listQueryBuilder

+ 2 - 0
packages/core/src/service/services/tax-category.service.ts

@@ -9,6 +9,7 @@ import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
 
 import { RequestContext } from '../../api/common/request-context';
 import { EntityNotFoundError } from '../../common/error/errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound } from '../../common/utils';
 import { TransactionalConnection } from '../../connection/transactional-connection';
@@ -26,6 +27,7 @@ import { patchEntity } from '../helpers/utils/patch-entity';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class TaxCategoryService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 0
packages/core/src/service/services/tax-rate.service.ts

@@ -10,6 +10,7 @@ import { ID, PaginatedList } from '@vendure/common/lib/shared-types';
 import { RequestContext } from '../../api/common/request-context';
 import { RelationPaths } from '../../api/decorators/relations.decorator';
 import { EntityNotFoundError } from '../../common/error/errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { createSelfRefreshingCache, SelfRefreshingCache } from '../../common/self-refreshing-cache';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound } from '../../common/utils';
@@ -33,6 +34,7 @@ import { patchEntity } from '../helpers/utils/patch-entity';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class TaxRateService {
     private readonly defaultTaxRate = new TaxRate({
         value: 0,

+ 2 - 0
packages/core/src/service/services/user.service.ts

@@ -18,6 +18,7 @@ import {
     VerificationTokenExpiredError,
     VerificationTokenInvalidError,
 } from '../../common/error/generated-graphql-shop-errors';
+import { Instrument } from '../../common/instrument-decorator';
 import { isEmailAddressLike, normalizeEmailAddress } from '../../common/utils';
 import { ConfigService } from '../../config/config.service';
 import { TransactionalConnection } from '../../connection/transactional-connection';
@@ -35,6 +36,7 @@ import { RoleService } from './role.service';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class UserService {
     constructor(
         private connection: TransactionalConnection,

+ 2 - 0
packages/core/src/service/services/zone.service.ts

@@ -12,6 +12,7 @@ import { unique } from '@vendure/common/lib/unique';
 import { In } from 'typeorm';
 
 import { RequestContext } from '../../api/common/request-context';
+import { Instrument } from '../../common/instrument-decorator';
 import { createSelfRefreshingCache, SelfRefreshingCache } from '../../common/self-refreshing-cache';
 import { ListQueryOptions } from '../../common/types/common-types';
 import { assertFound } from '../../common/utils';
@@ -34,6 +35,7 @@ import { patchEntity } from '../helpers/utils/patch-entity';
  * @docsCategory services
  */
 @Injectable()
+@Instrument()
 export class ZoneService {
     /**
      * We cache all Zones to avoid hitting the DB many times per request.