static void send_heartbeat(noit_websocket_closure_t *wcl) { #ifdef HAVE_WSLAY mtev_http_websocket_queue_msg(wcl->restc->http_ctx, WSLAY_TEXT_FRAME, (const unsigned char *)heartbeat_str, heartbeat_str_len); #endif }
static int my_websocket_msg_handler(mtev_http_rest_closure_t *restc, int opcode, const unsigned char *msg, size_t msg_len) { /* simply echo back what was sent */ mtev_boolean x = mtev_http_websocket_queue_msg(restc->http_ctx, opcode, msg, msg_len); if (debug == 1) { mtevL(mtev_debug, "Queue websocket message.. success == %d\n", x); } return !x; }
static void send_individual_metric(noit_websocket_closure_t *wcl, const char *metric_string, size_t len) { #ifdef HAVE_WSLAY noit_metric_message_t message; char *json = NULL; size_t json_len = 0; int rval = noit_message_decoder_parse_line(metric_string, len, &message.id.id, &message.id.name, &message.id.name_len, &message.value, mtev_false); if (rval < 0) { return; } message.type = metric_string[0]; if (wcl->use_filter == mtev_true) { for (int i = 0; i < wcl->filter_count; i++) { if (message.id.name_len > 0 && strncmp(wcl->filters[i], message.id.name, message.id.name_len) == 0) { noit_metric_to_json(&message, &json, &json_len, mtev_false); mtev_http_websocket_queue_msg(wcl->restc->http_ctx, WSLAY_TEXT_FRAME, (const unsigned char *)json, json_len); free(json); break; } } } else { noit_metric_to_json(&message, &json, &json_len, mtev_false); mtev_http_websocket_queue_msg(wcl->restc->http_ctx, WSLAY_TEXT_FRAME, (const unsigned char *)json, json_len); free(json); } #endif }
/** * The "noit_livestream" protocol requires a well formed request to come * in via websocket that resembles: * * { * "period_ms": <milliseconds>, * "check_uuid": "<uuid_string>", * "metrics" : ["<metric_name1>", "<metric_name2>"] * } * * There can be only one active livestream request for a single websocket at one time. * However, you can send down a new livestream request at any time to alter the * stream based on new requirements. * * If the "metrics" member exists in the incoming request, then the metrics that are sent will be * filtered to those that match the strings in the array by exact match. If you want to get * all metrics in the check, omit the "metrics" member from the request object. */ int noit_websocket_msg_handler(mtev_http_rest_closure_t *restc, int opcode, const unsigned char *msg, size_t msg_len) { #ifdef HAVE_WSLAY const char *error = NULL; noit_websocket_closure_t *handler_data = restc->call_closure; /* for now this message is JSON, that might change in the future */ struct mtev_json_tokener *tok = mtev_json_tokener_new(); struct mtev_json_object *request = mtev_json_tokener_parse_ex(tok, (const char *)msg, msg_len); enum mtev_json_tokener_error err = tok->err; mtev_json_tokener_free(tok); if (err != mtev_json_tokener_success) { error = "Unable to parse incoming json"; goto websocket_handler_error; } uint64_t period_ms = mtev_json_object_get_uint64(mtev_json_object_object_get(request, "period_ms")); const char *check_uuid = mtev_json_object_get_string(mtev_json_object_object_get(request, "check_uuid")); struct mtev_json_object *metrics = mtev_json_object_object_get(request, "metrics"); if (handler_data != NULL) { /* destroy old subscription */ noit_websocket_closure_free(handler_data); handler_data = NULL; } handler_data = restc->call_closure = noit_websocket_closure_alloc(); handler_data->use_filter = mtev_false; restc->call_closure_free = noit_websocket_closure_free; handler_data->period = period_ms; if (metrics != NULL) { handler_data->use_filter = mtev_true; handler_data->filter_count = mtev_json_object_array_length(metrics); handler_data->filters = calloc(sizeof(char *), handler_data->filter_count); jl_array_list* a = mtev_json_object_get_array(metrics); for (int i = 0; i < handler_data->filter_count; i++) { struct mtev_json_object *o = jl_array_list_get_idx(a, i); if (o != NULL) { handler_data->filters[i] = strdup(mtev_json_object_get_string(o)); } } } handler_data->restc = restc; strncpy(handler_data->uuid_str, check_uuid, UUID_STR_LEN); handler_data->uuid_str[36] = '\0'; if(uuid_parse(handler_data->uuid_str, handler_data->uuid)) { mtevL(noit_error, "bad uuid received in livestream websocket_handler '%s'\n", handler_data->uuid_str); error = "bad uuid received in livestream subscription request"; goto websocket_handler_error; } mtev_json_object_put(request); /* setup subscription to noit_livestream */ asprintf(&handler_data->feed, "websocket_livestream/%d", mtev_atomic_inc32(&ls_counter)); handler_data->log_stream = mtev_log_stream_new(handler_data->feed, "noit_websocket_livestream", handler_data->feed, handler_data, NULL); handler_data->check = noit_check_watch(handler_data->uuid, handler_data->period); if(!handler_data->check) { error = "Cannot locate check"; goto websocket_handler_error; } /* This check must be watched from the livestream */ noit_check_transient_add_feed(handler_data->check, handler_data->feed); /* Note the check */ noit_check_log_check(handler_data->check); /* kick it off, if it isn't running already */ if(!NOIT_CHECK_LIVE(handler_data->check)) noit_check_activate(handler_data->check); return 0; websocket_handler_error: { struct mtev_json_object *e = mtev_json_object_new_object(); mtev_json_object_object_add(e, "success", mtev_json_object_new_int(0)); struct mtev_json_object *errors = mtev_json_object_new_array(); struct mtev_json_object *error_o = mtev_json_object_new_object(); mtev_json_object_object_add(error_o, "error", mtev_json_object_new_string(error)); mtev_json_object_array_add(errors, error_o); mtev_json_object_object_add(e, "errors", errors); const char *json_error = mtev_json_object_to_json_string(e); mtev_http_websocket_queue_msg(restc->http_ctx, WSLAY_TEXT_FRAME | WSLAY_CONNECTION_CLOSE, (const unsigned char *)json_error, strlen(json_error)); mtev_json_object_put(e); } #endif return -1; }