UNPKG

@google-cloud/spanner

Version:
112 lines 4.93 kB
"use strict"; // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. Object.defineProperty(exports, "__esModule", { value: true }); exports.CloudMonitoringMetricsExporter = exports.MAX_BATCH_EXPORT_SIZE = void 0; const core_1 = require("@opentelemetry/core"); const monitoring_1 = require("@google-cloud/monitoring"); const transform_1 = require("./transform"); const grpc_js_1 = require("@grpc/grpc-js"); const constants_1 = require("./constants"); // Stackdriver Monitoring v3 only accepts up to 200 TimeSeries per // CreateTimeSeries call. exports.MAX_BATCH_EXPORT_SIZE = 200; /** * Format and sends metrics information to Google Cloud Monitoring. */ class CloudMonitoringMetricsExporter { _projectId; _lastExported = new Date(0); _client; _metricsExportFailureLogged = false; constructor({ auth }, projectId) { this._client = new monitoring_1.MetricServiceClient({ auth: auth }); this._projectId = projectId; } /** * Implementation for {@link PushMetricExporter.export}. * Calls the async wrapper method {@link _exportAsync} and * assures no rejected promises bubble up to the caller. * * @param metrics Metrics to be sent to the Google Cloud 3Monitoring backend * @param resultCallback result callback to be called on finish */ export(metrics, resultCallback) { // Do not export metrics if we've already exported within the last 30s const now = new Date(); if (now.getTime() - this._lastExported.getTime() <= constants_1.MIN_EXPORT_FREQUENCY_MS) { return; } this._lastExported = now; this._exportAsync(metrics).then(resultCallback, err => { resultCallback({ code: core_1.ExportResultCode.FAILED, error: err }); }); } async shutdown() { } async forceFlush() { } /** * Asnyc wrapper for the {@link export} implementation. * Writes the current values of all exported {@link MetricRecord}s * to the Google Cloud Monitoring backend. * * @param resourceMetrics Metrics to be sent to the Google Cloud Monitoring backend */ async _exportAsync(resourceMetrics) { const timeSeriesList = (0, transform_1.transformResourceMetricToTimeSeriesArray)(resourceMetrics, this._projectId); let failure = { sendFailed: false, }; await Promise.all(this._partitionList(timeSeriesList, exports.MAX_BATCH_EXPORT_SIZE).map(async (batchedTimeSeries) => this._sendTimeSeries(batchedTimeSeries))).catch(e => { if (!this._metricsExportFailureLogged) { const error = e; let msg = 'Send TimeSeries failed:'; if (error.code === grpc_js_1.status.PERMISSION_DENIED) { msg += ` Need monitoring metric writer permission on project ${this._projectId}. Follow https://cloud.google.com/spanner/docs/view-manage-client-side-metrics#access-client-side-metrics to set up permissions`; } console.warn(msg); this._metricsExportFailureLogged = true; } failure = { sendFailed: true, error: asError(e) }; }); if (!failure.sendFailed && this._metricsExportFailureLogged) { this._metricsExportFailureLogged = false; } return failure.sendFailed ? { code: core_1.ExportResultCode.FAILED, error: failure.error, } : { code: core_1.ExportResultCode.SUCCESS }; } async _sendTimeSeries(timeSeries) { if (timeSeries.length === 0) { return Promise.resolve(); } // TODO: Use createServiceTimeSeries when it is available await this._client.createTimeSeries({ name: `projects/${this._projectId}`, timeSeries: timeSeries, }); } /** Returns the minimum number of arrays of max size chunkSize, partitioned from the given array. */ _partitionList(list, chunkSize) { return Array.from({ length: Math.ceil(list.length / chunkSize) }, (_, i) => list.slice(i * chunkSize, (i + 1) * chunkSize)); } } exports.CloudMonitoringMetricsExporter = CloudMonitoringMetricsExporter; function asError(error) { return error instanceof Error ? error : new Error(String(error)); } //# sourceMappingURL=spanner-metrics-exporter.js.map