realm-object-server
Version:
323 lines • 11.5 kB
JavaScript
"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