Exemplo n.º 1
0
void *cpuidlejitter_main(void *ptr) {
    struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr;

    info("IDLEJITTER thread created with task id %d", gettid());

    if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
        error("Cannot set pthread cancel type to DEFERRED.");

    if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
        error("Cannot set pthread cancel state to ENABLE.");

    int sleep_ms = (int) config_get_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
    if(sleep_ms <= 0) {
        config_set_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
        sleep_ms = CPU_IDLEJITTER_SLEEP_TIME_MS;
    }

    RRDSET *st = rrdset_find_localhost("system.idlejitter");
    if(!st) {
        st = rrdset_create_localhost("system", "idlejitter", NULL, "processes", NULL, "CPU Idle Jitter"
                                     , "microseconds lost/s", 9999, localhost->rrd_update_every, RRDSET_TYPE_LINE);
        rrddim_add(st, "jitter", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
    }

    struct timeval before, after;
    unsigned long long counter;
    for(counter = 0; 1 ;counter++) {
        usec_t usec = 0, susec = 0;

        if(netdata_exit) break;

        while(susec < (localhost->rrd_update_every * USEC_PER_SEC)) {

            now_monotonic_timeval(&before);
            sleep_usec(sleep_ms * 1000);
            now_monotonic_timeval(&after);

            // calculate the time it took for a full loop
            usec = dt_usec(&after, &before);
            susec += usec;
        }
        usec -= (sleep_ms * 1000);

        if(counter) rrdset_next(st);
        rrddim_set(st, "jitter", usec);
        rrdset_done(st);
    }

    info("IDLEJITTER thread exiting");

    static_thread->enabled = 0;
    pthread_exit(NULL);
    return NULL;
}
Exemplo n.º 2
0
void *cpuidlejitter_main(void *ptr)
{
	if(ptr) { ; }

	info("CPU Idle Jitter thread created with task id %d", gettid());

	if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
		error("Cannot set pthread cancel type to DEFERRED.");

	if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
		error("Cannot set pthread cancel state to ENABLE.");

	int sleep_ms = (int) config_get_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
	if(sleep_ms <= 0) {
		config_set_number("plugin:idlejitter", "loop time in ms", CPU_IDLEJITTER_SLEEP_TIME_MS);
		sleep_ms = CPU_IDLEJITTER_SLEEP_TIME_MS;
	}

	RRDSET *st = rrdset_find("system.idlejitter");
	if(!st) {
		st = rrdset_create("system", "idlejitter", NULL, "cpu", "CPU Idle Jitter", "microseconds lost/s", 9999, rrd_update_every, RRDSET_TYPE_LINE);
		rrddim_add(st, "jitter", NULL, 1, 1, RRDDIM_ABSOLUTE);
	}

	struct timeval before, after;
	unsigned long long counter;
	for(counter = 0; 1 ;counter++) {
		unsigned long long usec = 0, susec = 0;

		while(susec < (rrd_update_every * 1000000ULL)) {

			gettimeofday(&before, NULL);
			usleep(sleep_ms * 1000);
			gettimeofday(&after, NULL);

			// calculate the time it took for a full loop
			usec = usecdiff(&after, &before);
			susec += usec;
		}
		usec -= (sleep_ms * 1000);

		if(counter) rrdset_next(st);
		rrddim_set(st, "jitter", usec);
		rrdset_done(st);
	}

	return NULL;
}
Exemplo n.º 3
0
int create_listen_sockets(void) {
	listen_backlog = (int) config_get_number("global", "http port listen backlog", LISTEN_BACKLOG);

    if(config_exists("global", "bind socket to IP") && !config_exists("global", "bind to"))
        config_rename("global", "bind socket to IP", "bind to");

    if(config_exists("global", "port") && !config_exists("global", "default port"))
        config_rename("global", "port", "default port");

    listen_port = (int) config_get_number("global", "default port", LISTEN_PORT);
	if(listen_port < 1 || listen_port > 65535) {
		error("Invalid listen port %d given. Defaulting to %d.", listen_port, LISTEN_PORT);
        listen_port = (int) config_set_number("global", "default port", LISTEN_PORT);
	}
	debug(D_OPTIONS, "Default listen port set to %d.", listen_port);

    char *s = config_get("global", "bind to", "*");
    while(*s) {
        char *e = s;

        // skip separators, moving both s(tart) and e(nd)
        while(isspace(*e) || *e == ',') s = ++e;

        // move e(nd) to the first separator
        while(*e && !isspace(*e) && *e != ',') e++;

        // is there anything?
        if(!*s || s == e) break;

        char buf[e - s + 1];
        strncpyz(buf, s, e - s);
        bind_to_one(buf, listen_port, listen_backlog);

        s = e;
    }

    if(!listen_fds_count)
        fatal("Cannot listen on any socket. Exiting...");

	return listen_fds_count;
}
Exemplo n.º 4
0
int registry_init(void) {
    char filename[FILENAME_MAX + 1];

    // registry enabled?
    if(web_server_mode != WEB_SERVER_MODE_NONE) {
        registry.enabled = config_get_boolean(CONFIG_SECTION_REGISTRY, "enabled", 0);
    }
    else {
        info("Registry is disabled - use the central netdata");
        config_set_boolean(CONFIG_SECTION_REGISTRY, "enabled", 0);
        registry.enabled = 0;
    }

    // pathnames
    snprintfz(filename, FILENAME_MAX, "%s/registry", netdata_configured_varlib_dir);
    registry.pathname = config_get(CONFIG_SECTION_REGISTRY, "registry db directory", filename);
    if(mkdir(registry.pathname, 0770) == -1 && errno != EEXIST)
        fatal("Cannot create directory '%s'.", registry.pathname);

    // filenames
    snprintfz(filename, FILENAME_MAX, "%s/netdata.public.unique.id", registry.pathname);
    registry.machine_guid_filename = config_get(CONFIG_SECTION_REGISTRY, "netdata unique id file", filename);

    snprintfz(filename, FILENAME_MAX, "%s/registry.db", registry.pathname);
    registry.db_filename = config_get(CONFIG_SECTION_REGISTRY, "registry db file", filename);

    snprintfz(filename, FILENAME_MAX, "%s/registry-log.db", registry.pathname);
    registry.log_filename = config_get(CONFIG_SECTION_REGISTRY, "registry log file", filename);

    // configuration options
    registry.save_registry_every_entries = (unsigned long long)config_get_number(CONFIG_SECTION_REGISTRY, "registry save db every new entries", 1000000);
    registry.persons_expiration = config_get_number(CONFIG_SECTION_REGISTRY, "registry expire idle persons days", 365) * 86400;
    registry.registry_domain = config_get(CONFIG_SECTION_REGISTRY, "registry domain", "");
    registry.registry_to_announce = config_get(CONFIG_SECTION_REGISTRY, "registry to announce", "https://registry.my-netdata.io");
    registry.hostname = config_get(CONFIG_SECTION_REGISTRY, "registry hostname", netdata_configured_hostname);
    registry.verify_cookies_redirects = config_get_boolean(CONFIG_SECTION_REGISTRY, "verify browser cookies support", 1);

    setenv("NETDATA_REGISTRY_HOSTNAME", registry.hostname, 1);
    setenv("NETDATA_REGISTRY_URL", registry.registry_to_announce, 1);

    registry.max_url_length = (size_t)config_get_number(CONFIG_SECTION_REGISTRY, "max URL length", 1024);
    if(registry.max_url_length < 10) {
        registry.max_url_length = 10;
        config_set_number(CONFIG_SECTION_REGISTRY, "max URL length", (long long)registry.max_url_length);
    }

    registry.max_name_length = (size_t)config_get_number(CONFIG_SECTION_REGISTRY, "max URL name length", 50);
    if(registry.max_name_length < 10) {
        registry.max_name_length = 10;
        config_set_number(CONFIG_SECTION_REGISTRY, "max URL name length", (long long)registry.max_name_length);
    }

    // initialize entries counters
    registry.persons_count = 0;
    registry.machines_count = 0;
    registry.usages_count = 0;
    registry.urls_count = 0;
    registry.persons_urls_count = 0;
    registry.machines_urls_count = 0;

    // initialize memory counters
    registry.persons_memory = 0;
    registry.machines_memory = 0;
    registry.urls_memory = 0;
    registry.persons_urls_memory = 0;
    registry.machines_urls_memory = 0;

    // initialize locks
    netdata_mutex_init(&registry.lock);

    // create dictionaries
    registry.persons = dictionary_create(DICTIONARY_FLAGS);
    registry.machines = dictionary_create(DICTIONARY_FLAGS);
    avl_init(&registry.registry_urls_root_index, registry_url_compare);

    // load the registry database
    if(registry.enabled) {
        registry_log_open();
        registry_db_load();
        registry_log_load();

        if(unlikely(registry_db_should_be_saved()))
            registry_db_save();
    }

    return 0;
}
Exemplo n.º 5
0
static void get_netdata_configured_variables() {
    backwards_compatible_config();

    // ------------------------------------------------------------------------
    // get the hostname

    char buf[HOSTNAME_MAX + 1];
    if(gethostname(buf, HOSTNAME_MAX) == -1)
        error("Cannot get machine hostname.");

    netdata_configured_hostname = config_get(CONFIG_SECTION_GLOBAL, "hostname", buf);
    debug(D_OPTIONS, "hostname set to '%s'", netdata_configured_hostname);

    // ------------------------------------------------------------------------
    // get default database size

    default_rrd_history_entries = (int) config_get_number(CONFIG_SECTION_GLOBAL, "history", align_entries_to_pagesize(default_rrd_memory_mode, RRD_DEFAULT_HISTORY_ENTRIES));

    long h = align_entries_to_pagesize(default_rrd_memory_mode, default_rrd_history_entries);
    if(h != default_rrd_history_entries) {
        config_set_number(CONFIG_SECTION_GLOBAL, "history", h);
        default_rrd_history_entries = (int)h;
    }

    if(default_rrd_history_entries < 5 || default_rrd_history_entries > RRD_HISTORY_ENTRIES_MAX) {
        error("Invalid history entries %d given. Defaulting to %d.", default_rrd_history_entries, RRD_DEFAULT_HISTORY_ENTRIES);
        default_rrd_history_entries = RRD_DEFAULT_HISTORY_ENTRIES;
    }

    // ------------------------------------------------------------------------
    // get default database update frequency

    default_rrd_update_every = (int) config_get_number(CONFIG_SECTION_GLOBAL, "update every", UPDATE_EVERY);
    if(default_rrd_update_every < 1 || default_rrd_update_every > 600) {
        error("Invalid data collection frequency (update every) %d given. Defaulting to %d.", default_rrd_update_every, UPDATE_EVERY_MAX);
        default_rrd_update_every = UPDATE_EVERY;
    }

    // ------------------------------------------------------------------------
    // get system paths

    netdata_configured_config_dir  = config_get(CONFIG_SECTION_GLOBAL, "config directory",    CONFIG_DIR);
    netdata_configured_log_dir     = config_get(CONFIG_SECTION_GLOBAL, "log directory",       LOG_DIR);
    netdata_configured_web_dir     = config_get(CONFIG_SECTION_GLOBAL, "web files directory", WEB_DIR);
    netdata_configured_cache_dir   = config_get(CONFIG_SECTION_GLOBAL, "cache directory",     CACHE_DIR);
    netdata_configured_varlib_dir  = config_get(CONFIG_SECTION_GLOBAL, "lib directory",       VARLIB_DIR);
    netdata_configured_home_dir    = config_get(CONFIG_SECTION_GLOBAL, "home directory",      CACHE_DIR);

    {
        char plugins_dirs[(FILENAME_MAX * 2) + 1];
        snprintfz(plugins_dirs, FILENAME_MAX * 2, "\"%s\" \"%s/custom-plugins.d\"", PLUGINS_DIR, CONFIG_DIR);
        netdata_configured_plugins_dir_base = strdupz(config_get(CONFIG_SECTION_GLOBAL, "plugins directory",  plugins_dirs));
        quoted_strings_splitter(netdata_configured_plugins_dir_base, plugin_directories, PLUGINSD_MAX_DIRECTORIES, config_isspace);
        netdata_configured_plugins_dir = plugin_directories[0];
    }

    // ------------------------------------------------------------------------
    // get default memory mode for the database

    default_rrd_memory_mode = rrd_memory_mode_id(config_get(CONFIG_SECTION_GLOBAL, "memory mode", rrd_memory_mode_name(default_rrd_memory_mode)));

    // ------------------------------------------------------------------------

    netdata_configured_host_prefix = config_get(CONFIG_SECTION_GLOBAL, "host access prefix", "");
    verify_netdata_host_prefix();

    // --------------------------------------------------------------------
    // get KSM settings

#ifdef MADV_MERGEABLE
    enable_ksm = config_get_boolean(CONFIG_SECTION_GLOBAL, "memory deduplication (ksm)", enable_ksm);
#endif

    // --------------------------------------------------------------------
    // get various system parameters

    get_system_HZ();
    get_system_cpus();
    get_system_pid_max();
}
Exemplo n.º 6
0
RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char *family, const char *context, const char *title, const char *units, long priority, int update_every, int chart_type)
{
	if(!type || !type[0]) {
		fatal("Cannot create rrd stats without a type.");
		return NULL;
	}

	if(!id || !id[0]) {
		fatal("Cannot create rrd stats without an id.");
		return NULL;
	}

	char fullid[RRD_ID_LENGTH_MAX + 1];
	char fullfilename[FILENAME_MAX + 1];
	RRDSET *st = NULL;

	snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id);

	st = rrdset_find(fullid);
	if(st) {
		error("Cannot create rrd stats for '%s', it already exists.", fullid);
		return st;
	}

	long entries = config_get_number(fullid, "history", rrd_default_history_entries);
	if(entries < 5) entries = config_set_number(fullid, "history", 5);
	if(entries > RRD_HISTORY_ENTRIES_MAX) entries = config_set_number(fullid, "history", RRD_HISTORY_ENTRIES_MAX);

	int enabled = config_get_boolean(fullid, "enabled", 1);
	if(!enabled) entries = 5;

	unsigned long size = sizeof(RRDSET);
	char *cache_dir = rrdset_cache_dir(fullid);

	debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id);

	snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir);
	if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) st = (RRDSET *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 0);
	if(st) {
		if(strcmp(st->magic, RRDSET_MAGIC) != 0) {
			errno = 0;
			info("Initializing file %s.", fullfilename);
			bzero(st, size);
		}
		else if(strcmp(st->id, fullid) != 0) {
			errno = 0;
			error("File %s contents are not for chart %s. Clearing it.", fullfilename, fullid);
			// munmap(st, size);
			// st = NULL;
			bzero(st, size);
		}
		else if(st->memsize != size || st->entries != entries) {
			errno = 0;
			error("File %s does not have the desired size. Clearing it.", fullfilename);
			bzero(st, size);
		}
		else if(st->update_every != update_every) {
			errno = 0;
			error("File %s does not have the desired update frequency. Clearing it.", fullfilename);
			bzero(st, size);
		}
		else if((time(NULL) - st->last_updated.tv_sec) > update_every * entries) {
			errno = 0;
			error("File %s is too old. Clearing it.", fullfilename);
			bzero(st, size);
		}
	}

	if(st) {
		st->name = NULL;
		st->type = NULL;
		st->family = NULL;
		st->context = NULL;
		st->title = NULL;
		st->units = NULL;
		st->dimensions = NULL;
		st->next = NULL;
		st->mapped = rrd_memory_mode;
	}
	else {
		st = calloc(1, size);
		if(!st) {
			fatal("Cannot allocate memory for RRD_STATS %s.%s", type, id);
			return NULL;
		}
		st->mapped = RRD_MEMORY_MODE_RAM;
	}
	st->memsize = size;
	st->entries = entries;
	st->update_every = update_every;

	if(st->current_entry >= st->entries) st->current_entry = 0;

	strcpy(st->cache_filename, fullfilename);
	strcpy(st->magic, RRDSET_MAGIC);

	strcpy(st->id, fullid);
	st->hash = simple_hash(st->id);

	st->cache_dir = cache_dir;

	st->chart_type = rrdset_type_id(config_get(st->id, "chart type", rrdset_type_name(chart_type)));
	st->type       = config_get(st->id, "type", type);
	st->family     = config_get(st->id, "family", family?family:st->type);
	st->context    = config_get(st->id, "context", context?context:st->id);
	st->units      = config_get(st->id, "units", units?units:"");

	st->priority = config_get_number(st->id, "priority", priority);
	st->enabled = enabled;

	st->isdetail = 0;
	st->debug = 0;

	st->last_collected_time.tv_sec = 0;
	st->last_collected_time.tv_usec = 0;
	st->counter_done = 0;

	st->gap_when_lost_iterations_above = (int) (
			config_get_number(st->id, "gap when lost iterations above", RRD_DEFAULT_GAP_INTERPOLATIONS) + 2);

	avl_init_lock(&st->dimensions_index, rrddim_compare);

	pthread_rwlock_init(&st->rwlock, NULL);
	pthread_rwlock_wrlock(&rrdset_root_rwlock);

	if(name && *name) rrdset_set_name(st, name);
	else rrdset_set_name(st, id);

	{
		char varvalue[CONFIG_MAX_VALUE + 1];
		snprintfz(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name);
		st->title = config_get(st->id, "title", varvalue);
	}

	st->next = rrdset_root;
	rrdset_root = st;

	rrdset_index_add(st);

	pthread_rwlock_unlock(&rrdset_root_rwlock);

	return(st);
}
Exemplo n.º 7
0
RRDHOST *rrdhost_create(const char *hostname,
        const char *guid,
        const char *os,
        int update_every,
        long entries,
        RRD_MEMORY_MODE memory_mode,
        int health_enabled,
        int rrdpush_enabled,
        char *rrdpush_destination,
        char *rrdpush_api_key,
        int is_localhost
) {
    debug(D_RRDHOST, "Host '%s': adding with guid '%s'", hostname, guid);

    rrd_check_wrlock();

    RRDHOST *host = callocz(1, sizeof(RRDHOST));

    host->rrd_update_every    = (update_every > 0)?update_every:1;
    host->rrd_history_entries = align_entries_to_pagesize(memory_mode, entries);
    host->rrd_memory_mode     = memory_mode;
    host->health_enabled      = (memory_mode == RRD_MEMORY_MODE_NONE)? 0 : health_enabled;
    host->rrdpush_enabled     = (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key);
    host->rrdpush_destination = (host->rrdpush_enabled)?strdupz(rrdpush_destination):NULL;
    host->rrdpush_api_key     = (host->rrdpush_enabled)?strdupz(rrdpush_api_key):NULL;

    host->rrdpush_pipe[0] = -1;
    host->rrdpush_pipe[1] = -1;
    host->rrdpush_socket  = -1;

    netdata_mutex_init(&host->rrdpush_mutex);
    netdata_rwlock_init(&host->rrdhost_rwlock);

    rrdhost_init_hostname(host, hostname);
    rrdhost_init_machine_guid(host, guid);
    rrdhost_init_os(host, os);

    avl_init_lock(&(host->rrdset_root_index),      rrdset_compare);
    avl_init_lock(&(host->rrdset_root_index_name), rrdset_compare_name);
    avl_init_lock(&(host->rrdfamily_root_index),   rrdfamily_compare);
    avl_init_lock(&(host->variables_root_index),   rrdvar_compare);

    if(config_get_boolean(CONFIG_SECTION_GLOBAL, "delete obsolete charts files", 1))
        rrdhost_flag_set(host, RRDHOST_DELETE_OBSOLETE_FILES);

    if(config_get_boolean(CONFIG_SECTION_GLOBAL, "delete orphan hosts files", 1) && !is_localhost)
        rrdhost_flag_set(host, RRDHOST_DELETE_ORPHAN_FILES);


    // ------------------------------------------------------------------------
    // initialize health variables

    host->health_log.next_log_id = 1;
    host->health_log.next_alarm_id = 1;
    host->health_log.max = 1000;
    host->health_log.next_log_id =
    host->health_log.next_alarm_id = (uint32_t)now_realtime_sec();

    long n = config_get_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", host->health_log.max);
    if(n < 10) {
        error("Host '%s': health configuration has invalid max log entries %ld. Using default %u", host->hostname, n, host->health_log.max);
        config_set_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", (long)host->health_log.max);
    }
    else
        host->health_log.max = (unsigned int)n;

    netdata_rwlock_init(&host->health_log.alarm_log_rwlock);

    char filename[FILENAME_MAX + 1];

    if(is_localhost) {

        host->cache_dir  = strdupz(netdata_configured_cache_dir);
        host->varlib_dir = strdupz(netdata_configured_varlib_dir);

    }
    else {
        // this is not localhost - append our GUID to localhost path

        snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_cache_dir, host->machine_guid);
        host->cache_dir = strdupz(filename);

        if(host->rrd_memory_mode == RRD_MEMORY_MODE_MAP || host->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) {
            int r = mkdir(host->cache_dir, 0775);
            if(r != 0 && errno != EEXIST)
                error("Host '%s': cannot create directory '%s'", host->hostname, host->cache_dir);
        }

        snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_varlib_dir, host->machine_guid);
        host->varlib_dir = strdupz(filename);

        if(host->health_enabled) {
            int r = mkdir(host->varlib_dir, 0775);
            if(r != 0 && errno != EEXIST)
                error("Host '%s': cannot create directory '%s'", host->hostname, host->varlib_dir);
       }

    }

    if(host->health_enabled) {
        snprintfz(filename, FILENAME_MAX, "%s/health", host->varlib_dir);
        int r = mkdir(filename, 0775);
        if(r != 0 && errno != EEXIST)
            error("Host '%s': cannot create directory '%s'", host->hostname, filename);
    }

    snprintfz(filename, FILENAME_MAX, "%s/health/health-log.db", host->varlib_dir);
    host->health_log_filename = strdupz(filename);

    snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_plugins_dir);
    host->health_default_exec = strdupz(config_get(CONFIG_SECTION_HEALTH, "script to execute on alarm", filename));
    host->health_default_recipient = strdup("root");


    // ------------------------------------------------------------------------
    // load health configuration

    if(host->health_enabled) {
        health_alarm_log_load(host);
        health_alarm_log_open(host);

        rrdhost_wrlock(host);
        health_readdir(host, health_config_dir());
        rrdhost_unlock(host);
    }


    // ------------------------------------------------------------------------
    // link it and add it to the index

    if(is_localhost) {
        host->next = localhost;
        localhost = host;
    }
    else {
        if(localhost) {
            host->next = localhost->next;
            localhost->next = host;
        }
        else localhost = host;
    }

    RRDHOST *t = rrdhost_index_add(host);

    if(t != host) {
        error("Host '%s': cannot add host with machine guid '%s' to index. It already exists as host '%s' with machine guid '%s'.", host->hostname, host->machine_guid, t->hostname, t->machine_guid);
        rrdhost_free(host);
        host = NULL;
    }
    else {
        info("Host '%s' with guid '%s' initialized"
                     ", os %s"
                     ", update every %d"
                     ", memory mode %s"
                     ", history entries %ld"
                     ", streaming %s"
                     " (to '%s' with api key '%s')"
                     ", health %s"
                     ", cache_dir '%s'"
                     ", varlib_dir '%s'"
                     ", health_log '%s'"
                     ", alarms default handler '%s'"
                     ", alarms default recipient '%s'"
             , host->hostname
             , host->machine_guid
             , host->os
             , host->rrd_update_every
             , rrd_memory_mode_name(host->rrd_memory_mode)
             , host->rrd_history_entries
             , host->rrdpush_enabled?"enabled":"disabled"
             , host->rrdpush_destination?host->rrdpush_destination:""
             , host->rrdpush_api_key?host->rrdpush_api_key:""
             , host->health_enabled?"enabled":"disabled"
             , host->cache_dir
             , host->varlib_dir
             , host->health_log_filename
             , host->health_default_exec
             , host->health_default_recipient
        );
    }

    rrd_hosts_available++;

    return host;
}