'use strict';

var chunkXUAWHRUO_cjs = require('./chunk-XUAWHRUO.cjs');
var chunkC73WLCY3_cjs = require('./chunk-C73WLCY3.cjs');
var api = require('@opentelemetry/api');
var core = require('@opentelemetry/core');
var otlpTransformer = require('@opentelemetry/otlp-transformer');

function hasActiveTelemetry(tracerName = "default-tracer") {
  try {
    return !!api.trace.getTracer(tracerName);
  } catch {
    return false;
  }
}
function getBaggageValues(ctx) {
  const currentBaggage = api.propagation.getBaggage(ctx);
  const requestId = currentBaggage?.getEntry("http.request_id")?.value;
  const componentName = currentBaggage?.getEntry("componentName")?.value;
  const runId = currentBaggage?.getEntry("runId")?.value;
  const threadId = currentBaggage?.getEntry("threadId")?.value;
  const resourceId = currentBaggage?.getEntry("resourceId")?.value;
  return {
    requestId,
    componentName,
    runId,
    threadId,
    resourceId
  };
}

// src/telemetry/telemetry.decorators.ts
function isStreamingResult(result, methodName) {
  if (methodName === "stream" || methodName === "streamVNext") {
    return true;
  }
  if (result && typeof result === "object" && result !== null) {
    const obj = result;
    return "textStream" in obj || "objectStream" in obj || "usagePromise" in obj || "finishReasonPromise" in obj;
  }
  return false;
}
function enhanceStreamingArgumentsWithTelemetry(args, span, spanName, methodName) {
  if (methodName === "stream" || methodName === "streamVNext") {
    const enhancedArgs = [...args];
    const streamOptions = enhancedArgs.length > 1 && enhancedArgs[1] || {};
    const enhancedStreamOptions = { ...streamOptions };
    const originalOnFinish = enhancedStreamOptions.onFinish;
    enhancedStreamOptions.onFinish = async (finishData) => {
      try {
        const telemetryData = {
          text: finishData.text,
          usage: finishData.usage,
          finishReason: finishData.finishReason,
          toolCalls: finishData.toolCalls,
          toolResults: finishData.toolResults,
          warnings: finishData.warnings,
          ...finishData.object !== void 0 && { object: finishData.object }
        };
        span.setAttribute(`${spanName}.result`, JSON.stringify(telemetryData));
        span.setStatus({ code: api.SpanStatusCode.OK });
        span.end();
      } catch (error) {
        debugger;
        console.warn("Telemetry capture failed:", error);
        span.setAttribute(`${spanName}.result`, "[Telemetry Capture Error]");
        span.setStatus({ code: api.SpanStatusCode.ERROR });
        span.end();
      }
      if (originalOnFinish) {
        return await originalOnFinish(finishData);
      }
    };
    enhancedArgs[1] = enhancedStreamOptions;
    span.__mastraStreamingSpan = true;
    return enhancedArgs;
  }
  return args;
}
function withSpan(options) {
  return function(_target, propertyKey, descriptor) {
    if (!descriptor || typeof descriptor === "number") return;
    const originalMethod = descriptor.value;
    const methodName = String(propertyKey);
    descriptor.value = function(...args) {
      if (options?.skipIfNoTelemetry && !hasActiveTelemetry(options?.tracerName)) {
        return originalMethod.apply(this, args);
      }
      const tracer = api.trace.getTracer(options?.tracerName ?? "default-tracer");
      let spanName;
      let spanKind;
      if (typeof options === "string") {
        spanName = options;
      } else if (options) {
        spanName = options.spanName || methodName;
        spanKind = options.spanKind;
      } else {
        spanName = methodName;
      }
      const span = tracer.startSpan(spanName, { kind: spanKind });
      let ctx = api.trace.setSpan(api.context.active(), span);
      args.forEach((arg, index) => {
        try {
          span.setAttribute(`${spanName}.argument.${index}`, JSON.stringify(arg));
        } catch {
          span.setAttribute(`${spanName}.argument.${index}`, "[Not Serializable]");
        }
      });
      const { requestId, componentName, runId, threadId, resourceId } = getBaggageValues(ctx);
      if (requestId) {
        span.setAttribute("http.request_id", requestId);
      }
      if (threadId) {
        span.setAttribute("threadId", threadId);
      }
      if (resourceId) {
        span.setAttribute("resourceId", resourceId);
      }
      if (componentName) {
        span.setAttribute("componentName", componentName);
        span.setAttribute("runId", runId);
      } else if (this && typeof this === "object" && "name" in this) {
        const contextObj = this;
        span.setAttribute("componentName", contextObj.name);
        if (contextObj.runId) {
          span.setAttribute("runId", contextObj.runId);
        }
        ctx = api.propagation.setBaggage(
          ctx,
          api.propagation.createBaggage({
            // @ts-ignore
            componentName: { value: this.name },
            // @ts-ignore
            runId: { value: this.runId },
            // @ts-ignore
            "http.request_id": { value: requestId },
            // @ts-ignore
            threadId: { value: threadId },
            // @ts-ignore
            resourceId: { value: resourceId }
          })
        );
      }
      let result;
      try {
        const enhancedArgs = isStreamingResult(result, methodName) ? enhanceStreamingArgumentsWithTelemetry(args, span, spanName, methodName) : args;
        result = api.context.with(ctx, () => originalMethod.apply(this, enhancedArgs));
        if (result instanceof Promise) {
          return result.then((resolvedValue) => {
            if (isStreamingResult(resolvedValue, methodName)) {
              return resolvedValue;
            } else {
              try {
                span.setAttribute(`${spanName}.result`, JSON.stringify(resolvedValue));
              } catch {
                span.setAttribute(`${spanName}.result`, "[Not Serializable]");
              }
              return resolvedValue;
            }
          }).finally(() => {
            if (!span.__mastraStreamingSpan) {
              span.end();
            }
          });
        }
        if (!isStreamingResult(result, methodName)) {
          try {
            span.setAttribute(`${spanName}.result`, JSON.stringify(result));
          } catch {
            span.setAttribute(`${spanName}.result`, "[Not Serializable]");
          }
        }
        return result;
      } catch (error) {
        span.setStatus({
          code: api.SpanStatusCode.ERROR,
          message: error instanceof Error ? error.message : "Unknown error"
        });
        if (error instanceof Error) {
          span.recordException(error);
        }
        throw error;
      } finally {
        if (!(result instanceof Promise) && !isStreamingResult(result, methodName)) {
          span.end();
        }
      }
    };
    return descriptor;
  };
}
function InstrumentClass(options) {
  return function(target) {
    const methods = Object.getOwnPropertyNames(target.prototype);
    methods.forEach((method) => {
      if (options?.excludeMethods?.includes(method) || method === "constructor") return;
      if (options?.methodFilter && !options.methodFilter(method)) return;
      const descriptor = Object.getOwnPropertyDescriptor(target.prototype, method);
      if (descriptor && typeof descriptor.value === "function") {
        Object.defineProperty(
          target.prototype,
          method,
          withSpan({
            spanName: options?.prefix ? `${options.prefix}.${method}` : method,
            skipIfNoTelemetry: true,
            spanKind: options?.spanKind || api.SpanKind.INTERNAL,
            tracerName: options?.tracerName
          })(target, method, descriptor)
        );
      }
    });
    return target;
  };
}
var OTLPTraceExporter = class {
  storage;
  queue = [];
  serializer;
  logger;
  activeFlush = void 0;
  constructor({ logger, storage }) {
    this.storage = storage;
    this.serializer = otlpTransformer.JsonTraceSerializer;
    this.logger = logger;
  }
  export(internalRepresentation, resultCallback) {
    const serializedRequest = this.serializer.serializeRequest(internalRepresentation);
    const payload = JSON.parse(Buffer.from(serializedRequest.buffer, "utf8"));
    const items = payload?.resourceSpans?.[0]?.scopeSpans;
    this.logger.debug(`Exporting telemetry: ${items.length} scope spans to be processed [trace batch]`);
    this.queue.push({ data: items, resultCallback });
    if (!this.activeFlush) {
      this.activeFlush = this.flush();
    }
  }
  shutdown() {
    return this.forceFlush();
  }
  flush() {
    const now = /* @__PURE__ */ new Date();
    const items = this.queue.shift();
    if (!items) return Promise.resolve();
    const allSpans = items.data.reduce((acc, scopedSpans) => {
      const { scope, spans } = scopedSpans;
      for (const span of spans) {
        const {
          spanId,
          parentSpanId,
          traceId,
          name,
          kind,
          attributes,
          status,
          events,
          links,
          startTimeUnixNano,
          endTimeUnixNano,
          ...rest
        } = span;
        const startTime = Number(BigInt(startTimeUnixNano) / 1000n);
        const endTime = Number(BigInt(endTimeUnixNano) / 1000n);
        acc.push({
          id: spanId,
          parentSpanId,
          traceId,
          name,
          scope: scope.name,
          kind,
          status: JSON.stringify(status),
          events: JSON.stringify(events),
          links: JSON.stringify(links),
          attributes: JSON.stringify(
            attributes.reduce((acc2, attr) => {
              const valueKey = Object.keys(attr.value)[0];
              if (valueKey) {
                acc2[attr.key] = attr.value[valueKey];
              }
              return acc2;
            }, {})
          ),
          startTime,
          endTime,
          other: JSON.stringify(rest),
          createdAt: now
        });
      }
      return acc;
    }, []);
    return this.storage.batchInsert({
      tableName: chunkXUAWHRUO_cjs.TABLE_TRACES,
      records: allSpans
    }).then(() => {
      items.resultCallback({
        code: core.ExportResultCode.SUCCESS
      });
    }).catch((e) => {
      const mastraError = new chunkC73WLCY3_cjs.MastraError(
        {
          id: "OTLP_TRACE_EXPORT_FAILURE",
          text: "Failed to export telemetry spans",
          domain: "MASTRA_TELEMETRY" /* MASTRA_TELEMETRY */,
          category: "SYSTEM" /* SYSTEM */,
          details: {
            attemptedSpanCount: allSpans.length,
            targetTable: chunkXUAWHRUO_cjs.TABLE_TRACES,
            firstSpanName: allSpans.length > 0 ? allSpans[0].name : "",
            firstSpanKind: allSpans.length > 0 ? allSpans[0].kind : "",
            firstSpanScope: allSpans.length > 0 ? allSpans[0].scope : ""
          }
        },
        e
      );
      this.logger.trackException(mastraError);
      this.logger.error("span err:" + mastraError.toString());
      items.resultCallback({
        code: core.ExportResultCode.FAILED,
        error: e
      });
    }).finally(() => {
      this.activeFlush = void 0;
    });
  }
  async forceFlush() {
    if (!this.queue.length) {
      return;
    }
    await this.activeFlush;
    while (this.queue.length) {
      await this.flush();
    }
  }
  __setLogger(logger) {
    this.logger = logger;
  }
};
var Telemetry = class _Telemetry {
  tracer = api.trace.getTracer("default");
  name = "default-service";
  constructor(config) {
    this.name = config.serviceName ?? "default-service";
    this.tracer = api.trace.getTracer(this.name);
  }
  /**
   * @deprecated This method does not do anything
   */
  async shutdown() {
  }
  /**
   * Initialize telemetry with the given configuration
   * @param config - Optional telemetry configuration object
   * @returns Telemetry instance that can be used for tracing
   */
  static init(config = {}) {
    try {
      if (!globalThis.__TELEMETRY__) {
        globalThis.__TELEMETRY__ = new _Telemetry(config);
      }
      return globalThis.__TELEMETRY__;
    } catch (error) {
      const wrappedError = new chunkC73WLCY3_cjs.MastraError(
        {
          id: "TELEMETRY_INIT_FAILED",
          text: "Failed to initialize telemetry",
          domain: "MASTRA_TELEMETRY" /* MASTRA_TELEMETRY */,
          category: "SYSTEM" /* SYSTEM */
        },
        error
      );
      throw wrappedError;
    }
  }
  static getActiveSpan() {
    const span = api.trace.getActiveSpan();
    return span;
  }
  /**
   * Get the global telemetry instance
   * @throws {Error} If telemetry has not been initialized
   * @returns {Telemetry} The global telemetry instance
   */
  static get() {
    if (!globalThis.__TELEMETRY__) {
      throw new chunkC73WLCY3_cjs.MastraError({
        id: "TELEMETRY_GETTER_FAILED_GLOBAL_TELEMETRY_NOT_INITIALIZED",
        text: "Telemetry not initialized",
        domain: "MASTRA_TELEMETRY" /* MASTRA_TELEMETRY */,
        category: "USER" /* USER */
      });
    }
    return globalThis.__TELEMETRY__;
  }
  /**
   * Wraps a class instance with telemetry tracing
   * @param instance The class instance to wrap
   * @param options Optional configuration for tracing
   * @returns Wrapped instance with all methods traced
   */
  traceClass(instance, options = {}) {
    const { skipIfNoTelemetry = true } = options;
    if (skipIfNoTelemetry && !hasActiveTelemetry()) {
      return instance;
    }
    const { spanNamePrefix = instance.constructor.name.toLowerCase(), attributes = {}, excludeMethods = [] } = options;
    return new Proxy(instance, {
      get: (target, prop) => {
        const value = target[prop];
        if (typeof value === "function" && prop !== "constructor" && !prop.toString().startsWith("_") && !excludeMethods.includes(prop.toString())) {
          return this.traceMethod(value.bind(target), {
            spanName: `${spanNamePrefix}.${prop.toString()}`,
            attributes: {
              ...attributes,
              [`${spanNamePrefix}.name`]: target.constructor.name,
              [`${spanNamePrefix}.method.name`]: prop.toString()
            }
          });
        }
        return value;
      }
    });
  }
  static setBaggage(baggage, ctx = api.context.active()) {
    const currentBaggage = Object.fromEntries(api.propagation.getBaggage(ctx)?.getAllEntries() ?? []);
    const newCtx = api.propagation.setBaggage(
      ctx,
      api.propagation.createBaggage({
        ...currentBaggage,
        ...baggage
      })
    );
    return newCtx;
  }
  static withContext(ctx, fn) {
    return api.context.with(ctx, fn);
  }
  /**
   * method to trace individual methods with proper context
   * @param method The method to trace
   * @param context Additional context for the trace
   * @returns Wrapped method with tracing
   */
  traceMethod(method, context3) {
    let ctx = api.context.active();
    const { skipIfNoTelemetry = true } = context3;
    if (skipIfNoTelemetry && !hasActiveTelemetry()) {
      return method;
    }
    return (...args) => {
      const span = this.tracer.startSpan(context3.spanName);
      function handleError(error) {
        span.recordException(error);
        span.setStatus({
          code: api.SpanStatusCode.ERROR,
          message: error.message
        });
        span.end();
        throw error;
      }
      try {
        let recordResult2 = function(res) {
          try {
            span.setAttribute(`${context3.spanName}.result`, JSON.stringify(res));
          } catch {
            span.setAttribute(`${context3.spanName}.result`, "[Not Serializable]");
          }
          span.end();
          return res;
        };
        const { requestId, componentName, runId, threadId, resourceId } = getBaggageValues(ctx);
        if (context3.attributes) {
          span.setAttributes(context3.attributes);
        }
        if (requestId) {
          span.setAttribute("http.request_id", requestId);
        }
        if (threadId) {
          span.setAttribute("threadId", threadId);
        }
        if (resourceId) {
          span.setAttribute("resourceId", resourceId);
        }
        if (context3.attributes?.componentName) {
          ctx = api.propagation.setBaggage(
            ctx,
            api.propagation.createBaggage({
              componentName: { value: context3.attributes.componentName },
              // @ts-ignore
              runId: { value: context3.attributes.runId },
              // @ts-ignore
              "http.request_id": { value: requestId }
            })
          );
        } else {
          if (componentName) {
            span.setAttribute("componentName", componentName);
            span.setAttribute("runId", runId);
          } else if (this && this.name) {
            span.setAttribute("componentName", this.name);
            span.setAttribute("runId", this.runId);
            ctx = api.propagation.setBaggage(
              ctx,
              api.propagation.createBaggage({
                componentName: { value: this.name },
                // @ts-ignore
                runId: { value: this.runId },
                // @ts-ignore
                "http.request_id": { value: requestId },
                // @ts-ignore
                threadId: { value: threadId },
                // @ts-ignore
                resourceId: { value: resourceId }
              })
            );
          }
        }
        args.forEach((arg, index) => {
          try {
            span.setAttribute(`${context3.spanName}.argument.${index}`, JSON.stringify(arg));
          } catch {
            span.setAttribute(`${context3.spanName}.argument.${index}`, "[Not Serializable]");
          }
        });
        let result;
        api.context.with(api.trace.setSpan(ctx, span), () => {
          result = method(...args);
        });
        if (result instanceof Promise) {
          return result.then(recordResult2).catch(handleError);
        } else {
          return recordResult2(result);
        }
      } catch (error) {
        handleError(error);
      }
    };
  }
  getBaggageTracer() {
    return new BaggageTracer(this.tracer);
  }
};
var BaggageTracer = class {
  _tracer;
  constructor(tracer) {
    this._tracer = tracer;
  }
  startSpan(name, options = {}, ctx) {
    ctx = ctx ?? api.context.active();
    const span = this._tracer.startSpan(name, options, ctx);
    const { componentName, runId, requestId, threadId, resourceId } = getBaggageValues(ctx);
    span.setAttribute("componentName", componentName);
    span.setAttribute("runId", runId);
    span.setAttribute("http.request_id", requestId);
    span.setAttribute("threadId", threadId);
    span.setAttribute("resourceId", resourceId);
    return span;
  }
  startActiveSpan(name, optionsOrFn, ctxOrFn, fn) {
    if (typeof optionsOrFn === "function") {
      const wrappedFn2 = (span) => {
        const { componentName, runId, requestId, threadId, resourceId } = getBaggageValues(api.context.active());
        span.setAttribute("componentName", componentName);
        span.setAttribute("runId", runId);
        span.setAttribute("http.request_id", requestId);
        span.setAttribute("threadId", threadId);
        span.setAttribute("resourceId", resourceId);
        return optionsOrFn(span);
      };
      return this._tracer.startActiveSpan(name, {}, api.context.active(), wrappedFn2);
    }
    if (typeof ctxOrFn === "function") {
      const wrappedFn2 = (span) => {
        const { componentName, runId, requestId, threadId, resourceId } = getBaggageValues(api.context.active());
        span.setAttribute("componentName", componentName);
        span.setAttribute("runId", runId);
        span.setAttribute("http.request_id", requestId);
        span.setAttribute("threadId", threadId);
        span.setAttribute("resourceId", resourceId);
        return ctxOrFn(span);
      };
      return this._tracer.startActiveSpan(name, optionsOrFn, api.context.active(), wrappedFn2);
    }
    const wrappedFn = (span) => {
      const { componentName, runId, requestId, threadId, resourceId } = getBaggageValues(
        ctxOrFn ?? api.context.active()
      );
      span.setAttribute("componentName", componentName);
      span.setAttribute("runId", runId);
      span.setAttribute("http.request_id", requestId);
      span.setAttribute("threadId", threadId);
      span.setAttribute("resourceId", resourceId);
      return fn(span);
    };
    return this._tracer.startActiveSpan(name, optionsOrFn, ctxOrFn, wrappedFn);
  }
};

exports.InstrumentClass = InstrumentClass;
exports.OTLPTraceExporter = OTLPTraceExporter;
exports.Telemetry = Telemetry;
exports.getBaggageValues = getBaggageValues;
exports.hasActiveTelemetry = hasActiveTelemetry;
exports.withSpan = withSpan;
//# sourceMappingURL=chunk-ZOU4K5MI.cjs.map
//# sourceMappingURL=chunk-ZOU4K5MI.cjs.map