Skip to content

Commit

Permalink
Merge pull request #15 from Castaglia/protocol-counters-gauges
Browse files Browse the repository at this point in the history
Protocol-specific counters, gauges
  • Loading branch information
Castaglia committed Mar 26, 2017
2 parents ab208c1 + 0097de9 commit 93db435
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 14 deletions.
118 changes: 106 additions & 12 deletions mod_statsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ static const char *statsd_exclude_filter = NULL;
static pr_regex_t *statsd_exclude_pre = NULL;
#endif /* PR_USE_REGEX */
static float statsd_sampling = STATSD_DEFAULT_SAMPLING;
static uint64_t statsd_sess_start_ms = 0;
static struct statsd *statsd = NULL;

static int statsd_sess_init(void);
Expand Down Expand Up @@ -69,8 +70,17 @@ static char *get_cmd_metric(pool *p, const char *cmd) {
return metric;
}

static char *get_conn_metric(pool *p) {
return pstrdup(p, "connection");
static char *get_conn_metric(pool *p, const char *name) {
char *metric;

if (name == NULL) {
metric = pstrdup(p, "connection");

} else {
metric = pstrcat(p, name, ".connection", NULL);
}

return metric;
}

static char *get_timeout_metric(pool *p, const char *name) {
Expand Down Expand Up @@ -310,11 +320,15 @@ MODRET set_statsdserver(cmd_rec *cmd) {

static void log_tls_auth_metrics(cmd_rec *cmd, uint64_t now_ms) {
const uint64_t *start_ms;
char *handshake_metric, *protocol_env, *cipher_env;
char *handshake_metric, *proto_metric, *protocol_env, *cipher_env;

handshake_metric = get_tls_metric(cmd->tmp_pool, "handshake.ctrl");
statsd_metric_counter(statsd, handshake_metric, 1);

proto_metric = get_conn_metric(cmd->tmp_pool, "ftps");
statsd_metric_counter(statsd, proto_metric, 1);
statsd_metric_gauge(statsd, proto_metric, 1, STATSD_METRIC_GAUGE_FL_ADJUST);

start_ms = pr_table_get(cmd->notes, "start_ms", NULL);
if (start_ms != NULL) {
uint64_t handshake_ms;
Expand Down Expand Up @@ -404,6 +418,24 @@ static void log_cmd_metrics(cmd_rec *cmd, int had_error) {
}

log_tls_metrics(cmd, had_error, now_ms);

if (pr_cmd_cmp(cmd, PR_CMD_PASS_ID) == 0 &&
had_error == FALSE) {
const char *proto;

proto = pr_session_get_protocol(0);
if (strcmp(proto, "ftp") == 0) {
char *proto_metric;

/* At this point in time, we are certain that we have a plain FTP
* connection, not FTPS or SFTP or anything else.
*/
proto_metric = get_conn_metric(cmd->tmp_pool, "ftp");
statsd_metric_counter(statsd, proto_metric, 1);
statsd_metric_gauge(statsd, proto_metric, 1, STATSD_METRIC_GAUGE_FL_ADJUST);
}
}

statsd_statsd_flush(statsd);
}

Expand All @@ -423,10 +455,20 @@ MODRET statsd_log_any_err(cmd_rec *cmd) {
static void statsd_exit_ev(const void *event_data, void *user_data) {
if (statsd != NULL) {
char *metric;
const char *proto;
uint64_t now_ms = 0, sess_ms;

metric = get_conn_metric(session.pool);
metric = get_conn_metric(session.pool, NULL);
statsd_metric_gauge(statsd, metric, -1, STATSD_METRIC_GAUGE_FL_ADJUST);

proto = pr_session_get_protocol(0);
metric = get_conn_metric(session.pool, proto);
statsd_metric_gauge(statsd, metric, -1, STATSD_METRIC_GAUGE_FL_ADJUST);

pr_gettimeofday_millis(&now_ms);
sess_ms = now_ms - statsd_sess_start_ms;
statsd_metric_timer(statsd, metric, sess_ms);

statsd_statsd_close(statsd);
statsd = NULL;
}
Expand Down Expand Up @@ -503,36 +545,73 @@ static void statsd_shutdown_ev(const void *event_data, void *user_data) {
}
}

static void incr_timeout_metric(pool *p, const char *name) {
static void statsd_ssh2_sftp_sess_opened_ev(const void *event_data,
void *user_data) {
pool *tmp_pool;
char *proto_metric;

if (should_sample(statsd_sampling) == FALSE) {
return;
}

tmp_pool = make_sub_pool(session.pool);
proto_metric = get_conn_metric(tmp_pool, "sftp");
statsd_metric_counter(statsd, proto_metric, 1);
statsd_metric_gauge(statsd, proto_metric, 1, STATSD_METRIC_GAUGE_FL_ADJUST);
statsd_statsd_flush(statsd);
destroy_pool(tmp_pool);
}

static void statsd_ssh2_scp_sess_opened_ev(const void *event_data,
void *user_data) {
pool *tmp_pool;
char *proto_metric;

if (should_sample(statsd_sampling) == FALSE) {
return;
}

tmp_pool = make_sub_pool(session.pool);
proto_metric = get_conn_metric(tmp_pool, "scp");
statsd_metric_counter(statsd, proto_metric, 1);
statsd_metric_gauge(statsd, proto_metric, 1, STATSD_METRIC_GAUGE_FL_ADJUST);
statsd_statsd_flush(statsd);
destroy_pool(tmp_pool);
}

static void incr_timeout_metric(const char *name) {
pool *tmp_pool;
char *metric;

/* Unlike other common metrics, for now the timeout counters are NOT subject
* to the sampling frequency.
*/

metric = get_timeout_metric(p, name);
tmp_pool = make_sub_pool(session.pool);
metric = get_timeout_metric(tmp_pool, name);
statsd_metric_counter(statsd, metric, 1);
statsd_statsd_flush(statsd);
destroy_pool(tmp_pool);
}

static void statsd_timeout_idle_ev(const void *event_data, void *user_data) {
incr_timeout_metric(session.pool, "TimeoutIdle");
incr_timeout_metric("TimeoutIdle");
}

static void statsd_timeout_login_ev(const void *event_data, void *user_data) {
incr_timeout_metric(session.pool, "TimeoutLogin");
incr_timeout_metric("TimeoutLogin");
}

static void statsd_timeout_noxfer_ev(const void *event_data, void *user_data) {
incr_timeout_metric(session.pool, "TimeoutNoTransfer");
incr_timeout_metric("TimeoutNoTransfer");
}

static void statsd_timeout_session_ev(const void *event_data, void *user_data) {
incr_timeout_metric(session.pool, "TimeoutSession");
incr_timeout_metric("TimeoutSession");
}

static void statsd_timeout_stalled_ev(const void *event_data, void *user_data) {
incr_timeout_metric(session.pool, "TimeoutStalled");
incr_timeout_metric("TimeoutStalled");
}

static void incr_tls_handshake_error_metric(const char *name) {
Expand Down Expand Up @@ -634,7 +713,7 @@ static int statsd_sess_init(void) {
statsd_sampling = *((float *) c->argv[0]);
}

metric = get_conn_metric(session.pool);
metric = get_conn_metric(session.pool, NULL);
statsd_metric_gauge(statsd, metric, 1, STATSD_METRIC_GAUGE_FL_ADJUST);
statsd_statsd_flush(statsd);

Expand All @@ -651,13 +730,28 @@ static int statsd_sess_init(void) {
pr_event_register(&statsd_module, "core.timeout-stalled",
statsd_timeout_stalled_ev, NULL);

if (pr_module_exists("mod_sftp.c") == TRUE) {
pr_event_register(&statsd_module, "mod_sftp.sftp.session-opened",
statsd_ssh2_sftp_sess_opened_ev, NULL);
pr_event_register(&statsd_module, "mod_sftp.scp.session-opened",
statsd_ssh2_scp_sess_opened_ev, NULL);
}

if (pr_module_exists("mod_tls.c") == TRUE) {
pr_event_register(&statsd_module, "mod_tls.ctrl-handshake-failed",
statsd_tls_ctrl_handshake_error_ev, NULL);
pr_event_register(&statsd_module, "mod_tls.data-handshake-failed",
statsd_tls_data_handshake_error_ev, NULL);
}

/* We only want to set the session start time once; this function could be
* called again due to e.g. a HOST command, and we do not want to reset
* the start time in that case.
*/
if (statsd_sess_start_ms == 0) {
pr_gettimeofday_millis(&statsd_sess_start_ms);
}

return 0;
}

Expand Down
17 changes: 15 additions & 2 deletions mod_statsd.html
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,17 @@ <h2><a name="Usage">Usage</a></h2>
Counters:
<pre>
<i>command</i>.<i>response-code</i>
<i>protocol</i>.connection
tls.handshake.ctrl
tls.hansdshake.ctrl.error
tls.hansdshake.data.error
tls.cipher.<i>cipher</i>
</pre>
Example:
Examples:
<pre>
USER.230
ftp.connection
sftp.connection
tls.cipher.ECDHE-RSA-AES128-SHA
tls.protocol.TLSv1
</pre>
Expand All @@ -220,18 +223,28 @@ <h2><a name="Usage">Usage</a></h2>
Timers:
<pre>
<i>command</i>.<i>response-code</i>
<i>protocol</i>.connection
tls.handshake.ctrl
</pre>
Example:
Examples:
<pre>
PASS.331
ftp.connection
sftp.connection
tls.handshake.ctrl
</pre>

<p>
Gauges:
<pre>
connection
<i>protocol</i>.connection
</pre>
Examples:
<pre>
connection
ftp.connection
sftp.connection
</pre>

<p>
Expand Down

0 comments on commit 93db435

Please sign in to comment.