var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import OneUptimeDate from "../../Types/Date";
import ObjectID from "../../Types/ObjectID";
import Metric, { AggregationTemporality, } from "../../Models/AnalyticsModels/Metric";
import Service from "../../Models/DatabaseModels/Service";
import ProjectService from "../../Server/Services/ProjectService";
import ServiceService from "../../Server/Services/ServiceService";
import LabelService from "../../Server/Services/LabelService";
import { DEFAULT_RETENTION_IN_DAYS } from "../../Models/DatabaseModels/TelemetryUsageBilling";
import TelemetryUtil from "../../Server/Utils/Telemetry/Telemetry";
import { extractOneuptimeLabelNames } from "../Utils/Telemetry/OneuptimeLabel";
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
import SortOrder from "../../Types/BaseDatabase/SortOrder";
import QueryHelper from "../Types/Database/QueryHelper";
import logger from "../Utils/Logger";
import ServiceType from "../../Types/Telemetry/ServiceType";
import HostService from "./HostService";
import DockerHostService from "./DockerHostService";
import KubernetesClusterService from "./KubernetesClusterService";
import ServerlessFunctionService from "./ServerlessFunctionService";
import CloudResourceService from "./CloudResourceService";
import RumApplicationService from "./RumApplicationService";
import GlobalCache from "../Infrastructure/GlobalCache";
import ColumnLength from "../../Types/Database/ColumnLength";
import EntityType from "../../Types/Telemetry/EntityType";
import { reconcileEntityRegistryThrottled } from "../Utils/Telemetry/EntityRegistry";
import { keyForService, canonicalizeEntityValue, } from "../../Utils/Telemetry/EntityKey";
export var OtelAggregationTemporality;
(function (OtelAggregationTemporality) {
    OtelAggregationTemporality["Cumulative"] = "AGGREGATION_TEMPORALITY_CUMULATIVE";
    OtelAggregationTemporality["Delta"] = "AGGREGATION_TEMPORALITY_DELTA";
})(OtelAggregationTemporality || (OtelAggregationTemporality = {}));
export function emptyScalarEntityKeys() {
    return {
        serviceEntityKey: "",
        hostEntityKey: "",
        k8sPodEntityKey: "",
        k8sNodeEntityKey: "",
        k8sClusterEntityKey: "",
        containerEntityKey: "",
    };
}
/**
 * The six scalar entity-key columns for a signal row, defaulting every
 * field to '' when the metadata carries no scalar map (e.g. a resolver
 * path that never saw resource attributes). Spread the result into the
 * row object so every signal row always carries all six columns.
 */
export function getScalarEntityKeyColumns(metadata) {
    var _a;
    return (_a = metadata === null || metadata === void 0 ? void 0 : metadata.scalarEntityKeys) !== null && _a !== void 0 ? _a : emptyScalarEntityKeys();
}
const PROJECT_RETENTION_CACHE_NAMESPACE = "project-retention-context";
/*
 * 5-minute TTL is long enough that steady-state ingest sees ~100%
 * cache hits and short enough that an admin retention change in
 * the UI propagates without us having to wire up cross-process
 * invalidation (which would need pub/sub — GlobalCache has no
 * delete primitive today). Admins changing retention should
 * expect up to 5 minutes of lag before new rows pick up the new
 * config; existing rows keep whatever retentionDate they were
 * stamped with at ingest time and aren't affected either way.
 */
const PROJECT_RETENTION_CACHE_TTL_SECONDS = 5 * 60;
const projectRetentionInProcessCache = new Map();
export default class OTelIngestService {
    /*
     * Read a single string-valued OTel resource attribute out of the raw
     * OTLP attribute array (shape: [{ key, value: { stringValue } }]).
     * Mirrors OtelIngestBaseService.getStringAttribute — duplicated here
     * because that one is on the ingest-side base class and this read path
     * (Service resolution) lives in Common.
     */
    static getResourceStringAttribute(attributes, key) {
        for (const attribute of attributes) {
            if (attribute["key"] === key &&
                attribute["value"] &&
                attribute["value"]["stringValue"]) {
                const value = attribute["value"]["stringValue"];
                if (typeof value === "string" && value.trim()) {
                    return value.trim();
                }
            }
        }
        return null;
    }
    /*
     * Truncate to the Service column width (ColumnLength.ShortText) so a
     * pathological over-long resource attribute can't fail the UPDATE — a
     * throw there would leave the throttle fingerprint cached and freeze
     * lastSeenAt refreshes for the rest of the throttle window.
     */
    static clampServiceMetadataValue(value) {
        if (!value) {
            return undefined;
        }
        return value.slice(0, ColumnLength.ShortText);
    }
    /*
     * Build the metadata captured onto the Service row from OTel resource
     * attributes (service.version, deployment.environment, cloud.*, runtime.*).
     * Returns undefined when no resource attributes are available so the
     * caller falls back to a plain lastSeenAt touch.
     */
    static buildServiceMetadataFromAttributes(attributes) {
        var _a;
        if (!attributes) {
            return undefined;
        }
        return {
            serviceVersion: this.clampServiceMetadataValue(this.getResourceStringAttribute(attributes, "service.version")),
            deploymentEnvironment: this.clampServiceMetadataValue(this.getResourceStringAttribute(attributes, "deployment.environment.name") ||
                this.getResourceStringAttribute(attributes, "deployment.environment")),
            serviceNamespace: this.clampServiceMetadataValue(this.getResourceStringAttribute(attributes, "service.namespace")),
            runtimeName: this.clampServiceMetadataValue(this.getResourceStringAttribute(attributes, "process.runtime.name")),
            runtimeVersion: this.clampServiceMetadataValue(this.getResourceStringAttribute(attributes, "process.runtime.version")),
            telemetrySdkLanguage: this.clampServiceMetadataValue((_a = this.getResourceStringAttribute(attributes, "telemetry.sdk.language")) === null || _a === void 0 ? void 0 : _a.toLowerCase()),
            cloudProvider: this.clampServiceMetadataValue(this.getResourceStringAttribute(attributes, "cloud.provider")),
            cloudPlatform: this.clampServiceMetadataValue(this.getResourceStringAttribute(attributes, "cloud.platform")),
            cloudRegion: this.clampServiceMetadataValue(this.getResourceStringAttribute(attributes, "cloud.region")),
            cloudAccountId: this.clampServiceMetadataValue(this.getResourceStringAttribute(attributes, "cloud.account.id")),
        };
    }
    static async getProjectRetentionContext(projectId) {
        var _a, _b, _c;
        const projectIdStr = projectId.toString();
        const now = Date.now();
        // L1: in-process memo. Zero network cost.
        const memoed = projectRetentionInProcessCache.get(projectIdStr);
        if (memoed && memoed.expiresAtMs > now) {
            return memoed.context;
        }
        // L2: Redis. Single round-trip; shared across workers.
        try {
            const cached = await GlobalCache.getJSONObject(PROJECT_RETENTION_CACHE_NAMESPACE, projectIdStr);
            if (cached) {
                const context = {
                    projectRetentionConfig: (_a = cached["projectRetentionConfig"]) !== null && _a !== void 0 ? _a : null,
                    projectRetentionInDays: cached["projectRetentionInDays"] ||
                        DEFAULT_RETENTION_IN_DAYS,
                };
                projectRetentionInProcessCache.set(projectIdStr, {
                    context,
                    expiresAtMs: now + PROJECT_RETENTION_CACHE_TTL_SECONDS * 1000,
                });
                return context;
            }
        }
        catch (err) {
            // Cache outage must never fail ingest. Fall through to Postgres.
            logger.warn(`Project retention cache read failed for project ${projectIdStr}; falling back to Postgres: ${err instanceof Error ? err.message : String(err)}`);
        }
        // Cold path: hit Postgres and warm both caches.
        const project = await ProjectService.findOneById({
            id: projectId,
            select: {
                defaultTelemetryRetentionInDays: true,
                telemetryRetentionConfig: true,
            },
            props: {
                isRoot: true,
            },
        });
        const context = {
            projectRetentionConfig: (_b = project === null || project === void 0 ? void 0 : project.telemetryRetentionConfig) !== null && _b !== void 0 ? _b : null,
            projectRetentionInDays: (project === null || project === void 0 ? void 0 : project.defaultTelemetryRetentionInDays) || DEFAULT_RETENTION_IN_DAYS,
        };
        projectRetentionInProcessCache.set(projectIdStr, {
            context,
            expiresAtMs: now + PROJECT_RETENTION_CACHE_TTL_SECONDS * 1000,
        });
        try {
            await GlobalCache.setJSON(PROJECT_RETENTION_CACHE_NAMESPACE, projectIdStr, {
                projectRetentionConfig: ((_c = context.projectRetentionConfig) !== null && _c !== void 0 ? _c : null),
                projectRetentionInDays: context.projectRetentionInDays,
            }, { expiresInSeconds: PROJECT_RETENTION_CACHE_TTL_SECONDS });
        }
        catch (err) {
            // Best-effort warm. Don't fail the request.
            logger.warn(`Project retention cache write failed for project ${projectIdStr}: ${err instanceof Error ? err.message : String(err)}`);
        }
        return context;
    }
    static async telemetryServiceFromName(data) {
        const result = await this.findOrCreateTelemetryService({
            serviceName: data.serviceName,
            projectId: data.projectId,
        });
        /*
         * Name-only sources (syslog / fluent) never go through
         * `resolveTelemetryResource`, so its extractor never registers this
         * service. Reconcile the single Service entity here, under the same
         * fence/throttle machinery. OTLP batches (resourceAttributes present)
         * reconcile their full entity set — including the service.namespace
         * identity this name-only path cannot see — in
         * `resolveTelemetryResource` instead. Fire-and-forget: all errors are
         * swallowed inside, so the registry can never break ingest.
         */
        if (!data.resourceAttributes) {
            const serviceEntity = {
                entityType: EntityType.Service,
                entityKey: keyForService(data.projectId.toString(), data.serviceName),
                identifyingAttributes: {
                    "service.name": canonicalizeEntityValue(data.serviceName),
                },
            };
            void reconcileEntityRegistryThrottled({
                projectId: data.projectId,
                entities: [serviceEntity],
            });
        }
        /*
         * Touch `lastSeenAt` on the service. Throttled per-service inside
         * ServiceService.updateLastSeen so the steady-state firehose costs
         * one in-memory cache lookup per batch.
         */
        try {
            await ServiceService.updateLastSeen(result.primaryEntityId, this.buildServiceMetadataFromAttributes(data.resourceAttributes));
        }
        catch (err) {
            logger.warn(`telemetryServiceFromName lastSeen update failed for "${data.serviceName}": ${err instanceof Error ? err.message : String(err)}`);
        }
        /*
         * Promote `oneuptime.label.<dim>=<val>` resource attributes into
         * project labels and attach them to the discovered service. The
         * attach is throttled per-service so steady-state ingest with
         * unchanged labels costs one in-memory cache lookup.
         */
        if (data.resourceAttributes) {
            try {
                const labelNames = extractOneuptimeLabelNames(data.resourceAttributes);
                if (labelNames.length > 0) {
                    const labelIds = await LabelService.findOrCreateLabelsByNames({
                        projectId: data.projectId,
                        labelNames,
                    });
                    if (labelIds.length > 0) {
                        await ServiceService.attachLabels({
                            serviceId: result.primaryEntityId,
                            labelIds,
                        });
                    }
                }
            }
            catch (err) {
                logger.warn(`telemetryServiceFromName label promotion failed for "${data.serviceName}": ${err instanceof Error ? err.message : String(err)}`);
            }
        }
        return result;
    }
    static async findOrCreateTelemetryService(data) {
        /*
         * Sort by createdAt ASC for deterministic resolution if the
         * DB ever ends up with duplicates (defense in depth — the
         * unique index on (projectId, name) added in
         * DedupeServicesAndAddUniqueIndex1778100000000 prevents new
         * ones from forming, and converts concurrent first-contact
         * inserts into unique-violation errors that the catch block
         * below resolves to the winning row).
         */
        /*
         * Case-insensitive lookup (findWithSameText) to match the unique
         * guard's comparison — otherwise a service.name that drifts only in
         * case or surrounding whitespace misses here, gets rejected on create
         * ("Service with the same name already exists"), and wedges ingest.
         * Stored casing is preserved: service-detail pages key telemetry by the
         * stable primaryEntityId, and the name is user-facing.
         */
        const service = await ServiceService.findOneBy({
            query: {
                projectId: data.projectId,
                name: QueryHelper.findWithSameText(data.serviceName),
            },
            select: {
                _id: true,
                retainTelemetryDataForDays: true,
                telemetryRetentionConfig: true,
            },
            sort: {
                createdAt: SortOrder.Ascending,
            },
            props: {
                isRoot: true,
            },
        });
        const projectContext = await this.getProjectRetentionContext(data.projectId);
        /*
         * The service's own membership key (pure hash, no DB round trip), so
         * name-only sources (syslog / fluent) stamp a queryable `entityKeys`
         * instead of []. The OTLP path overwrites this with the full extracted
         * entity set in `resolveTelemetryResource`.
         */
        const serviceEntityKey = keyForService(data.projectId.toString(), data.serviceName);
        const buildMetadata = (svc) => {
            var _a, _b;
            const serviceLevelRetention = (_a = svc.retainTelemetryDataForDays) !== null && _a !== void 0 ? _a : null;
            return {
                serviceName: data.serviceName,
                primaryEntityId: svc.id,
                primaryEntityType: ServiceType.OpenTelemetry,
                entityKeys: [serviceEntityKey],
                /*
                 * Name-only sources can only ever see the service entity; the
                 * OTLP path overwrites this with the full per-type map in
                 * `resolveTelemetryResource`.
                 */
                scalarEntityKeys: Object.assign(Object.assign({}, emptyScalarEntityKeys()), { serviceEntityKey: serviceEntityKey }),
                dataRententionInDays: serviceLevelRetention || projectContext.projectRetentionInDays,
                serviceRetentionConfig: (_b = svc.telemetryRetentionConfig) !== null && _b !== void 0 ? _b : null,
                serviceRetentionInDays: serviceLevelRetention,
                projectRetentionConfig: projectContext.projectRetentionConfig,
                projectRetentionInDays: projectContext.projectRetentionInDays,
            };
        };
        if (!service) {
            try {
                const newService = new Service();
                newService.projectId = data.projectId;
                newService.name = data.serviceName;
                newService.description = data.serviceName;
                const createdService = await ServiceService.create({
                    data: newService,
                    props: {
                        isRoot: true,
                    },
                });
                return buildMetadata(createdService);
            }
            catch (_a) {
                /*
                 * Race condition: another request created the service concurrently.
                 * Re-fetch the existing service (oldest wins, see sort above).
                 */
                const existingService = await ServiceService.findOneBy({
                    query: {
                        projectId: data.projectId,
                        name: QueryHelper.findWithSameText(data.serviceName),
                    },
                    select: {
                        _id: true,
                        retainTelemetryDataForDays: true,
                        telemetryRetentionConfig: true,
                    },
                    sort: {
                        createdAt: SortOrder.Ascending,
                    },
                    props: {
                        isRoot: true,
                    },
                });
                if (existingService) {
                    return buildMetadata(existingService);
                }
                throw new Error("Failed to create or find service: " + data.serviceName);
            }
        }
        return buildMetadata(service);
    }
    /*
     * Builds a TelemetryServiceMetadata for a non-Service resource —
     * Host, DockerHost, KubernetesCluster, Monitor. These resources
     * own telemetry directly via their own Postgres id (stamped into
     * the analytics row's `primaryEntityId` column) and do not have a paired
     * Service row. Per-resource retention overrides (when set on the
     * Host / DockerHost / KubernetesCluster row) are honoured here so
     * the resource owner can keep host telemetry longer/shorter than
     * the project default. Monitor / unknown resource types fall back
     * to the project retention.
     */
    static async buildResourceMetadataForNonService(data) {
        const projectContext = await this.getProjectRetentionContext(data.projectId);
        const resourceRetention = await this.getResourceRetention(data.resourceId, data.primaryEntityType);
        return {
            serviceName: data.serviceName,
            primaryEntityId: data.resourceId,
            primaryEntityType: data.primaryEntityType,
            dataRententionInDays: resourceRetention.retainTelemetryDataForDays ||
                projectContext.projectRetentionInDays,
            serviceRetentionConfig: resourceRetention.telemetryRetentionConfig,
            serviceRetentionInDays: resourceRetention.retainTelemetryDataForDays,
            projectRetentionConfig: projectContext.projectRetentionConfig,
            projectRetentionInDays: projectContext.projectRetentionInDays,
        };
    }
    /*
     * Look up per-resource retention overrides for non-Service telemetry.
     * One small SELECT per batch — the caller caches the resulting
     * TelemetryServiceMetadata under `serviceDictionary[serviceName]`
     * so steady-state ingest skips this lookup after the first row.
     */
    static async getResourceRetention(resourceId, primaryEntityType) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
        try {
            if (primaryEntityType === ServiceType.Host) {
                const host = await HostService.findOneById({
                    id: resourceId,
                    select: {
                        retainTelemetryDataForDays: true,
                        telemetryRetentionConfig: true,
                    },
                    props: { isRoot: true },
                });
                return {
                    retainTelemetryDataForDays: (_a = host === null || host === void 0 ? void 0 : host.retainTelemetryDataForDays) !== null && _a !== void 0 ? _a : null,
                    telemetryRetentionConfig: (_b = host === null || host === void 0 ? void 0 : host.telemetryRetentionConfig) !== null && _b !== void 0 ? _b : null,
                };
            }
            if (primaryEntityType === ServiceType.DockerHost) {
                const dockerHost = await DockerHostService.findOneById({
                    id: resourceId,
                    select: {
                        retainTelemetryDataForDays: true,
                        telemetryRetentionConfig: true,
                    },
                    props: { isRoot: true },
                });
                return {
                    retainTelemetryDataForDays: (_c = dockerHost === null || dockerHost === void 0 ? void 0 : dockerHost.retainTelemetryDataForDays) !== null && _c !== void 0 ? _c : null,
                    telemetryRetentionConfig: (_d = dockerHost === null || dockerHost === void 0 ? void 0 : dockerHost.telemetryRetentionConfig) !== null && _d !== void 0 ? _d : null,
                };
            }
            if (primaryEntityType === ServiceType.KubernetesCluster) {
                const cluster = await KubernetesClusterService.findOneById({
                    id: resourceId,
                    select: {
                        retainTelemetryDataForDays: true,
                        telemetryRetentionConfig: true,
                    },
                    props: { isRoot: true },
                });
                return {
                    retainTelemetryDataForDays: (_e = cluster === null || cluster === void 0 ? void 0 : cluster.retainTelemetryDataForDays) !== null && _e !== void 0 ? _e : null,
                    telemetryRetentionConfig: (_f = cluster === null || cluster === void 0 ? void 0 : cluster.telemetryRetentionConfig) !== null && _f !== void 0 ? _f : null,
                };
            }
            if (primaryEntityType === ServiceType.ServerlessFunction) {
                const serverlessFunction = await ServerlessFunctionService.findOneById({
                    id: resourceId,
                    select: {
                        retainTelemetryDataForDays: true,
                        telemetryRetentionConfig: true,
                    },
                    props: { isRoot: true },
                });
                return {
                    retainTelemetryDataForDays: (_g = serverlessFunction === null || serverlessFunction === void 0 ? void 0 : serverlessFunction.retainTelemetryDataForDays) !== null && _g !== void 0 ? _g : null,
                    telemetryRetentionConfig: (_h = serverlessFunction === null || serverlessFunction === void 0 ? void 0 : serverlessFunction.telemetryRetentionConfig) !== null && _h !== void 0 ? _h : null,
                };
            }
            if (primaryEntityType === ServiceType.CloudResource) {
                const cloudResource = await CloudResourceService.findOneById({
                    id: resourceId,
                    select: {
                        retainTelemetryDataForDays: true,
                        telemetryRetentionConfig: true,
                    },
                    props: { isRoot: true },
                });
                return {
                    retainTelemetryDataForDays: (_j = cloudResource === null || cloudResource === void 0 ? void 0 : cloudResource.retainTelemetryDataForDays) !== null && _j !== void 0 ? _j : null,
                    telemetryRetentionConfig: (_k = cloudResource === null || cloudResource === void 0 ? void 0 : cloudResource.telemetryRetentionConfig) !== null && _k !== void 0 ? _k : null,
                };
            }
            if (primaryEntityType === ServiceType.RealUserMonitor) {
                const rumApplication = await RumApplicationService.findOneById({
                    id: resourceId,
                    select: {
                        retainTelemetryDataForDays: true,
                        telemetryRetentionConfig: true,
                    },
                    props: { isRoot: true },
                });
                return {
                    retainTelemetryDataForDays: (_l = rumApplication === null || rumApplication === void 0 ? void 0 : rumApplication.retainTelemetryDataForDays) !== null && _l !== void 0 ? _l : null,
                    telemetryRetentionConfig: (_m = rumApplication === null || rumApplication === void 0 ? void 0 : rumApplication.telemetryRetentionConfig) !== null && _m !== void 0 ? _m : null,
                };
            }
        }
        catch (err) {
            logger.warn(`Per-resource retention lookup failed for ${primaryEntityType} ${resourceId.toString()}: ${err instanceof Error ? err.message : String(err)}`);
        }
        return {
            retainTelemetryDataForDays: null,
            telemetryRetentionConfig: null,
        };
    }
    static getMetricFromDatapoint(data) {
        const { dbMetric, datapoint, aggregationTemporality, isMonotonic } = data;
        const newDbMetric = Metric.fromJSON(dbMetric.toJSON(), Metric);
        // Handle start timestamp safely
        if (datapoint["startTimeUnixNano"]) {
            try {
                let startTimeUnixNano;
                if (typeof datapoint["startTimeUnixNano"] === "string") {
                    startTimeUnixNano = parseFloat(datapoint["startTimeUnixNano"]);
                    if (isNaN(startTimeUnixNano)) {
                        startTimeUnixNano = OneUptimeDate.getCurrentDateAsUnixNano();
                    }
                }
                else {
                    startTimeUnixNano =
                        datapoint["startTimeUnixNano"] ||
                            OneUptimeDate.getCurrentDateAsUnixNano();
                }
                newDbMetric.startTimeUnixNano = startTimeUnixNano;
                newDbMetric.startTime = OneUptimeDate.fromUnixNano(startTimeUnixNano);
            }
            catch (_a) {
                const currentNano = OneUptimeDate.getCurrentDateAsUnixNano();
                newDbMetric.startTimeUnixNano = currentNano;
                newDbMetric.startTime = OneUptimeDate.getCurrentDate();
            }
        }
        // Handle end timestamp safely
        if (datapoint["timeUnixNano"]) {
            try {
                let timeUnixNano;
                if (typeof datapoint["timeUnixNano"] === "string") {
                    timeUnixNano = parseFloat(datapoint["timeUnixNano"]);
                    if (isNaN(timeUnixNano)) {
                        timeUnixNano = OneUptimeDate.getCurrentDateAsUnixNano();
                    }
                }
                else {
                    timeUnixNano =
                        datapoint["timeUnixNano"] ||
                            OneUptimeDate.getCurrentDateAsUnixNano();
                }
                newDbMetric.timeUnixNano = timeUnixNano;
                newDbMetric.time = OneUptimeDate.fromUnixNano(timeUnixNano);
            }
            catch (_b) {
                const currentNano = OneUptimeDate.getCurrentDateAsUnixNano();
                newDbMetric.timeUnixNano = currentNano;
                newDbMetric.time = OneUptimeDate.getCurrentDate();
            }
        }
        if (Object.keys(datapoint).includes("asInt")) {
            newDbMetric.value = datapoint["asInt"];
        }
        else if (Object.keys(datapoint).includes("asDouble")) {
            newDbMetric.value = datapoint["asDouble"];
        }
        newDbMetric.count = datapoint["count"];
        newDbMetric.sum = datapoint["sum"];
        newDbMetric.min = datapoint["min"];
        newDbMetric.max = datapoint["max"];
        newDbMetric.bucketCounts = datapoint["bucketCounts"];
        newDbMetric.explicitBounds = datapoint["explicitBounds"];
        if (!newDbMetric.value) {
            newDbMetric.value = newDbMetric.sum;
        }
        // attrbutes
        if (Object.keys(datapoint).includes("attributes")) {
            if (!newDbMetric.attributes) {
                newDbMetric.attributes = {};
            }
            newDbMetric.attributes = Object.assign(Object.assign({}, TelemetryUtil.getAttributesForServiceIdAndServiceName({
                serviceId: data.primaryEntityId,
                serviceName: data.serviceName,
            })), TelemetryUtil.getAttributes({
                items: datapoint["attributes"] || [],
                prefixKeysWithString: "",
            }));
        }
        newDbMetric.attributeKeys = TelemetryUtil.getAttributeKeys(newDbMetric.attributes);
        // aggregationTemporality
        if (aggregationTemporality) {
            if (aggregationTemporality === OtelAggregationTemporality.Cumulative) {
                newDbMetric.aggregationTemporality = AggregationTemporality.Cumulative;
            }
            if (aggregationTemporality === OtelAggregationTemporality.Delta) {
                newDbMetric.aggregationTemporality = AggregationTemporality.Delta;
            }
        }
        if (isMonotonic !== undefined) {
            newDbMetric.isMonotonic = isMonotonic;
        }
        return newDbMetric;
    }
}
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID]),
    __metadata("design:returntype", Promise)
], OTelIngestService, "getProjectRetentionContext", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], OTelIngestService, "telemetryServiceFromName", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], OTelIngestService, "findOrCreateTelemetryService", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Promise)
], OTelIngestService, "buildResourceMetadataForNonService", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [ObjectID, String]),
    __metadata("design:returntype", Promise)
], OTelIngestService, "getResourceRetention", null);
__decorate([
    CaptureSpan(),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", Metric)
], OTelIngestService, "getMetricFromDatapoint", null);
//# sourceMappingURL=OpenTelemetryIngestService.js.map