UNPKG

realm-object-server

Version:

Realm Object Server

323 lines 11.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const _ = require("lodash"); const Statsd_1 = require("./Statsd"); const SyncWorkerCounters = { authentication_failed: { help: "Authentication failed", }, connection_started: { help: "Connection started", }, connection_terminated: { help: "Connection terminated", }, session_started: { help: "Session started", }, session_terminated: { help: "Session terminated", }, session_failed: { help: "Session failed", }, protocol_violated: { help: "Protocol violated", }, protocol_bytes_sent: { help: "Total bytes sent", }, protocol_bytes_received: { help: "Total bytes received", }, changeset_integrated: { help: "Changesets integrated", }, download_constructed: { help: "Downloads constructed", }, permission_denied: { help: "Permission denied", }, client_unsyncable: { help: "Client unsyncable", }, merges_performed: { help: "Merges performed", }, connection_term_end_of_input: { name: "ros_sync_conn_term_end_of_input", help: "End of input", }, connection_term_connection_reset_error: { name: "ros_sync_conn_term_connection_reset_error", help: "Connection reset", }, connection_term_broken_pipe_error: { name: "ros_sync_conn_term_broken_pipe_error", help: "Broken pipe", }, connection_term_system_error: { name: "ros_sync_conn_term_system_error", help: "System error", }, connection_term_network_error: { name: "ros_sync_conn_term_network_error", help: "Network error", }, connection_term_ssl_error: { name: "ros_sync_conn_term_ssl_error", help: "TLS error", }, connection_term_http_error: { name: "ros_sync_conn_term_http_error", help: "HTTP error", }, connection_term_websocket_error: { name: "ros_sync_conn_term_websocket_error", help: "WebSocker error", }, connection_term_sync_protocol_error: { name: "ros_sync_conn_term_sync_protocol_error", help: "Sync protocol error", }, connection_term_error_of_unexpected_category: { name: "ros_sync_conn_term_error_of_unexpected_category", help: "Error of unexpected category", }, connection_term_superseded_session: { name: "ros_sync_conn_term_superseded_session", help: "Superseded session", }, connection_term_heartbeat_timeout: { name: "ros_sync_conn_term_heartbeat_timeout", help: "Heartbeat timeout", }, connection_term_http_response_written: { name: "ros_sync_conn_term_http_response_written", help: "HTTP response written", }, blacklisted: { name: "ros_sync_session_blacklisted", help: "A counter of sessions rejected due to the client file having been blacklisted", }, protocol_used: { name: "ros_sync_protocol_used", help: "A counter of protocol versions", labelNames: ["version"], } }; const SyncWorkerGauges = { protocol_bytes_sent: { name: "ros_sync_protocol_bytes_sent_gauge", help: "Total bytes sent", }, protocol_bytes_received: { name: "ros_sync_protocol_bytes_received_gauge", help: "Total bytes received", }, connection_online: { help: "Connections online", }, connection_total: { help: "Connections total", }, session_online: { help: "Sessions online", }, session_total: { help: "Sessions total", }, realms_open: { help: "Realms open", }, realms_all: { help: "Number of realms in the sync worker's data directory", }, realm_state_size: { help: "Size of realm states in bytes", labelNames: ["path"], }, event_loop_saturation: { help: "Event loop saturation", }, event_loop_inefficiency: { help: "Event loop inefficiency", }, upload_pending_bytes: { help: "Pending uploaded data in bytes" }, realm_file_size: { help: "Size of the Realm files in bytes", labelNames: ["path"], }, memory: { help: "Memory consumed by different sync subsystems", labelNames: ["subsystem"] }, user_sessions: { help: "Number of currently established sessions on behalf of a particular user", labelNames: ["identity"] }, core_transaction_disk_size: { help: "The size in bytes of the Realm file after a write transaction", labelNames: ["path"] }, core_transaction_free_space: { help: "The amount of free space within a Realm file after a write transaction", labelNames: ["path"] }, core_transaction_objects_count: { help: "The number of objects, across all classes in a Realm file after a write transaction", labelNames: ["path"] }, core_transaction_versions_count: { help: "The number of versions in a Realm file after a write transaction", labelNames: ["path"] }, }; const SyncWorkerHistograms = { download_constructed: { name: "ros_sync_download_constructed_ms", help: "Downloads constructed durations in ms", buckets: [1, 5, 10, 100, 500, 1000, 5000, 10000, 50000, 100000], }, download_constructed_size: { name: "ros_sync_download_constructed_bytes", help: "Downloads constructed sizes in bytes", buckets: [1, 64, 256, 1024, 64 * 1024, 256 * 1024, 1024 * 1024], }, changeset_integrated: { name: "ros_sync_changeset_integrated_ms", help: "Changeset integrated durations in ms", buckets: [1, 5, 10, 100, 500, 1000, 5000, 10000, 50000, 100000, 1000000, 5000000], }, changeset_integrated_size: { name: "ros_sync_changeset_integrated_bytes", help: "Changeset integrated sizes in bytes", buckets: [1, 64, 256, 1024, 64 * 1024, 256 * 1024, 1024 * 1024], }, changeset_integrated_merges: { help: "Changeset integrated merge counts", buckets: [1, 10, 100, 1000, 10000], }, ping_rtt: { name: "ros_sync_ping_rtt_ms", help: "Ping round-trip-time in ms", buckets: [1, 5, 10, 100, 500, 1000, 5000, 10000, 50000, 100000], }, upload_processing: { name: "ros_sync_change_propagation_ms", help: "Change propagation times", buckets: [10, 32, 100, 316, 1000, 3160, 10000, 31600, 100000, 316000, 1000000, 3160000], }, precheck_time: { name: "ros_sync_precheck_time_ms", help: "Time taken by prechecking processes", buckets: [1000, 2000, 4000, 8000, 16000, 32000, 1 * 60000, 2 * 60000, 4 * 60000, 8 * 60000, 16 * 60000] }, core_query: { help: "The time, in milliseconds, that a query took to run", buckets: [10, 500, 1000, 3000, 6000, 12000, 30000, 1 * 60000, 2 * 60000, 4 * 60000, 10 * 60000, 30 * 60000], labelNames: ["path", "description"], }, core_transaction_total_time: { help: "The time, in milliseconds, that a transaction took to run", buckets: [1, 2, 4, 8, 16, 32, 1 * 60, 2 * 60, 4 * 60, 8 * 60, 1000, 10000], labelNames: ["path", "type"], }, core_transaction_write_time: { help: "The portion of time, in milliseconds, that a write transaction took during the write phase of the commit", buckets: [1, 2, 4, 8, 16, 32, 1 * 60, 2 * 60, 4 * 60, 8 * 60, 1000, 10000], labelNames: ["path"], }, core_transaction_fsync_time: { help: "The portion of time, in milliseconds, that a write transaction took during the fsync phase of the commit", buckets: [1, 2, 4, 8, 16, 32, 1 * 60, 2 * 60, 4 * 60, 8 * 60, 1000, 10000], labelNames: ["path"], }, }; class StatsdToStatsSink { constructor(config, receiver) { this.gauges = {}; this.counters = {}; this.histograms = {}; this.handleMetric = (metric) => { try { const localMetricName = Statsd_1.parseMetricName(metric); const labels = Object.assign({}, this.labels, metric.labels); for (const stat of metric.stats) { if (stat.type === Statsd_1.MetricType.Gauge) { const gauge = this.gauges[localMetricName]; if (gauge) { gauge.set(labels, Number(stat.value) || 0); } else { throw new Error("Unexpected gauge"); } } else if (stat.type === Statsd_1.MetricType.Counter) { const counter = this.counters[localMetricName]; if (counter) { counter.inc(labels, Number(stat.value) || 0); } else { throw new Error("Unexpected counter"); } } else if (stat.type === Statsd_1.MetricType.Histogram) { const histogram = this.histograms[localMetricName]; if (histogram) { histogram.observe(labels, Number(stat.value) || 0); } else { throw new Error("Unexpected histogram"); } } else { throw new Error(`Unexpected metric type: "${stat.type}"`); } } } catch (err) { this.skipMetric(metric, err.message); } }; this.skipMetric = _.debounce((metric, reason) => { this.logger.detail(`Skipping "${metric.name}" metric: ${reason}`); }, 60000, { leading: true }); this.logger = config.logger; this.labels = config.labels; for (const name in SyncWorkerCounters) { this.counters[name] = config.statsSink.counter(Object.assign({ name: `ros_sync_${name}` }, SyncWorkerCounters[name])); } for (const name in SyncWorkerGauges) { this.gauges[name] = config.statsSink.gauge(Object.assign({ name: `ros_sync_${name}` }, SyncWorkerGauges[name])); } for (const name in SyncWorkerHistograms) { this.histograms[name] = config.statsSink.histogram(Object.assign({ name: `ros_sync_${name}` }, SyncWorkerHistograms[name])); } if (receiver) { this.listenTo(receiver); } } listenTo(receiver) { if (this.receiver) { throw new Error("Already listening to another receiver"); } else if (!receiver) { throw new Error("Cannot listen to a missing receiver"); } this.receiver = receiver; this.receiver.addListener("metric", this.handleMetric); } stop() { if (!this.receiver) { throw new Error("Not listening to a receiver"); } this.receiver.removeListener("metric", this.handleMetric); delete this.receiver; } } exports.StatsdToStatsSink = StatsdToStatsSink; //# sourceMappingURL=StatsdToStatsSink.js.map