diff --git a/include/zbxexpr.h b/include/zbxexpr.h
index f4e0c5706b3..3288825460d 100644
--- a/include/zbxexpr.h
+++ b/include/zbxexpr.h
@@ -256,7 +256,12 @@ int	zbx_get_report_nextcheck(int now, unsigned char cycle, unsigned char weekday
 #define ZBX_CONDITION_OPERATOR_EXIST		12
 #define ZBX_CONDITION_OPERATOR_NOT_EXIST		13
 
-int	zbx_strloc_cmp(const char *src, const zbx_strloc_t *loc, const char *text, size_t text_len);
+#define ZBX_STRLOC_LEN(loc)	((loc)->r - (loc)->l + 1)
+int	zbx_strloc_cmp_str(const char *src, const zbx_strloc_t *loc, const char *text, size_t text_len);
+int	zbx_strloc_cmp(const char *src, const zbx_strloc_t *s1, const zbx_strloc_t *s2);
+
+void	zbx_strloc_set_null(zbx_strloc_t *loc);
+int	zbx_strloc_is_null(zbx_strloc_t *loc);
 
 typedef struct
 {
diff --git a/include/zbxprometheus.h b/include/zbxprometheus.h
index c48d92ff838..9c08200e7f9 100644
--- a/include/zbxprometheus.h
+++ b/include/zbxprometheus.h
@@ -16,22 +16,23 @@
 #define ZABBIX_ZBXPROMETHEUS_H
 
 #include "zbxalgo.h"
+#include "zbxexpr.h"
 
 typedef struct
 {
-	char	*name;
-	char	*value;
+	zbx_strloc_t	name;
+	zbx_strloc_t 	value;
 }
 zbx_prometheus_label_t;
 
-ZBX_PTR_VECTOR_DECL(prometheus_label, zbx_prometheus_label_t *)
+ZBX_VECTOR_DECL(prometheus_label, zbx_prometheus_label_t)
 
 typedef struct
 {
-	char				*metric;
-	char				*value;
+	zbx_strloc_t			metric;
+	zbx_strloc_t			value;
+	zbx_strloc_t			raw;
 	zbx_vector_prometheus_label_t	labels;
-	char				*raw;
 }
 zbx_prometheus_row_t;
 
@@ -48,6 +49,7 @@ ZBX_PTR_VECTOR_DECL(prometheus_label_index, zbx_prometheus_label_index_t *)
 
 typedef struct
 {
+	char					*data;
 	zbx_vector_prometheus_row_t		rows;
 	zbx_vector_prometheus_label_index_t	indexes;
 	zbx_hashset_t				hints;
diff --git a/src/libs/zbxcacheconfig/dbconfig.c b/src/libs/zbxcacheconfig/dbconfig.c
index d3defd0803b..435fd7e1520 100644
--- a/src/libs/zbxcacheconfig/dbconfig.c
+++ b/src/libs/zbxcacheconfig/dbconfig.c
@@ -2348,19 +2348,19 @@ static char	*dc_expand_host_macros_dyn(const char *text, const ZBX_DC_HOST *dc_h
 
 		zbx_strncpy_alloc(&str, &str_alloc, &str_offset, text + last_pos, token.loc.l - (size_t)last_pos);
 
-		if (SUCCEED == zbx_strloc_cmp(text, &token.loc, IF_MACRO_HOST_HOST, IF_MACRO_HOST_HOST_LEN) ||
-				SUCCEED == zbx_strloc_cmp(text, &token.loc, IF_MACRO_HOSTNAME, IF_MACRO_HOSTNAME_LEN))
+		if (SUCCEED == zbx_strloc_cmp_str(text, &token.loc, IF_MACRO_HOST_HOST, IF_MACRO_HOST_HOST_LEN) ||
+				SUCCEED == zbx_strloc_cmp_str(text, &token.loc, IF_MACRO_HOSTNAME, IF_MACRO_HOSTNAME_LEN))
 		{
 			value = dc_host->host;
 		}
-		else if (SUCCEED == zbx_strloc_cmp(text, &token.loc, IF_MACRO_HOST_NAME, IF_MACRO_HOST_NAME_LEN))
+		else if (SUCCEED == zbx_strloc_cmp_str(text, &token.loc, IF_MACRO_HOST_NAME, IF_MACRO_HOST_NAME_LEN))
 		{
 			value = dc_host->name;
 		}
 		else if (0 != (flags & EXPAND_INTERFACE_MACROS))
 		{
-			if (SUCCEED == zbx_strloc_cmp(text, &token.loc, IF_MACRO_HOST_IP, IF_MACRO_HOST_IP_LEN) ||
-					SUCCEED == zbx_strloc_cmp(text, &token.loc, IF_MACRO_IPADDRESS,
+			if (SUCCEED == zbx_strloc_cmp_str(text, &token.loc, IF_MACRO_HOST_IP, IF_MACRO_HOST_IP_LEN) ||
+					SUCCEED == zbx_strloc_cmp_str(text, &token.loc, IF_MACRO_IPADDRESS,
 							IF_MACRO_IPADDRESS_LEN))
 			{
 				if (SUCCEED == zbx_dc_config_get_interface_by_type(&interface, dc_host->hostid,
@@ -2369,7 +2369,7 @@ static char	*dc_expand_host_macros_dyn(const char *text, const ZBX_DC_HOST *dc_h
 					value = interface.ip_orig;
 				}
 			}
-			else if (SUCCEED == zbx_strloc_cmp(text, &token.loc, IF_MACRO_HOST_DNS, IF_MACRO_HOST_DNS_LEN))
+			else if (SUCCEED == zbx_strloc_cmp_str(text, &token.loc, IF_MACRO_HOST_DNS, IF_MACRO_HOST_DNS_LEN))
 			{
 				if (SUCCEED == zbx_dc_config_get_interface_by_type(&interface, dc_host->hostid,
 						INTERFACE_TYPE_AGENT))
@@ -2377,7 +2377,7 @@ static char	*dc_expand_host_macros_dyn(const char *text, const ZBX_DC_HOST *dc_h
 					value = interface.dns_orig;
 				}
 			}
-			else if (SUCCEED == zbx_strloc_cmp(text, &token.loc, IF_MACRO_HOST_CONN,
+			else if (SUCCEED == zbx_strloc_cmp_str(text, &token.loc, IF_MACRO_HOST_CONN,
 					IF_MACRO_HOST_CONN_LEN))
 			{
 				if (SUCCEED == zbx_dc_config_get_interface_by_type(&interface, dc_host->hostid,
diff --git a/src/libs/zbxexpr/token.c b/src/libs/zbxexpr/token.c
index 21b33ffb889..00fd1c2809f 100644
--- a/src/libs/zbxexpr/token.c
+++ b/src/libs/zbxexpr/token.c
@@ -13,6 +13,7 @@
 **/
 
 #include "zbxexpr.h"
+#include "zbxalgo.h"
 
 /******************************************************************************
  *                                                                            *
@@ -983,7 +984,7 @@ int	zbx_token_parse_nested_macro(const char *expression, const char *macro, zbx_
  *                1 - the substring is greater than the specified text        *
  *                                                                            *
  ******************************************************************************/
-int	zbx_strloc_cmp(const char *src, const zbx_strloc_t *loc, const char *text, size_t text_len)
+int	zbx_strloc_cmp_str(const char *src, const zbx_strloc_t *loc, const char *text, size_t text_len)
 {
 	size_t	src_len = loc->r - loc->l + 1;
 
@@ -996,3 +997,26 @@ int	zbx_strloc_cmp(const char *src, const zbx_strloc_t *loc, const char *text, s
 	return memcmp(src + loc->l, text, text_len);
 }
 
+int	zbx_strloc_cmp(const char *src, const zbx_strloc_t *s1, const zbx_strloc_t *s2)
+{
+	size_t	len1 = s1->r - s1->l + 1;
+	size_t	len2 = s2->r - s2->l + 1;
+
+	ZBX_RETURN_IF_NOT_EQUAL(len1, len2);
+
+
+	return memcmp(src + s1->l, src + s2->l, len1);
+}
+
+void	zbx_strloc_set_null(zbx_strloc_t *loc)
+{
+	loc->l = loc->r = SIZE_MAX;
+}
+
+int	zbx_strloc_is_null(zbx_strloc_t *loc)
+{
+	return loc->l == SIZE_MAX ? SUCCEED : FAIL;
+}
+
+
+
diff --git a/src/libs/zbxhttppoller/httpmacro.c b/src/libs/zbxhttppoller/httpmacro.c
index f4c637a2267..979037bef88 100644
--- a/src/libs/zbxhttppoller/httpmacro.c
+++ b/src/libs/zbxhttppoller/httpmacro.c
@@ -56,7 +56,7 @@ static int	zbx_macro_variable_search(const zbx_vector_ptr_pair_t *pmacro, const
 {
 	for (int i = 0; i < pmacro->values_num; i++)
 	{
-		if (SUCCEED == zbx_strloc_cmp(key, &loc, pmacro->values[i].first, strlen(pmacro->values[i].first)))
+		if (SUCCEED == zbx_strloc_cmp_str(key, &loc, pmacro->values[i].first, strlen(pmacro->values[i].first)))
 			return i;
 	}
 
diff --git a/src/libs/zbxprometheus/zbxprometheus.c b/src/libs/zbxprometheus/zbxprometheus.c
index cf7f11cb13c..8a122a3f553 100644
--- a/src/libs/zbxprometheus/zbxprometheus.c
+++ b/src/libs/zbxprometheus/zbxprometheus.c
@@ -65,9 +65,10 @@ zbx_prometheus_filter_t;
 /* the prometheus metric HELP, TYPE hints in comments */
 typedef struct
 {
-	char	*metric;
-	char	*type;
-	char	*help;
+	const char	*data;
+	zbx_strloc_t	metric;
+	zbx_strloc_t	type;
+	zbx_strloc_t	help;
 }
 zbx_prometheus_hint_t;
 
@@ -86,7 +87,8 @@ static zbx_hash_t	prometheus_hint_hash(const void *d)
 {
 	const zbx_prometheus_hint_t	*hint = (const zbx_prometheus_hint_t *)d;
 
-	return ZBX_DEFAULT_STRING_HASH_FUNC(hint->metric);
+	return ZBX_DEFAULT_STRING_HASH_ALGO(hint->data + hint->metric.l, hint->metric.r - hint->metric.l + 1,
+			ZBX_DEFAULT_HASH_SEED);
 }
 
 static int	prometheus_hint_compare(const void *d1, const void *d2)
@@ -94,15 +96,28 @@ static int	prometheus_hint_compare(const void *d1, const void *d2)
 	const zbx_prometheus_hint_t	*hint1 = (const zbx_prometheus_hint_t *)d1;
 	const zbx_prometheus_hint_t	*hint2 = (const zbx_prometheus_hint_t *)d2;
 
-	return strcmp(hint1->metric, hint2->metric);
+	return zbx_strloc_cmp(hint1->data, &hint1->metric, &hint2->metric);
 }
 
-ZBX_PTR_VECTOR_IMPL(prometheus_label, zbx_prometheus_label_t *)
+ZBX_VECTOR_IMPL(prometheus_label, zbx_prometheus_label_t)
 ZBX_PTR_VECTOR_IMPL(prometheus_row, zbx_prometheus_row_t *)
 ZBX_PTR_VECTOR_IMPL(prometheus_label_index, zbx_prometheus_label_index_t *)
 
 ZBX_PTR_VECTOR_IMPL(prometheus_condition, zbx_prometheus_condition_t *)
 
+static void	str_loc_dup_alloc(char **dst, size_t *dst_alloc, const char *src, const zbx_strloc_t *loc)
+{
+	size_t	len = loc->r - loc->l + 1;
+
+	if (len + 1 > *dst_alloc)
+	{
+		*dst_alloc = len + 1;
+		*dst = zbx_realloc(*dst, *dst_alloc);
+	}
+	memcpy(*dst, src + loc->l, len);
+	(*dst)[len] = '\0';
+}
+
 /******************************************************************************
  *                                                                            *
  * Purpose: allocates and copies substring at the specified location          *
@@ -115,34 +130,28 @@ ZBX_PTR_VECTOR_IMPL(prometheus_condition, zbx_prometheus_condition_t *)
  ******************************************************************************/
 static char	*str_loc_dup(const char *src, const zbx_strloc_t *loc)
 {
-	char	*str;
-	size_t	len;
+	char	*str = NULL;
+	size_t	len = 0;
 
-	len = loc->r - loc->l + 1;
-	str = zbx_malloc(NULL, len + 1);
-	memcpy(str, src + loc->l, len);
-	str[len] = '\0';
+	str_loc_dup_alloc(&str, &len, src, loc);
 
 	return str;
 }
 
-/******************************************************************************
- *                                                                            *
- * Purpose: unquotes substring at the specified location                      *
- *                                                                            *
- * Parameters: src - [IN] the source string                                   *
- *             loc - [IN] the substring location                              *
- *                                                                            *
- * Return value: The unquoted and copied substring.                           *
- *                                                                            *
- ******************************************************************************/
-static char	*str_loc_unquote_dyn(const char *src, const zbx_strloc_t *loc)
+static void 	str_loc_unquote_alloc(char **dst, size_t *dst_alloc, const char *src, const zbx_strloc_t *loc)
 {
-	char		*str, *ptr;
+	char	*ptr;
+	size_t	len = loc->r - loc->l;
 
-	src += loc->l + 1;
+	/* the unquoted value will be at least 2 characters shorted because of the double quote */
+	if (len > *dst_alloc)
+	{
+                *dst_alloc = len;
+		*dst = zbx_realloc(*dst, *dst_alloc);
+	}
 
-	str = ptr = zbx_malloc(NULL, loc->r - loc->l);
+	src += loc->l + 1;
+	ptr = *dst;
 
 	while ('"' != *src)
 	{
@@ -166,6 +175,24 @@ static char	*str_loc_unquote_dyn(const char *src, const zbx_strloc_t *loc)
 		src++;
 	}
 	*ptr = '\0';
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Purpose: unquotes substring at the specified location                      *
+ *                                                                            *
+ * Parameters: src - [IN] the source string                                   *
+ *             loc - [IN] the substring location                              *
+ *                                                                            *
+ * Return value: The unquoted and copied substring.                           *
+ *                                                                            *
+ ******************************************************************************/
+static char	*str_loc_unquote_dyn(const char *src, const zbx_strloc_t *loc)
+{
+	char	*str = NULL;
+	size_t	len = 0;
+
+	str_loc_unquote_alloc(&str, &len, src, loc);
 
 	return str;
 }
@@ -640,7 +667,7 @@ static int	prometheus_filter_parse_labels(zbx_prometheus_filter_t *filter, const
 			return FAIL;
 		}
 
-		if (0 == zbx_strloc_cmp(data, &loc_key, "__name__", ZBX_CONST_STRLEN("__name__")))
+		if (0 == zbx_strloc_cmp_str(data, &loc_key, "__name__", ZBX_CONST_STRLEN("__name__")))
 		{
 			if (NULL != filter->metric)
 			{
@@ -770,19 +797,9 @@ out:
 	return ret;
 }
 
-static void	prometheus_label_free(zbx_prometheus_label_t *label)
-{
-	zbx_free(label->name);
-	zbx_free(label->value);
-	zbx_free(label);
-}
 
 static void	prometheus_row_free(zbx_prometheus_row_t *row)
 {
-	zbx_free(row->metric);
-	zbx_free(row->value);
-	zbx_free(row->raw);
-	zbx_vector_prometheus_label_clear_ext(&row->labels, prometheus_label_free);
 	zbx_vector_prometheus_label_destroy(&row->labels);
 	zbx_free(row);
 }
@@ -791,39 +808,48 @@ static void	prometheus_row_free(zbx_prometheus_row_t *row)
  *                                                                            *
  * Purpose: matches key,value against filter condition                        *
  *                                                                            *
- * Parameters: condition - [IN] the condition                                 *
- *             key       - [IN] the key (optional, can be NULL)               *
- *             value     - [IN] the value                                     *
+ * Parameters: condition - [IN] condition                                     *
+ *             data      - [IN] prometheus data                               *
+ *             key       - [IN] key (optional, can be NULL)                   *
+ *             value     - [IN] value                                         *
  *                                                                            *
  * Return value: SUCCEED - the key,value pair matches condition               *
  *               FAIL    - otherwise                                          *
  *                                                                            *
  ******************************************************************************/
-static int	condition_match_key_value(const zbx_prometheus_condition_t *condition, const char *key,
-		const char *value)
+static int	condition_match_key_value(const zbx_prometheus_condition_t *condition, const char *data,
+		const zbx_strloc_t *key, const zbx_strloc_t *value, char **buf, size_t *buf_alloc)
 {
 	/* perform key match, succeeds if key is not defined in filter */
-	if (NULL != condition->key && (NULL == key || 0 != strcmp(key, condition->key)))
-		return FAIL;
+	if (NULL != condition->key)
+	{
+		if (NULL == key || 0 != zbx_strloc_cmp_str(data, key, condition->key, strlen(condition->key)))
+			return FAIL;
+	}
+
+	if ('"' == data[value->l])
+		str_loc_unquote_alloc(buf, buf_alloc, data, value);
+	else
+		str_loc_dup_alloc(buf, buf_alloc, data, value);
 
 	/* match value */
 	switch (condition->op)
 	{
 		case ZBX_PROMETHEUS_CONDITION_OP_EQUAL:
 		case ZBX_PROMETHEUS_CONDITION_OP_EQUAL_VALUE:
-			if (0 != strcmp(value, condition->pattern))
+			if (0 != strcmp(*buf, condition->pattern))
 				return FAIL;
 			break;
 		case ZBX_PROMETHEUS_CONDITION_OP_REGEX:
-			if (NULL == zbx_regexp_match(value, condition->pattern, NULL))
+			if (NULL == zbx_regexp_match(*buf, condition->pattern, NULL))
 				return FAIL;
 			break;
 		case ZBX_PROMETHEUS_CONDITION_OP_NOT_EQUAL:
-			if (0 == strcmp(value, condition->pattern))
+			if (0 == strcmp(*buf, condition->pattern))
 				return FAIL;
 			break;
 		case ZBX_PROMETHEUS_CONDITION_OP_REGEX_NOT_MATCHED:
-			if (NULL != zbx_regexp_match(value, condition->pattern, NULL))
+			if (NULL != zbx_regexp_match(*buf, condition->pattern, NULL))
 				return FAIL;
 			break;
 		default:
@@ -837,38 +863,50 @@ static int	condition_match_key_value(const zbx_prometheus_condition_t *condition
  *                                                                            *
  * Purpose: matches metric value against filter condition                     *
  *                                                                            *
- * Parameters: pattern   - [IN] the condition                                 *
- *             value     - [IN] the value                                     *
+ * Parameters: pattern   - [IN] condition                                     *
+ *             data      - [IN] prometheus data                               *
+ *             value     - [IN] value location                                *
  *                                                                            *
  * Return value: SUCCEED - the 'value' matches 'condition'                    *
  *               FAIL    - otherwise                                          *
  *                                                                            *
  ******************************************************************************/
-static int	condition_match_metric_value(const char *pattern, const char *value)
+static int	condition_match_metric_value(const char *pattern, const char *data, const zbx_strloc_t *value)
 {
 	double	pattern_dbl, value_dbl;
 	char	buffer[5];
 
 	if (SUCCEED != zbx_is_double(pattern, &pattern_dbl))
 	{
+		size_t	len = MIN(sizeof(buffer), (size_t)ZBX_STRLOC_LEN(value));
+		size_t	pos = (size_t)value->l;
+
 		if ('+' == *pattern)
 			pattern++;
 
-		if ('+' == *value)
-			value++;
+		if ('+' == data[pos])
+		{
+			pos++;
+			len--;
+		}
 
-		zbx_strlcpy(buffer, value, sizeof(buffer));
+		zbx_strlcpy(buffer, data + pos, len + 1);
 		zbx_strlower(buffer);
 		return (0 == strcmp(pattern, buffer) ? SUCCEED : FAIL);
 	}
 
-	if (SUCCEED != zbx_is_double(value, &value_dbl))
-		return FAIL;
+	char	*value_str = str_loc_dup(data, value);
+	int	ret = SUCCEED;
+
+	if (SUCCEED != zbx_is_double(value_str, &value_dbl))
+		ret = FAIL;
 
 	if (zbx_get_double_epsilon() <= fabs(pattern_dbl - value_dbl))
-		return FAIL;
+		ret = FAIL;
 
-	return SUCCEED;
+	zbx_free(value_str);
+
+	return ret;
 }
 
 /******************************************************************************
@@ -888,8 +926,7 @@ static int	condition_match_metric_value(const char *pattern, const char *value)
 static int	prometheus_metric_parse_labels(const char *data, size_t pos, zbx_vector_prometheus_label_t *labels,
 		zbx_strloc_t *loc, char **error)
 {
-	zbx_strloc_t		loc_key, loc_value, loc_op;
-	zbx_prometheus_label_t	*label;
+	zbx_strloc_t	loc_key, loc_value, loc_op;
 
 	pos = skip_spaces(data, pos + 1);
 	loc->l = pos;
@@ -897,6 +934,7 @@ static int	prometheus_metric_parse_labels(const char *data, size_t pos, zbx_vect
 	while ('}' != data[pos])
 	{
 		zbx_prometheus_condition_op_t	op;
+		zbx_prometheus_label_t		label_local;
 
 		if (FAIL == parse_condition(data, pos, &loc_key, &loc_op, &loc_value))
 		{
@@ -911,10 +949,9 @@ static int	prometheus_metric_parse_labels(const char *data, size_t pos, zbx_vect
 			return FAIL;
 		}
 
-		label = (zbx_prometheus_label_t *)zbx_malloc(NULL, sizeof(zbx_prometheus_label_t));
-		label->name = str_loc_dup(data, &loc_key);
-		label->value = str_loc_unquote_dyn(data, &loc_value);
-		zbx_vector_prometheus_label_append(labels, label);
+		label_local.name = loc_key;
+		label_local.value = loc_value;
+		zbx_vector_prometheus_label_append(labels, label_local);
 
 		pos = skip_spaces(data, loc_value.r + 1);
 
@@ -954,7 +991,7 @@ static int	prometheus_metric_parse_labels(const char *data, size_t pos, zbx_vect
  *                                                                            *
  ******************************************************************************/
 static int	prometheus_parse_row(zbx_prometheus_filter_t *filter, const char *data, size_t pos,
-		zbx_prometheus_row_t **prow, zbx_strloc_t *loc_row, char **error)
+		zbx_prometheus_row_t **prow, zbx_strloc_t *loc_row, char **buf, size_t *buf_alloc, char **error)
 {
 	zbx_strloc_t		loc;
 	zbx_prometheus_row_t	*row;
@@ -974,12 +1011,16 @@ static int	prometheus_parse_row(zbx_prometheus_filter_t *filter, const char *dat
 		goto out;
 	}
 
-	row->metric = str_loc_dup(data, &loc);
+	row->metric = loc;
 
 	if (NULL != filter->metric)
 	{
-		if (FAIL == (match = condition_match_key_value(filter->metric, NULL, row->metric)))
+		if (FAIL == (match = condition_match_key_value(filter->metric, data, NULL, &row->metric, buf,
+				buf_alloc)))
+
+		{
 			goto out;
+		}
 	}
 
 	/* parse labels and check against the filter */
@@ -997,10 +1038,13 @@ static int	prometheus_parse_row(zbx_prometheus_filter_t *filter, const char *dat
 
 			for (j = 0; j < row->labels.values_num; j++)
 			{
-				zbx_prometheus_label_t	*label = row->labels.values[j];
+				zbx_prometheus_label_t	*label = &row->labels.values[j];
 
-				if (SUCCEED == condition_match_key_value(condition, label->name, label->value))
+				if (SUCCEED == condition_match_key_value(condition, data, &label->name, &label->value,
+						buf, buf_alloc))
+				{
 					break;
+				}
 			}
 
 			if (j == row->labels.values_num)
@@ -1036,11 +1080,11 @@ static int	prometheus_parse_row(zbx_prometheus_filter_t *filter, const char *dat
 		*error = zbx_strdup(*error, "cannot parse metric value");
 		goto out;
 	}
-	row->value = str_loc_dup(data, &loc);
+	row->value = loc;
 
 	if (NULL != filter->value)
 	{
-		if (SUCCEED != (match = condition_match_metric_value(filter->value->pattern, row->value)))
+		if (SUCCEED != (match = condition_match_metric_value(filter->value->pattern, data, &row->value)))
 			goto out;
 	}
 
@@ -1169,43 +1213,44 @@ static int	parse_type(const char *data, size_t pos, zbx_strloc_t *loc_metric, zb
  *               FAIL    - otherwise                                          *
  *                                                                            *
  ******************************************************************************/
-static int	prometheus_register_hint(zbx_hashset_t *hints, const char *data, char *metric,
+static int	prometheus_register_hint(zbx_hashset_t *hints, const char *data, const zbx_strloc_t *metric,
 		const zbx_strloc_t *loc_hint, int hint_type, char **error)
 {
 	zbx_prometheus_hint_t	*hint, hint_local;
 	zbx_strloc_t		loc = *loc_hint;
 
-	hint_local.metric = metric;
+	hint_local.data = data;
+	hint_local.metric = *metric;
 
 	if (NULL == (hint = (zbx_prometheus_hint_t *)zbx_hashset_search(hints, &hint_local)))
 	{
-		hint_local.type = NULL;
-		hint_local.help = NULL;
+		zbx_strloc_set_null(&hint_local.type);
+		zbx_strloc_set_null(&hint_local.help);
 		hint = zbx_hashset_insert(hints, &hint_local, sizeof(hint_local));
 	}
-	else
-		zbx_free(metric);
 
 	while ((' ' == data[loc.r] || '\t' == data[loc.r]) && loc.r > loc.l)
 		loc.r--;
 
 	if (ZBX_PROMETHEUS_HINT_HELP == hint_type)
 	{
-		if (NULL != hint->help)
+		if (FAIL == zbx_strloc_is_null(&hint->help))
 		{
-			*error = zbx_dsprintf(*error, "multiple HELP comments found for metric \"%s\"", hint->metric);
+			*error = zbx_dsprintf(*error, "multiple HELP comments found for metric \"%.*s\"",
+					(int)ZBX_STRLOC_LEN(&hint->metric), hint->data + hint->metric.l);
 			return FAIL;
 		}
-		hint->help = str_loc_unescape_hint_dyn(data, &loc);
+		hint->help = loc;
 	}
 	else /* ZBX_PROMETHEUS_HINT_TYPE */
 	{
-		if (NULL != hint->type)
+		if (FAIL == zbx_strloc_is_null(&hint->type))
 		{
-			*error = zbx_dsprintf(*error, "multiple TYPE comments found for metric \"%s\"", hint->metric);
+			*error = zbx_dsprintf(*error, "multiple TYPE comments found for metric \"%.*s\"",
+					(int)ZBX_STRLOC_LEN(&hint->metric), hint->data + hint->metric.l);
 			return FAIL;
 		}
-		hint->type = str_loc_dup(data, &loc);
+		hint->type = loc;
 	}
 
 	return SUCCEED;
@@ -1227,11 +1272,10 @@ static int	prometheus_register_hint(zbx_hashset_t *hints, const char *data, char
  *                                                                            *
  ******************************************************************************/
 static int	prometheus_parse_hint(zbx_prometheus_filter_t *filter, const char *data, size_t pos,
-		zbx_hashset_t *hints, zbx_strloc_t *loc, char **error)
+		zbx_hashset_t *hints, zbx_strloc_t *loc, char **buf, size_t *buf_alloc, char **error)
 {
 	int		ret, hint_type;
 	zbx_strloc_t	loc_metric, loc_hint;
-	char		*metric;
 
 	loc->l = pos;
 	pos = skip_spaces(data, pos + 1);
@@ -1274,16 +1318,15 @@ static int	prometheus_parse_hint(zbx_prometheus_filter_t *filter, const char *da
 	}
 
 	loc->r = loc_hint.r;
-	metric = str_loc_dup(data, &loc_metric);
 
 	/* skip hints of metrics not matching filter */
-	if (NULL != filter->metric && SUCCEED != condition_match_key_value(filter->metric, NULL, metric))
+	if (NULL != filter->metric && SUCCEED != condition_match_key_value(filter->metric, data, NULL, &loc_metric,
+			buf, buf_alloc))
 	{
-		zbx_free(metric);
 		return SUCCEED;
 	}
 
-	return prometheus_register_hint(hints, data, metric, &loc_hint, hint_type, error);
+	return prometheus_register_hint(hints, data, &loc_metric, &loc_hint, hint_type, error);
 }
 
 /******************************************************************************
@@ -1303,10 +1346,10 @@ static int	prometheus_parse_hint(zbx_prometheus_filter_t *filter, const char *da
 static int	prometheus_parse_rows(zbx_prometheus_filter_t *filter, const char *data,
 		zbx_vector_prometheus_row_t *rows, zbx_hashset_t *hints, char **error)
 {
-	size_t			pos = 0;
+	size_t			pos = 0, buf_alloc = 0;
 	int			row_num = 1, ret = FAIL;
 	zbx_prometheus_row_t	*row;
-	char			*errmsg = NULL;
+	char			*errmsg = NULL, *buf = NULL;
 	zbx_strloc_t		loc;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
@@ -1323,19 +1366,22 @@ static int	prometheus_parse_rows(zbx_prometheus_filter_t *filter, const char *da
 		{
 			if (NULL != hints)
 			{
-				if (SUCCEED != prometheus_parse_hint(filter, data, pos, hints, &loc, &errmsg))
+				if (SUCCEED != prometheus_parse_hint(filter, data, pos, hints, &loc, &buf, &buf_alloc,
+						&errmsg))
+				{
 					goto out;
+				}
 				pos = loc.r + 1;
 			}
 			continue;
 		}
 
-		if (SUCCEED != prometheus_parse_row(filter, data, pos, &row, &loc, &errmsg))
+		if (SUCCEED != prometheus_parse_row(filter, data, pos, &row, &loc, &buf, &buf_alloc, &errmsg))
 			goto out;
 
 		if (NULL != row)
 		{
-			row->raw = str_loc_dup(data, &loc);
+			row->raw = loc;
 			zbx_vector_prometheus_row_append(rows, row);
 		}
 
@@ -1369,6 +1415,8 @@ out:
 #undef ZBX_PROMEHTEUS_ERROR_MAX_ROW_LENGTH
 	}
 
+	zbx_free(buf);
+
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s rows:%d hints:%d", __func__, zbx_result_string(ret),
 			rows->values_num, (NULL == hints ? 0 : hints->num_data));
 	return ret;
@@ -1378,7 +1426,8 @@ out:
  *                                                                            *
  * Purpose: extracts value from row                                           *
  *                                                                            *
- * Parameters: rows    - [IN] the source rows                                 *
+ * Parameters: data    - [IN] prometheus data                                 *
+ *             rows    - [IN] the source rows                                 *
  *             output  - [IN] the output template                             *
  *             value   - [OUT] the extracted value                            *
  *             error   - [OUT] the error message                              *
@@ -1387,8 +1436,8 @@ out:
  *               FAIL    - otherwise                                          *
  *                                                                            *
  ******************************************************************************/
-static int prometheus_extract_value(const zbx_vector_prometheus_row_t *rows, const char *output, char **value,
-		char **error)
+static int	prometheus_extract_value(const char *data, const zbx_vector_prometheus_row_t *rows, const char *output,
+		char **value, char **error)
 {
 	const zbx_prometheus_row_t	*row;
 
@@ -1415,7 +1464,8 @@ static int prometheus_extract_value(const zbx_vector_prometheus_row_t *rows, con
 		for (i = 0; i < rows_num; i++)
 		{
 			row = rows->values[i];
-			zbx_strcpy_alloc(error, &error_alloc, &error_offset, row->raw);
+			zbx_strncpy_alloc(error, &error_alloc, &error_offset, data + row->raw.l,
+					ZBX_STRLOC_LEN(&row->raw));
 			zbx_chrcpy_alloc(error, &error_alloc, &error_offset, '\n');
 		}
 
@@ -1437,11 +1487,11 @@ static int prometheus_extract_value(const zbx_vector_prometheus_row_t *rows, con
 
 		for (i = 0; i < row->labels.values_num; i++)
 		{
-			const zbx_prometheus_label_t	*label = (const zbx_prometheus_label_t *)row->labels.values[i];
+			const zbx_prometheus_label_t	*label = (const zbx_prometheus_label_t *)&row->labels.values[i];
 
-			if (0 == strcmp(label->name, output))
+			if (0 == zbx_strloc_cmp_str(data, &label->name, output, strlen(output)))
 			{
-				*value = zbx_strdup(NULL, label->value);
+				*value = str_loc_unquote_dyn(data, &label->value);
 				break;
 			}
 		}
@@ -1453,7 +1503,7 @@ static int prometheus_extract_value(const zbx_vector_prometheus_row_t *rows, con
 		}
 	}
 	else
-		*value = zbx_strdup(NULL, row->value);
+		*value = str_loc_dup(data, &row->value);
 
 	return SUCCEED;
 }
@@ -1462,7 +1512,8 @@ static int prometheus_extract_value(const zbx_vector_prometheus_row_t *rows, con
  *                                                                            *
  * Purpose: aggregates row values                                             *
  *                                                                            *
- * Parameters: rows     - [IN] the source rows                                *
+ * Parameters: data    - [IN] prometheus data                                 *
+ *             rows     - [IN] the source rows                                *
  *             function - [IN] the aggregation function                       *
  *             value    - [OUT] the aggregated value                          *
  *             error    - [OUT] the error message                             *
@@ -1471,8 +1522,8 @@ static int prometheus_extract_value(const zbx_vector_prometheus_row_t *rows, con
  *               FAIL    - otherwise                                          *
  *                                                                            *
  ******************************************************************************/
-static int	prometheus_aggregate_values(const zbx_vector_prometheus_row_t *rows, const char *function,
-		char **value, char **error)
+static int	prometheus_aggregate_values(const char *data, const zbx_vector_prometheus_row_t *rows,
+		const char *function, char **value, char **error)
 {
 	zbx_vector_dbl_t		values;
 	int				i, ret;
@@ -1485,7 +1536,7 @@ static int	prometheus_aggregate_values(const zbx_vector_prometheus_row_t *rows,
 	{
 		row = rows->values[i];
 
-		value_dbl = atof(row->value);
+		value_dbl = atof(data + row->value.l);
 
 		if (0 == isnan(value_dbl))
 			zbx_vector_dbl_append(&values, value_dbl);
@@ -1535,39 +1586,43 @@ static int	prometheus_aggregate_values(const zbx_vector_prometheus_row_t *rows,
  *                                                                            *
  * Purpose: performs the specified request on rows                            *
  *                                                                            *
- * Parameters: rows    - [IN] the source rows                                 *
- *             request - [IN] the request  (value, label, function)           *
- *             output  - [IN] the output template/function name               *
- *             value   - [OUT] the result value                               *
- *             error   - [OUT] the error message                              *
+ * Parameters: data    - [IN] prometheus data                                 *
+ *             rows    - [IN] source rows                                     *
+ *             request - [IN] request  (value, label, function)               *
+ *             output  - [IN] output template/function name                   *
+ *             value   - [OUT] result value                                   *
+ *             error   - [OUT] error message                                  *
  *                                                                            *
  * Return value: SUCCEED - the request was performed successfully             *
  *               FAIL    - otherwise                                          *
  *                                                                            *
  ******************************************************************************/
-static int	prometheus_query_rows(const zbx_vector_prometheus_row_t *rows, const char *request, const char *output,
-		char **value, char **error)
+static int	prometheus_query_rows(const char *data, const zbx_vector_prometheus_row_t *rows, const char *request,
+		const char *output, char **value, char **error)
 {
 	if (0 == strcmp(request, "function"))
-		return prometheus_aggregate_values(rows, output, value, error);
+		return prometheus_aggregate_values(data, rows, output, value, error);
 
-	return prometheus_extract_value(rows, output, value, error);
+	return prometheus_extract_value(data, rows, output, value, error);
 }
 
 /******************************************************************************
  *                                                                            *
  * Purpose: get rows matching the filter criteria                             *
  *                                                                            *
- * Parameters: rows     - [IN] the rows to filter                             *
- *             filter   - [IN] the prometheus filt                            *
- *             rows_out - [OUT] the filtered rows                             *
+ * Parameters: data     - [IN] prometheus data                                *
+ *             rows     - [IN] rows to filter                                 *
+ *             filter   - [IN] prometheus filt                                *
+ *             rows_out - [OUT] filtered rows                                 *
  *                                                                            *
  ******************************************************************************/
-static void	prometheus_filter_rows(zbx_vector_prometheus_row_t *rows, zbx_prometheus_filter_t *filter,
-		zbx_vector_prometheus_row_t *rows_out)
+static void	prometheus_filter_rows(const char *data, zbx_vector_prometheus_row_t *rows,
+		zbx_prometheus_filter_t *filter, zbx_vector_prometheus_row_t *rows_out)
 {
 	int			i, j, k;
 	zbx_prometheus_row_t	*row;
+	char			*buf = NULL;
+	size_t			buf_alloc = 0;
 
 	zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
 
@@ -1577,8 +1632,11 @@ static void	prometheus_filter_rows(zbx_vector_prometheus_row_t *rows, zbx_promet
 
 		if (NULL != filter->metric)
 		{
-			if (SUCCEED != condition_match_key_value(filter->metric, NULL, row->metric))
+			if (SUCCEED != condition_match_key_value(filter->metric, data, NULL, &row->metric, &buf,
+					&buf_alloc))
+			{
 				continue;
+			}
 		}
 
 		if (0 == row->labels.values_num && 0 != filter->labels.values_num)
@@ -1590,10 +1648,13 @@ static void	prometheus_filter_rows(zbx_vector_prometheus_row_t *rows, zbx_promet
 
 			for (k = 0; k < row->labels.values_num; k++)
 			{
-				zbx_prometheus_label_t	*label = row->labels.values[k];
+				zbx_prometheus_label_t	*label = &row->labels.values[k];
 
-				if (SUCCEED == condition_match_key_value(condition, label->name, label->value))
+				if (SUCCEED == condition_match_key_value(condition, data, &label->name, &label->value,
+						&buf, &buf_alloc))
+				{
 					break;
+				}
 			}
 
 			if (k == row->labels.values_num)
@@ -1605,23 +1666,16 @@ static void	prometheus_filter_rows(zbx_vector_prometheus_row_t *rows, zbx_promet
 
 		if (NULL != filter->value)
 		{
-			if (SUCCEED != condition_match_metric_value(filter->value->pattern, row->value))
+			if (SUCCEED != condition_match_metric_value(filter->value->pattern, data, &row->value))
 				continue;
 		}
 
 		zbx_vector_prometheus_row_append(rows_out, row);
 	}
 
-	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() rows:%d", __func__, rows_out->values_num);
-}
+	zbx_free(buf);
 
-static void	prometheus_hint_clear(void *d)
-{
-	zbx_prometheus_hint_t	*hint = (zbx_prometheus_hint_t *)d;
-
-	zbx_free(hint->metric);
-	zbx_free(hint->help);
-	zbx_free(hint->type);
+	zabbix_log(LOG_LEVEL_DEBUG, "End of %s() rows:%d", __func__, rows_out->values_num);
 }
 
 /******************************************************************************
@@ -1643,9 +1697,9 @@ int	zbx_prometheus_init(zbx_prometheus_t *prom, const char *data, char **error)
 
 	zbx_vector_prometheus_row_create(&prom->rows);
 	zbx_vector_prometheus_label_index_create(&prom->indexes);
+	prom->data = zbx_strdup(NULL, data);
 
-	zbx_hashset_create_ext(&prom->hints, 100, prometheus_hint_hash, prometheus_hint_compare, prometheus_hint_clear,
-			ZBX_DEFAULT_MEM_MALLOC_FUNC, ZBX_DEFAULT_MEM_REALLOC_FUNC, ZBX_DEFAULT_MEM_FREE_FUNC);
+	zbx_hashset_create(&prom->hints, 100, prometheus_hint_hash, prometheus_hint_compare);
 
 	if (0 != pthread_mutex_init(&prom->index_lock, NULL))
 	{
@@ -1656,7 +1710,7 @@ int	zbx_prometheus_init(zbx_prometheus_t *prom, const char *data, char **error)
 	if (SUCCEED != prometheus_filter_init(&filter, NULL, error))
 		goto out;
 
-	if (FAIL == prometheus_parse_rows(&filter, data, &prom->rows, &prom->hints, error))
+	if (FAIL == prometheus_parse_rows(&filter, prom->data, &prom->rows, &prom->hints, error))
 		goto out;
 
 	ret = SUCCEED;
@@ -1678,7 +1732,10 @@ static void	prometheus_label_index_free(zbx_prometheus_label_index_t *label_inde
 
 	zbx_hashset_iter_reset(&label_index->index, &iter);
 	while (NULL != (index = (zbx_prometheus_index_t *)zbx_hashset_iter_next(&iter)))
+	{
+		zbx_free(index->value);
 		zbx_vector_prometheus_row_destroy(&index->rows);
+	}
 
 	zbx_hashset_destroy(&label_index->index);
 	zbx_free(label_index);
@@ -1693,6 +1750,7 @@ static void	prometheus_label_index_free(zbx_prometheus_label_index_t *label_inde
  ******************************************************************************/
 void	zbx_prometheus_clear(zbx_prometheus_t *prom)
 {
+	zbx_free(prom->data);
 	zbx_hashset_destroy(&prom->hints);
 
 	zbx_vector_prometheus_label_index_clear_ext(&prom->indexes, prometheus_label_index_free);
@@ -1777,22 +1835,23 @@ static int	prometheus_index_compare_func(const void *d1, const void *d2)
  *                                                                            *
  * Purpose: get label from row by the specified name                          *
  *                                                                            *
- * Parameters: row  - [IN] the prometheus row                                 *
- *             name - [IN] the label name                                     *
+ * Parameters: data - [IN] prometheus data                                    *
+ *             row  - [IN] prometheus row                                     *
+ *             name - [IN] label name                                         *
  *                                                                            *
  * Return value: The prometheus row label or NULL if no labels matched the    *
  *               specified name.                                              *
  *                                                                            *
  ******************************************************************************/
-static zbx_prometheus_label_t	*prometheus_get_row_label(zbx_prometheus_row_t *row, const char *name)
+static zbx_prometheus_label_t	*prometheus_get_row_label(const char *data, zbx_prometheus_row_t *row, const char *name)
 {
 	int	i;
 
 	for (i = 0; i < row->labels.values_num; i++)
 	{
-		zbx_prometheus_label_t	*label = row->labels.values[i];
+		zbx_prometheus_label_t	*label = &row->labels.values[i];
 
-		if (0 == strcmp(label->name, name))
+		if (0 == zbx_strloc_cmp_str(data, &label->name, name, strlen(name)))
 			return label;
 	}
 
@@ -1848,10 +1907,10 @@ static int	prometheus_get_indexed_rows_by_label(zbx_prometheus_t *prom, zbx_prom
 			zbx_prometheus_row_t	*row = prom->rows.values[i];
 			zbx_prometheus_label_t	*label;
 
-			if (NULL == (label = prometheus_get_row_label(row, label_index->label)))
+			if (NULL == (label = prometheus_get_row_label(prom->data, row, label_index->label)))
 				continue;
 
-			index_local.value = label->value;
+			index_local.value = str_loc_unquote_dyn(prom->data, &label->value);
 
 			if (NULL == (index = (zbx_prometheus_index_t *)zbx_hashset_search(&label_index->index,
 					&index_local)))
@@ -1860,6 +1919,8 @@ static int	prometheus_get_indexed_rows_by_label(zbx_prometheus_t *prom, zbx_prom
 						sizeof(index_local));
 				zbx_vector_prometheus_row_create(&index->rows);
 			}
+			else
+				zbx_free(index_local.value);
 
 			zbx_vector_prometheus_row_append(&index->rows, row);
 		}
@@ -1950,9 +2011,9 @@ int	zbx_prometheus_pattern_ex(zbx_prometheus_t *prom, const char *filter_data, c
 	if (SUCCEED != prometheus_get_indexed_rows_by_label(prom, &filter, &prows) || NULL == prows)
 		prows = &prom->rows;
 
-	prometheus_filter_rows(prows, &filter, &rows);
+	prometheus_filter_rows(prom->data, prows, &filter, &rows);
 
-	if (FAIL == (ret = prometheus_query_rows(&rows, request, output, value, &errmsg)))
+	if (FAIL == (ret = prometheus_query_rows(prom->data, &rows, request, output, value, &errmsg)))
 	{
 		*error = zbx_dsprintf(*error, "data extraction error: %s", errmsg);
 		zbx_free(errmsg);
@@ -2007,7 +2068,7 @@ int	zbx_prometheus_pattern(const char *data, const char *filter_data, const char
 	if (FAIL == prometheus_parse_rows(&filter, data, &rows, NULL, error))
 		goto cleanup;
 
-	if (FAIL == prometheus_query_rows(&rows, request, output, value, &errmsg))
+	if (FAIL == prometheus_query_rows(data, &rows, request, output, value, &errmsg))
 	{
 		*error = zbx_dsprintf(*error, "data extraction error: %s", errmsg);
 		zbx_free(errmsg);
@@ -2029,31 +2090,40 @@ out:
  *                                                                            *
  * Purpose: converts filtered prometheus rows to json to be used with LLD     *
  *                                                                            *
- * Parameters: rows  - [IN] filtered prometheus rows                          *
+ * Parameters: dat a - [IN] prometheus data                                   *
+ *             rows  - [IN] filtered prometheus rows                          *
  *             hints - [IN] prometheus hints                                  *
- *             value - [OUT] the converted data                               *
+ *             value - [OUT] converted data                                   *
  *                                                                            *
  * Return value: SUCCEED - the data was converted successfully                *
  *               FAIL    - otherwise                                          *
  *                                                                            *
  ******************************************************************************/
-static void	prometheus_to_json(zbx_vector_prometheus_row_t *rows, zbx_hashset_t *hints, char **value)
+static void	prometheus_to_json(const char *data, zbx_vector_prometheus_row_t *rows, zbx_hashset_t *hints,
+		char **value)
 {
 	int			i, j;
 	struct zbx_json		json;
 	zbx_prometheus_hint_t	*hint, hint_local;
+	char			*val, *key;
+	size_t			val_alloc = 1024, key_alloc = 128;
+
+	val = (char *)zbx_malloc(NULL, val_alloc);
+	key = (char *)zbx_malloc(NULL, key_alloc);
 
 	zbx_json_initarray(&json, (size_t)rows->values_num * 100);
 
 	for (i = 0; i < rows->values_num; i++)
 	{
-		zbx_prometheus_row_t	*row =rows->values[i];
-		char			*hint_type;
+		zbx_prometheus_row_t	*row = rows->values[i];
 
 		zbx_json_addobject(&json, NULL);
-		zbx_json_addstring(&json, ZBX_PROTO_TAG_NAME, row->metric, ZBX_JSON_TYPE_STRING);
-		zbx_json_addstring(&json, ZBX_PROTO_TAG_VALUE, row->value, ZBX_JSON_TYPE_STRING);
-		zbx_json_addstring(&json, ZBX_PROTO_TAG_LINE_RAW, row->raw, ZBX_JSON_TYPE_STRING);
+		str_loc_dup_alloc(&val, &val_alloc, data, &row->metric);
+		zbx_json_addstring(&json, ZBX_PROTO_TAG_NAME, val, ZBX_JSON_TYPE_STRING);
+		str_loc_dup_alloc(&val, &val_alloc, data, &row->value);
+		zbx_json_addstring(&json, ZBX_PROTO_TAG_VALUE, val, ZBX_JSON_TYPE_STRING);
+		str_loc_dup_alloc(&val, &val_alloc, data, &row->raw);
+		zbx_json_addstring(&json, ZBX_PROTO_TAG_LINE_RAW, val, ZBX_JSON_TYPE_STRING);
 
 		if (0 != row->labels.values_num)
 		{
@@ -2061,32 +2131,52 @@ static void	prometheus_to_json(zbx_vector_prometheus_row_t *rows, zbx_hashset_t
 
 			for (j = 0; j < row->labels.values_num; j++)
 			{
-				zbx_prometheus_label_t	*label = row->labels.values[j];
+				zbx_prometheus_label_t	*label = &row->labels.values[j];
 
-				zbx_json_addstring(&json, label->name, label->value, ZBX_JSON_TYPE_STRING);
+				str_loc_dup_alloc(&key, &key_alloc, data, &label->name);
+				str_loc_unquote_alloc(&val, &val_alloc, data, &label->value);
+				zbx_json_addstring(&json, key, val, ZBX_JSON_TYPE_STRING);
 			}
 
 			zbx_json_close(&json);
 		}
 
 		hint_local.metric = row->metric;
+		hint_local.data = data;
 		hint = (zbx_prometheus_hint_t *)zbx_hashset_search(hints, &hint_local);
 
 #define ZBX_PROMETHEUS_TYPE_UNTYPED	"untyped"
+		if (NULL != hint && FAIL == zbx_strloc_is_null(&hint->type))
+		{
+			char	*hint_type = str_loc_unescape_hint_dyn(hint->data, &hint->type);
 
-		hint_type = (NULL != hint && NULL != hint->type ? hint->type : ZBX_PROMETHEUS_TYPE_UNTYPED);
-		zbx_json_addstring(&json, ZBX_PROTO_TAG_TYPE, hint_type, ZBX_JSON_TYPE_STRING);
+			zbx_json_addstring(&json, ZBX_PROTO_TAG_TYPE, hint_type, ZBX_JSON_TYPE_STRING);
+			zbx_free(hint_type);
+		}
+		else
+		{
+			zbx_json_addstring(&json, ZBX_PROTO_TAG_TYPE, ZBX_PROMETHEUS_TYPE_UNTYPED,
+					ZBX_JSON_TYPE_STRING);
+		}
 
 #undef ZBX_PROMETHEUS_TYPE_UNTYPED
 
-		if (NULL != hint && NULL != hint->help)
-			zbx_json_addstring(&json, ZBX_PROTO_TAG_HELP, hint->help, ZBX_JSON_TYPE_STRING);
+		if (NULL != hint && FAIL == zbx_strloc_is_null(&hint->help))
+		{
+			char	*hint_help = str_loc_unescape_hint_dyn(hint->data, &hint->help);
+
+			zbx_json_addstring(&json, ZBX_PROTO_TAG_HELP, hint_help, ZBX_JSON_TYPE_STRING);
+			zbx_free(hint_help);
+		}
 
 		zbx_json_close(&json);
 	}
 
 	*value = zbx_strdup(NULL, json.buffer);
 	zbx_json_free(&json);
+
+	zbx_free(val);
+	zbx_free(key);
 }
 
 /******************************************************************************
@@ -2120,9 +2210,9 @@ int	zbx_prometheus_to_json_ex(zbx_prometheus_t *prom, const char *filter_data, c
 
 	zbx_vector_prometheus_row_create(&rows);
 
-	prometheus_filter_rows(&prom->rows, &filter, &rows);
+	prometheus_filter_rows(prom->data, &prom->rows, &filter, &rows);
 
-	prometheus_to_json(&rows, &prom->hints, value);
+	prometheus_to_json(prom->data, &rows, &prom->hints, value);
 	zbx_vector_prometheus_row_destroy(&rows);
 	prometheus_filter_clear(&filter);
 
@@ -2163,11 +2253,10 @@ int	zbx_prometheus_to_json(const char *data, const char *filter_data, char **val
 	}
 
 	zbx_vector_prometheus_row_create(&rows);
-	zbx_hashset_create_ext(&hints, 100, prometheus_hint_hash, prometheus_hint_compare, prometheus_hint_clear,
-			ZBX_DEFAULT_MEM_MALLOC_FUNC, ZBX_DEFAULT_MEM_REALLOC_FUNC, ZBX_DEFAULT_MEM_FREE_FUNC);
+	zbx_hashset_create(&hints, 100, prometheus_hint_hash, prometheus_hint_compare);
 
 	if (FAIL != (ret = prometheus_parse_rows(&filter, data, &rows, &hints, error)))
-		prometheus_to_json(&rows, &hints, value);
+		prometheus_to_json(data, &rows, &hints, value);
 
 	zbx_hashset_destroy(&hints);
 
diff --git a/tests/libs/zbxprometheus/prometheus_test.c b/tests/libs/zbxprometheus/prometheus_test.c
index a6ea1300fca..372a20e2034 100644
--- a/tests/libs/zbxprometheus/prometheus_test.c
+++ b/tests/libs/zbxprometheus/prometheus_test.c
@@ -81,8 +81,10 @@ int	zbx_prometheus_row_parse(const char *data, char **metric, zbx_vector_ptr_pai
 		zbx_strloc_t *loc, char **error)
 {
 	zbx_prometheus_filter_t	filter;
-	int			i;
+	int			i, ret;
 	zbx_prometheus_row_t	*prow;
+	char			*buf = NULL;
+	size_t			buf_alloc = 0;
 
 	if (FAIL == prometheus_filter_init(&filter, "", error))
 	{
@@ -90,27 +92,31 @@ int	zbx_prometheus_row_parse(const char *data, char **metric, zbx_vector_ptr_pai
 		return FAIL;
 	}
 
-	if (FAIL == prometheus_parse_row(&filter, data, 0, &prow, loc, error))
+	ret = prometheus_parse_row(&filter, data, 0, &prow, loc, &buf, &buf_alloc, error);
+	zbx_free(buf);
+
+	if (FAIL == ret)
 	{
 		zabbix_log(LOG_LEVEL_DEBUG, "failed to parse prometheus row: %s", *error);
 		return FAIL;
 	}
 
-	*metric = prow->metric;
-	prow->metric = NULL;
-	*value = prow->value;
-	prow->value = NULL;
+	*metric = str_loc_dup(data, &prow->metric);
+	*value = str_loc_dup(data, &prow->value);
 
 	for (i = 0; i < prow->labels.values_num; i++)
 	{
-		zbx_prometheus_label_t	*label = prow->labels.values[i];
-		zbx_ptr_pair_t		pair = {label->name, label->value};
+		zbx_prometheus_label_t	*label = &prow->labels.values[i];
+		zbx_ptr_pair_t		pair;
+
+		pair.first = str_loc_dup(data, &label->name);
+		pair.second = str_loc_unquote_dyn(data, &label->value);
 
 		zbx_vector_ptr_pair_append_ptr(labels, &pair);
 	}
 
 	/* free only label structure not internals - they're used */
-	zbx_vector_prometheus_label_clear_ext(&prow->labels, (zbx_prometheus_label_free_func_t)zbx_ptr_free);
+	zbx_vector_prometheus_label_clear(&prow->labels);
 	prometheus_row_free(prow);
 
 	return SUCCEED;
