UNPKG

@atomist/automation-client

Version:
195 lines • 7.93 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const cluster = require("cluster"); const hot_shots_1 = require("hot-shots"); const os = require("os"); const logger_1 = require("../internal/util/logger"); const shutdown_1 = require("../internal/util/shutdown"); const AutomationEventListener_1 = require("../server/AutomationEventListener"); class StatsdAutomationEventListener extends AutomationEventListener_1.AutomationEventListenerSupport { constructor(configuration) { super(); this.configuration = configuration; this.registrationName = `${this.configuration.name}/${this.configuration.version}`; this.initStatsd(); } registrationSuccessful(handler) { this.increment("counter.registration"); this.event("event.registration", `New registration for ${this.registrationName}`); } contextCreated(ctx) { const context = ctx.context; const graphClient = ctx.graphClient; // On the cluster master we don't have a GraphClient if (graphClient) { const tags = [ `atomist_operation:${context.operation}`, `atomist_operation_type:command`, ]; ctx.graphClient = { endpoint: graphClient.endpoint, mutate: (optionsOrName) => { const start = Date.now(); return graphClient.mutate(optionsOrName) .then(result => { this.statsd.increment("counter.graphql.mutation.success", 1, 1, tags, this.callback); this.statsd.timing("timer.graphql.mutation", Date.now() - start, 1, tags, this.callback); return result; }) .catch(err => { this.statsd.increment("counter.graphql.mutation.failure", 1, 1, tags, this.callback); this.statsd.timing("timer.graphql.mutation", Date.now() - start, 1, tags, this.callback); return err; }); }, query: (optionsOrName) => { const start = Date.now(); return graphClient.query(optionsOrName) .then(result => { this.statsd.increment("counter.graphql.query.success", 1, 1, tags, this.callback); this.statsd.timing("timer.graphql.query", Date.now() - start, 1, tags, this.callback); return result; }) .catch(err => { this.statsd.increment("counter.graphql.query.failure", 1, 1, tags, this.callback); this.statsd.timing("timer.graphql.query", Date.now() - start, 1, tags, this.callback); return err; }); }, }; } } commandSuccessful(payload, ctx, result) { const tags = [ `atomist_operation_type:command`, ]; this.increment("counter.operation.success", tags); this.timing("timer.operation", ctx, tags); return Promise.resolve(); } commandFailed(payload, ctx, err) { const tags = [ `atomist_operation:${payload.name}`, `atomist_operation_type:command`, ...this.teamDetail(ctx), ]; this.increment("counter.operation.failure", tags); this.timing("timer.operation", ctx, tags); this.event("event.operation.failure", "Unsuccessfully invoked command", tags); return Promise.resolve(); } eventSuccessful(payload, ctx, result) { const tags = [ `atomist_operation_type:event`, ]; this.increment("counter.operation.success", tags); this.timing("timer.operation", ctx, tags); return Promise.resolve(); } eventFailed(payload, ctx, err) { const tags = [ `atomist_operation:${payload.extensions.operationName}`, `atomist_operation_type:event`, ...this.teamDetail(ctx), ]; this.increment("counter.operation.failure", tags); this.timing("timer.operation", ctx, tags); this.event("event.operation.failure", "Unsuccessfully invoked event", tags); return Promise.resolve(); } messageSent(message, destinations, options, ctx) { let type; destinations = Array.isArray(destinations) ? destinations : [destinations]; destinations.forEach(d => { if (d.userAgent === "slack") { const sd = d; if (sd.users && sd.users.length > 0) { type = "slack_users"; } else if (sd.channels && sd.channels.length > 0) { type = "slack_channels"; } else { type = "slack_response"; } } }); this.increment("counter.message", [ `atomist_message_type:${type}`, ...this.teamDetail(ctx), ]); return Promise.resolve(); } /** Do-nothing callback */ callback(err) { return; } increment(stat, tags) { if (cluster.isMaster) { this.statsd.increment(stat, 1, 1, tags, this.callback); } } event(title, text, tags) { if (cluster.isMaster) { this.statsd.event(`automation_client.${title}`, text, {}, tags, this.callback); } } timing(stat, ctx, tags) { if (cluster.isMaster && ctx && ctx.context && ctx.context.ts) { const context = ctx.context; this.statsd.timing(stat, Date.now() - context.ts, 1, tags, this.callback); } } initStatsd() { const options = { prefix: "automation_client.", host: this.configuration.statsd.host || "localhost", port: this.configuration.statsd.port || 8125, globalTags: [ `atomist_name:${this.configuration.name.replace("@", "").replace("/", ".")}`, `atomist_version:${this.configuration.version}`, `atomist_environment:${this.configuration.environment}`, `atomist_application_id:${this.configuration.application}`, `atomist_process_id:${process.pid}`, `atomist_host:${os.hostname()}`, ], }; this.statsd = new hot_shots_1.StatsD(options); this.timer = setInterval(() => { this.submitHeapStats(); }, 5000); // Register orderly shutdown shutdown_1.registerShutdownHook(() => { this.event("event.shutdown", `Shutting down client ${this.registrationName}`); this.statsd.close(() => { logger_1.logger.debug("Closing StatsD connection"); }); return Promise.resolve(0); }); } teamDetail(ctx) { if (ctx && ctx.context) { const context = ctx.context; const safeTeamName = context.workspaceName ? context.workspaceName.trim().replace(/ /g, "_").replace(/\W/g, "") : undefined; return [ `atomist_team_id:${context.workspaceId}`, `atomist_team_name:${safeTeamName}`, ]; } else { return []; } } submitHeapStats() { const heap = process.memoryUsage(); this.statsd.gauge("heap.rss", heap.rss, 1, [], this.callback); this.statsd.gauge("heap.total", heap.heapTotal, 1, [], this.callback); this.statsd.gauge("heap.used", heap.heapUsed, 1, [], this.callback); } } exports.StatsdAutomationEventListener = StatsdAutomationEventListener; //# sourceMappingURL=statsd.js.map