summaryrefslogtreecommitdiffstats
path: root/.gitreview
blob: 8b5a8f7de287a7d41e1811c3f65700706c40b7b3 (plain)
1
2
3
4
[gerrit]
host=gerrit.automotivelinux.org
port=29418
project=AGL/meta-agl
ground-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
/*
 * Copyright (C) 2018-2019 "IoT.bzh"
 * Author "Romain Forlot" <romain.forlot@iot.bzh>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *	 http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>

#include "influxdb.h"

void influxdb_write_curl_cb(void* closure, int status, CURL* curl, const char* result, size_t size)
{
	afb_req_t request = (afb_req_t)closure;
	long rep_code = curl_wrap_response_code_get(curl);
    switch (rep_code) {
		case 204:
			AFB_REQ_DEBUG(request, "Request correctly written");
			afb_req_success(request, NULL, "Request has been successfully written");
			break;
		case 400:
			afb_req_fail(request, "Bad request", result);
			break;
		case 401:
			afb_req_fail(request, "Unauthorized access", result);
			break;
		case 404:
			afb_req_fail(request, "Not found", result);
        AFB_REQ_NOTICE(request, "Attempt to create the DB '" DEFAULT_DB "'");
			create_database(request);
			break;
		case 500:
			afb_req_fail_f(request, "Timeout", "Overloaded server: %s", result);
			break;
		default:
        afb_req_fail_f(request, "Failure", "Unexpected behavior (code %ld).", rep_code);
			break;
	}
}

// query: destination buffer
// node: head node of the list
// list_sep: separator to append in front of the list
// item_sep: separator to append between items of the list
static void serialize_list_to_query(char *query, struct list *node, const char *list_sep, const char *item_sep) {
	bool first = true;

    while (node != NULL) {
        if (first) {
			concatenate(query, node->key, list_sep);
			first = false;
		} else {
			concatenate(query, node->key, item_sep);
		}

		if(json_object_is_type(node->value, json_type_string))
			concatenate_str(query, json_object_get_string(node->value), "=");
		else
			concatenate(query, json_object_to_json_string(node->value), "=");
		node = node->next;
	}
}

static size_t format_write_args(char* query, struct series_t* serie)
{
    char* ts;

	strncat(query, serie->name, strlen(serie->name));

	serialize_list_to_query(query, serie->serie_columns.tags, ",", ",");
	serialize_list_to_query(query, serie->serie_columns.fields, " ", ",");

	if (asprintf(&ts, "%lu", serie->timestamp) > 0) {
		concatenate(query, ts, " ");
		free(ts);
		return strlen(query);
	}
	return -1;
}

CURL* make_curl_write_post(afb_api_t apiHandle, const char* url, json_object* metricsJ)
{
    CURL* curl = NULL;
	size_t lpd = 0, len_write = 0, i = 0;
    char** post_data;
    char write[URL_MAXIMUM_LENGTH] = "";
    struct series_t* serie = NULL;
    json_object* metricsArrayJ = NULL;


    if (json_object_is_type(metricsJ, json_type_array)) {
		lpd = json_object_array_length(metricsJ);
		metricsArrayJ = metricsJ;
    } else {
		metricsArrayJ = json_object_new_array();
		json_object_array_add(metricsArrayJ, metricsJ);
		lpd = 1;
	}

	serie = malloc(sizeof(struct series_t));
	post_data = calloc(lpd + 1, sizeof(void*));

    for (i = 0; i < lpd; i++) {
		memset(serie, 0, sizeof(struct series_t));

        if (unpack_metric_from_api(json_object_array_get_idx(metricsArrayJ, i), serie)) {
			AFB_API_ERROR(apiHandle, "ERROR unpacking metric. %s", json_object_to_json_string(metricsArrayJ));
			break;
        } else {
            if (!serie->name) {
				post_data[i] = NULL;
            } else {
				len_write = format_write_args(write, serie);
                if (len_write > 0) {
					post_data[i] = malloc(len_write + 1);
					strcpy(post_data[i], write);
					memset(write, 0, len_write);
				}
			}
		}
	}

    AFB_API_DEBUG(apiHandle, "curl POST '%s' '%s' ", url, *post_data);

	/* Check that we just do not broke the for loop before trying preparing CURL
	   request object */
    curl = i == lpd ? curl_wrap_prepare_post_unescaped(url, NULL, "\n", (const char* const*)post_data) : NULL;
	free(serie);
    for (i = 0; i < lpd; i++) {
        if (post_data[i]) {
            free(post_data[i]);
        }
    }
	free(post_data);

	return curl;
}

CURL* influxdb_write(afb_api_t apiHandle, const char* host, const char* port, json_object* metricJ)
{
	char url[URL_MAXIMUM_LENGTH]; /* Safe limit for most popular web browser */
	make_url(url, sizeof(url), host, port, "write");
	return make_curl_write_post(apiHandle, url, metricJ);
}

CTLP_CAPI(write_to_influxdb, source, argsJ, eventJ)
{
	afb_req_t request = source->request;
    const char* port = NULL;
    const char* host = NULL;
    CURL* curl_request;
	int rc = -1;

	json_object *req_args = afb_req_json(request),
				*portJ = NULL,
				*metric = NULL;

    if (wrap_json_unpack(req_args, "{s?s,s?o,so!}",
			"host", &host,
			"port", &portJ,
            "metric", &metric)
        || !metric) {
		afb_req_fail(request, "Failed", "Error processing arguments. Miss metric\
JSON object or malformed");
		rc = -1;
	} else {
        port = json_object_is_type(portJ, json_type_null) ? NULL : json_object_to_json_string(portJ);
		curl_request = influxdb_write(source->api, host, port, metric);
		curl_wrap_do(curl_request, influxdb_write_curl_cb, request);
		rc = 0;
	}

	return rc;
}