var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var otel_trace_exports = {};
__export(otel_trace_exports, {
  handler: () => handler,
  startSpanProcessor: () => startSpanProcessor
});
module.exports = __toCommonJS(otel_trace_exports);
var import_stringify = __toESM(require("@babel/runtime-corejs3/core-js/json/stringify"));
var import_keys = __toESM(require("@babel/runtime-corejs3/core-js/object/keys"));
var import_map = __toESM(require("@babel/runtime-corejs3/core-js/instance/map"));
var import_flags = __toESM(require("@babel/runtime-corejs3/core-js/instance/flags"));
var import_splice = __toESM(require("@babel/runtime-corejs3/core-js/instance/splice"));
var import_promise = __toESM(require("@babel/runtime-corejs3/core-js/promise"));
var import_set_interval = __toESM(require("@babel/runtime-corejs3/core-js/set-interval"));
var import_map2 = __toESM(require("@babel/runtime-corejs3/core-js/map"));
var import_node_crypto = __toESM(require("node:crypto"));
var import_realtime = require("@cedarjs/realtime");
var import_db = require("../../lib/db");
var import_logger = require("../../lib/logger");
var import_opentelemetry = require("../../lib/opentelemetry");
var import_store = require("@cedarjs/context/dist/store");
function getMD5Hash(value) {
  return import_node_crypto.default.createHash("md5").update((0, import_stringify.default)(value)).digest("hex");
}
function convertLongToBigInt(input) {
  if (typeof input === "string") {
    return BigInt(input);
  }
  const {
    low,
    high,
    unsigned
  } = input;
  const lowBI = BigInt.asUintN(32, BigInt(low));
  const highBI = BigInt.asUintN(32, BigInt(high));
  const combined = highBI << 32n | lowBI;
  return unsigned ? BigInt.asUintN(64, combined) : BigInt.asIntN(64, combined);
}
async function createAttribute(attribute) {
  const hash = getMD5Hash(attribute);
  const attributeId = (await import_db.db.oTelTraceAttribute.findUnique({
    where: {
      hash
    },
    select: {
      id: true
    }
  }))?.id;
  if (!attributeId) {
    const {
      id,
      createdAt,
      updatedAt
    } = (0, import_db.generateTypicalValues)();
    const attributeType = (0, import_keys.default)(attribute.value)[0];
    const attributeValue = (0, import_stringify.default)(attribute.value[attributeType]);
    const _rowsAffected = await import_db.db.$executeRaw`INSERT INTO OTelTraceAttribute (
      id,
      createdAt,
      updatedAt,
      [hash],
      [key],
      [value],
      [type]
    ) VALUES (
      ${id},
      ${createdAt},
      ${updatedAt},
      ${hash},
      ${attribute.key},
      ${attributeValue},
      ${attributeType.replace("Value", "")}
    ) ON CONFLICT ([hash]) DO NOTHING;`;
    const {
      id: createdId
    } = await import_db.db.oTelTraceAttribute.findUnique({
      where: {
        hash
      },
      select: {
        id: true
      }
    });
    return createdId;
  }
  return attributeId;
}
async function createResource(resource) {
  const resourceAttributesHash = getMD5Hash(resource.attributes);
  const existingResource = await import_db.db.oTelTraceResource.findUnique({
    where: {
      attributesHash: resourceAttributesHash
    },
    select: {
      id: true
    }
  });
  if (existingResource?.id) {
    return existingResource.id;
  }
  const attributeIds = [];
  for (let i = 0; i < resource.attributes.length; i++) {
    attributeIds.push(await createAttribute(resource.attributes[i]));
  }
  const resourceRow = await import_db.db.oTelTraceResource.upsert({
    where: {
      attributesHash: resourceAttributesHash
    },
    create: {
      attributesHash: resourceAttributesHash,
      attributes: {
        connect: (0, import_map.default)(attributeIds).call(attributeIds, (id) => ({
          id
        }))
      }
    },
    update: {
      // Do nothing
    },
    select: {
      id: true
    }
  });
  return resourceRow.id;
}
async function createScope(scope) {
  const attributeIds = [];
  if (scope.attributes !== void 0) {
    for (let i = 0; i < scope.attributes.length; i++) {
      attributeIds.push(await createAttribute(scope.attributes[i]));
    }
  }
  const version = scope.version ?? "__unversioned__";
  const scopeInDb = await import_db.db.oTelTraceScope.upsert({
    where: {
      OTelTraceScope_name_version_unique: {
        name: scope.name,
        version
      }
    },
    create: {
      name: scope.name,
      version,
      attributes: {
        connect: (0, import_map.default)(attributeIds).call(attributeIds, (id) => ({
          id
        }))
      }
    },
    update: {
      // Do nothing
    },
    select: {
      id: true
    }
  });
  return scopeInDb.id;
}
async function createSpan(span, resourceId, scopeId) {
  const attributeIds = [];
  if (span.attributes !== void 0) {
    for (let i = 0; i < span.attributes.length; i++) {
      attributeIds.push(await createAttribute(span.attributes[i]));
    }
  }
  const events = [];
  if (span.events !== void 0) {
    for (let i = 0; i < span.events.length; i++) {
      const event = span.events[i];
      const eventAttributeIds = [];
      if (event.attributes !== void 0) {
        for (let j = 0; j < event.attributes.length; j++) {
          eventAttributeIds.push(await createAttribute(event.attributes[j]));
        }
      }
      events.push({
        name: event.name,
        startTimeNano: convertLongToBigInt(event.timeUnixNano),
        attributes: {
          connect: (0, import_map.default)(eventAttributeIds).call(eventAttributeIds, (id) => ({
            id
          }))
        }
      });
    }
  }
  const links = [];
  if (span.links !== void 0) {
    for (let i = 0; i < span.links.length; i++) {
      const link = span.links[i];
      const linkAttributeIds = [];
      if (link.attributes !== void 0) {
        for (let j = 0; j < link.attributes.length; j++) {
          linkAttributeIds.push(await createAttribute(link.attributes[j]));
        }
      }
      links.push({
        spanId: link.spanId,
        traceId: link.traceId,
        traceState: link.traceState,
        flags: (0, import_flags.default)(link),
        attributes: {
          connect: (0, import_map.default)(linkAttributeIds).call(linkAttributeIds, (id) => ({
            id
          }))
        }
      });
    }
  }
  const {
    typeId: spanTypeId,
    brief: spanBrief
  } = await (0, import_opentelemetry.detectSpanTypeAndBrief)({
    name: span.name,
    attributes: span.attributes
  });
  await import_db.db.oTelTraceSpan.create({
    data: {
      typeId: spanTypeId,
      brief: spanBrief,
      traceId: span.traceId,
      traceState: span.traceState,
      spanId: span.spanId,
      parentId: span.parentSpanId,
      name: span.name,
      flags: (0, import_flags.default)(span),
      kind: span.kind,
      startTimeNano: convertLongToBigInt(span.startTimeUnixNano),
      endTimeNano: convertLongToBigInt(span.endTimeUnixNano),
      attributes: {
        connect: (0, import_map.default)(attributeIds).call(attributeIds, (id) => ({
          id
        }))
      },
      events: {
        create: events
      },
      links: {
        create: links
      },
      statusMessage: span.status.message,
      statusCode: span.status.code,
      resourceId,
      scopeId
    },
    select: {
      id: true
    }
  });
}
let spanProcessingInterval = null;
const spanDataQueue = [];
const startSpanProcessor = async () => {
  import_logger.logger.info("Starting OpenTelemetry span processor");
  if (spanProcessingInterval) {
    clearInterval(spanProcessingInterval);
  }
  const processSpanBatch = async () => {
    if (spanDataQueue.length === 0) {
      return;
    }
    const spans = (0, import_splice.default)(spanDataQueue).call(spanDataQueue, 0, spanDataQueue.length);
    await import_promise.default.allSettled((0, import_map.default)(spans).call(spans, processSpan));
    await import_realtime.liveQueryStore?.invalidate("Query.otelSpans");
    await import_realtime.liveQueryStore?.invalidate("Query.otelTraces");
    await import_realtime.liveQueryStore?.invalidate("Query.otelSpanCount");
    await import_realtime.liveQueryStore?.invalidate("Query.otelTraceCount");
    import_logger.logger.info(`Processed ${spans.length} OpenTelemetry spans`);
  };
  spanProcessingInterval = (0, import_set_interval.default)(processSpanBatch, 1e3);
};
const processSpan = async (body) => {
  const {
    resourceSpans
  } = JSON.parse(body);
  for (let i = 0; i < resourceSpans.length; i++) {
    const resourceId = await createResource(resourceSpans[i].resource);
    const scopeSpans = resourceSpans[i].scopeSpans;
    for (let j = 0; j < scopeSpans.length; j++) {
      const scopeId = await createScope(scopeSpans[j].scope);
      const spans = scopeSpans[j].spans;
      for (let k = 0; k < spans.length; k++) {
        try {
          await createSpan(spans[k], resourceId, scopeId);
        } catch (error) {
          import_logger.logger.error("Failed to ingest span");
          import_logger.logger.error(error);
        }
      }
      import_logger.logger.debug(`Ingested ${spans.length} OpenTelemetry spans`);
    }
  }
};
const __rw_handler = async (event, _context) => {
  spanDataQueue.push(event.body);
  return {
    statusCode: 200,
    headers: {
      "Content-Type": "application/json"
    },
    body: "{}"
  };
};
const handler = async (__rw_event, __rw__context) => {
  const __rw_contextStore = (0, import_store.getAsyncStoreInstance)().getStore();
  if (__rw_contextStore === void 0) {
    return (0, import_store.getAsyncStoreInstance)().run(new import_map2.default(), __rw_handler, __rw_event, __rw__context);
  }
  return __rw_handler(__rw_event, __rw__context);
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  handler,
  startSpanProcessor
});
//# sourceMappingURL=otel-trace.js.map
