diff --git a/create/bin/gen_schema.pl b/create/bin/gen_schema.pl
index eec39ad7bc..daf589daa0 100755
--- a/create/bin/gen_schema.pl
+++ b/create/bin/gen_schema.pl
@@ -540,10 +540,22 @@ sub process_index
 			{
 				s/,/`,`/g;
 			}
-			print "CREATE${unique} INDEX `${table_name}_$name` ON `$table_name` (`$fields`);${eol}\n";
+
+			my $quote_index = "`$fields`";
+
+			for ($quote_index)
+			{
+				s/\)`/\)/g;
+				s/\(/`\(/g;
+			}
+			print "CREATE${unique} INDEX `${table_name}_$name` ON `$table_name` ($quote_index);${eol}\n";
 		}
 		else
 		{
+			for ($fields)
+			{
+				s/\(\d+\)//g;
+			}
 			print "CREATE${unique} INDEX ${table_name}_$name ON $table_name ($fields);${eol}\n";
 		}
 	}
diff --git a/create/src/schema.tmpl b/create/src/schema.tmpl
index d7bbf3fafa..19fe93977c 100644
--- a/create/src/schema.tmpl
+++ b/create/src/schema.tmpl
@@ -214,7 +214,7 @@ TABLE|dchecks|dcheckid|ZBX_DATA
 FIELD		|dcheckid	|t_id		|	|NOT NULL	|0
 FIELD		|druleid	|t_id		|	|NOT NULL	|ZBX_PROXY		|1|drules
 FIELD		|type		|t_integer	|'0'	|NOT NULL	|ZBX_PROXY
-FIELD		|key_		|t_varchar(512)	|''	|NOT NULL	|ZBX_PROXY
+FIELD		|key_		|t_varchar(2048)|''	|NOT NULL	|ZBX_PROXY
 FIELD		|snmp_community	|t_varchar(255)	|''	|NOT NULL	|ZBX_PROXY
 FIELD		|ports		|t_varchar(255)	|'0'	|NOT NULL	|ZBX_PROXY
 FIELD		|snmpv3_securityname|t_varchar(64)|''	|NOT NULL	|ZBX_PROXY
@@ -299,7 +299,7 @@ FIELD		|snmp_community	|t_varchar(64)	|''	|NOT NULL	|ZBX_PROXY
 FIELD		|snmp_oid	|t_varchar(512)	|''	|NOT NULL	|ZBX_PROXY
 FIELD		|hostid		|t_id		|	|NOT NULL	|ZBX_PROXY		|1|hosts
 FIELD		|name		|t_varchar(255)	|''	|NOT NULL	|0
-FIELD		|key_		|t_varchar(255)	|''	|NOT NULL	|ZBX_PROXY
+FIELD		|key_		|t_varchar(2048)|''	|NOT NULL	|ZBX_PROXY
 FIELD		|delay		|t_varchar(1024)|'0'	|NOT NULL	|ZBX_PROXY
 FIELD		|history	|t_varchar(255)	|'90d'	|NOT NULL	|0
 FIELD		|trends		|t_varchar(255)	|'365d'	|NOT NULL	|0
@@ -356,7 +356,7 @@ FIELD		|ssl_key_password|t_varchar(64)	|''	|NOT NULL	|ZBX_PROXY,ZBX_NODATA
 FIELD		|verify_peer	|t_integer	|'0'	|NOT NULL	|ZBX_PROXY
 FIELD		|verify_host	|t_integer	|'0'	|NOT NULL	|ZBX_PROXY
 FIELD		|allow_traps	|t_integer	|'0'	|NOT NULL	|ZBX_PROXY
-UNIQUE		|1		|hostid,key_
+INDEX		|1		|hostid,key_(1021)
 INDEX		|3		|status
 INDEX		|4		|templateid
 INDEX		|5		|valuemapid
@@ -1302,7 +1302,7 @@ TABLE|item_discovery|itemdiscoveryid|ZBX_TEMPLATE
 FIELD		|itemdiscoveryid|t_id		|	|NOT NULL	|0
 FIELD		|itemid		|t_id		|	|NOT NULL	|0			|1|items
 FIELD		|parent_itemid	|t_id		|	|NOT NULL	|0			|2|items	|itemid
-FIELD		|key_		|t_varchar(255)	|''	|NOT NULL	|ZBX_NODATA
+FIELD		|key_		|t_varchar(2048)|''	|NOT NULL	|ZBX_NODATA
 FIELD		|lastcheck	|t_integer	|'0'	|NOT NULL	|ZBX_NODATA
 FIELD		|ts_delete	|t_time		|'0'	|NOT NULL	|ZBX_NODATA
 UNIQUE		|1		|itemid,parent_itemid
@@ -1651,4 +1651,4 @@ INDEX|1|maintenanceid
 TABLE|dbversion||
 FIELD		|mandatory	|t_integer	|'0'	|NOT NULL	|
 FIELD		|optional	|t_integer	|'0'	|NOT NULL	|
-ROW		|4000000	|4000004
+ROW		|4000000	|4000011
diff --git a/frontends/php/app/views/popup.generic.php b/frontends/php/app/views/popup.generic.php
index e7eb403ab3..e31b60be87 100644
--- a/frontends/php/app/views/popup.generic.php
+++ b/frontends/php/app/views/popup.generic.php
@@ -439,7 +439,7 @@ switch ($data['popup_type']) {
 					($options['hostid'] > 0) ? null : $item['hostname'],
 					$data['multiselect'] ? new CCheckBox('item[' . $checkbox_key . ']', $item['itemid']) : null,
 					$description,
-					$item['key_'],
+					(new CDiv($item['key_']))->addClass(ZBX_STYLE_WORDWRAP),
 					item_type2str($item['type']),
 					itemValueTypeString($item['value_type']),
 					(new CSpan(itemIndicator($item['status'], $item['state'])))
@@ -473,7 +473,7 @@ switch ($data['popup_type']) {
 							CJs::encodeJson($item['itemid']).', '.
 							$options['parentid'].
 							');'.$js_action_onclick),
-					$item['key_'],
+					(new CDiv($item['key_']))->addClass(ZBX_STYLE_WORDWRAP),
 					item_type2str($item['type']),
 					itemValueTypeString($item['value_type']),
 					(new CSpan(itemIndicator($item['status'], $item['state'])))
diff --git a/frontends/php/include/classes/api/services/CDRule.php b/frontends/php/include/classes/api/services/CDRule.php
index 49f217e29c..90051934d4 100644
--- a/frontends/php/include/classes/api/services/CDRule.php
+++ b/frontends/php/include/classes/api/services/CDRule.php
@@ -514,10 +514,11 @@ class CDRule extends CApiService {
 					}
 
 					$length = mb_strlen($dcheck['key_']);
-					if ($length > 255) {
+					$max_length = DB::getFieldLength('dchecks', 'key_');
+					if ($length > $max_length) {
 						self::exception(ZBX_API_ERROR_PARAMETERS,
 							_s('Incorrect value for field "%1$s": %2$s.', 'key_',
-								_s('%1$d characters exceeds maximum length of %2$d characters', $length, 255)
+								_s('%1$d characters exceeds maximum length of %2$d characters', $length, $max_length)
 							)
 						);
 					}
diff --git a/frontends/php/include/classes/screens/CScreenProblem.php b/frontends/php/include/classes/screens/CScreenProblem.php
index 60de9d8f9f..6fa727cf0e 100644
--- a/frontends/php/include/classes/screens/CScreenProblem.php
+++ b/frontends/php/include/classes/screens/CScreenProblem.php
@@ -1046,11 +1046,11 @@ class CScreenProblem extends CScreenBase {
 					$description[] = BR();
 
 					if ($trigger['recovery_mode'] == ZBX_RECOVERY_MODE_RECOVERY_EXPRESSION) {
-						$description[] = [_('Problem'), ': ', $trigger['expression_html'], BR()];
-						$description[] = [_('Recovery'), ': ', $trigger['recovery_expression_html']];
+						$description[] = [_('Problem'), ': ', (new CDiv($trigger['expression_html']))->addClass(ZBX_STYLE_WORDWRAP), BR()];
+						$description[] = [_('Recovery'), ': ', (new CDiv($trigger['recovery_expression_html']))->addClass(ZBX_STYLE_WORDWRAP)];
 					}
 					else {
-						$description[] = $trigger['expression_html'];
+						$description[] = (new CDiv($trigger['expression_html']))->addClass(ZBX_STYLE_WORDWRAP);
 					}
 				}
 
diff --git a/frontends/php/include/schema.inc.php b/frontends/php/include/schema.inc.php
index eb4a99d174..fe262a09f0 100644
--- a/frontends/php/include/schema.inc.php
+++ b/frontends/php/include/schema.inc.php
@@ -925,7 +925,7 @@ return [
 			'key_' => [
 				'null' => false,
 				'type' => DB::FIELD_TYPE_CHAR,
-				'length' => 512,
+				'length' => 2048,
 				'default' => '',
 			],
 			'snmp_community' => [
@@ -1333,7 +1333,7 @@ return [
 			'key_' => [
 				'null' => false,
 				'type' => DB::FIELD_TYPE_CHAR,
-				'length' => 255,
+				'length' => 2048,
 				'default' => '',
 			],
 			'delay' => [
@@ -6004,7 +6004,7 @@ return [
 			'key_' => [
 				'null' => false,
 				'type' => DB::FIELD_TYPE_CHAR,
-				'length' => 255,
+				'length' => 2048,
 				'default' => '',
 			],
 			'lastcheck' => [
diff --git a/frontends/php/include/triggers.inc.php b/frontends/php/include/triggers.inc.php
index c1762cb564..490bca17a0 100644
--- a/frontends/php/include/triggers.inc.php
+++ b/frontends/php/include/triggers.inc.php
@@ -1269,11 +1269,11 @@ function make_trigger_details($trigger) {
 	$table
 		->addRow([
 			new CCol(_('Problem expression')),
-			new CCol($trigger['expression'])
+			new CCol((new CDiv($trigger['expression']))->addClass(ZBX_STYLE_WORDWRAP))
 		])
 		->addRow([
 			new CCol(_('Recovery expression')),
-			new CCol($trigger['recovery_expression'])
+			new CCol((new CDiv($trigger['recovery_expression']))->addClass(ZBX_STYLE_WORDWRAP))
 		])
 		->addRow([_('Event generation'), _('Normal').((TRIGGER_MULT_EVENT_ENABLED == $trigger['type'])
 			? SPACE.'+'.SPACE._('Multiple PROBLEM events')
diff --git a/frontends/php/include/views/configuration.host.discovery.edit.php b/frontends/php/include/views/configuration.host.discovery.edit.php
index f968e81303..79da647ded 100644
--- a/frontends/php/include/views/configuration.host.discovery.edit.php
+++ b/frontends/php/include/views/configuration.host.discovery.edit.php
@@ -66,7 +66,7 @@ else {
 // append key to form list
 $itemFormList->addRow(
 	(new CLabel(_('Key'), 'key'))->setAsteriskMark(),
-	(new CTextBox('key', $this->data['key'], $this->data['limited']))
+	(new CTextBox('key', $this->data['key'], $this->data['limited'], DB::getFieldLength('item_discovery', 'key_')))
 		->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
 		->setAriaRequired()
 );
diff --git a/frontends/php/include/views/configuration.host.discovery.list.php b/frontends/php/include/views/configuration.host.discovery.list.php
index 00476fc26c..359b9c21c8 100644
--- a/frontends/php/include/views/configuration.host.discovery.list.php
+++ b/frontends/php/include/views/configuration.host.discovery.list.php
@@ -132,7 +132,7 @@ foreach ($data['discoveries'] as $discovery) {
 			CViewHelper::showNum($discovery['graphs'])
 		],
 		$hostPrototypeLink,
-		$discovery['key_'],
+		(new CDiv(CHtml::encode($discovery['key_'])))->addClass(ZBX_STYLE_WORDWRAP),
 		$discovery['delay'],
 		item_type2str($discovery['type']),
 		$status,
diff --git a/frontends/php/include/views/configuration.item.edit.php b/frontends/php/include/views/configuration.item.edit.php
index 65843da8d1..77f30fbb25 100644
--- a/frontends/php/include/views/configuration.item.edit.php
+++ b/frontends/php/include/views/configuration.item.edit.php
@@ -81,7 +81,7 @@ else {
 }
 
 // Append key to form list.
-$key_controls = [(new CTextBox('key', $data['key'], $readonly))
+$key_controls = [(new CTextBox('key', $data['key'], $readonly, DB::getFieldLength('items', 'key_')))
 	->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
 	->setAriaRequired()
 ];
diff --git a/frontends/php/include/views/configuration.item.list.php b/frontends/php/include/views/configuration.item.list.php
index af5d9ccea9..a0cf87ab1b 100644
--- a/frontends/php/include/views/configuration.item.list.php
+++ b/frontends/php/include/views/configuration.item.list.php
@@ -181,7 +181,7 @@ foreach ($data['items'] as $item) {
 		$triggerHintTable->addRow([
 			getSeverityCell($trigger['priority'], $this->data['config']),
 			$trigger_description,
-			$expression,
+			(new CDiv($expression))->addClass(ZBX_STYLE_WORDWRAP),
 			(new CSpan(triggerIndicator($trigger['status'], $trigger['state'])))
 				->addClass(triggerIndicatorStyle($trigger['status'], $trigger['state']))
 		]);
@@ -224,7 +224,7 @@ foreach ($data['items'] as $item) {
 		empty($this->data['filter_hostid']) ? $item['host'] : null,
 		$description,
 		$triggerInfo,
-		CHtml::encode($item['key_']),
+		(new CDiv(CHtml::encode($item['key_'])))->addClass(ZBX_STYLE_WORDWRAP),
 		$item['delay'],
 		$item['history'],
 		$item['trends'],
diff --git a/frontends/php/include/views/configuration.item.prototype.edit.php b/frontends/php/include/views/configuration.item.prototype.edit.php
index 74f4f0b0af..d608f6703f 100644
--- a/frontends/php/include/views/configuration.item.prototype.edit.php
+++ b/frontends/php/include/views/configuration.item.prototype.edit.php
@@ -70,7 +70,7 @@ else {
 
 // append key to form list
 $key_controls = [
-	(new CTextBox('key', $this->data['key'], $readonly))
+	(new CTextBox('key', $this->data['key'], $readonly, DB::getFieldLength('item_discovery', 'key_')))
 		->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
 		->setAriaRequired()
 ];
diff --git a/frontends/php/include/views/configuration.item.prototype.list.php b/frontends/php/include/views/configuration.item.prototype.list.php
index 4d21f47f1e..fc0392b26c 100644
--- a/frontends/php/include/views/configuration.item.prototype.list.php
+++ b/frontends/php/include/views/configuration.item.prototype.list.php
@@ -147,7 +147,7 @@ foreach ($data['items'] as $item) {
 		new CCheckBox('group_itemid['.$item['itemid'].']', $item['itemid']),
 		$wizard,
 		$description,
-		$item['key_'],
+		(new CDiv($item['key_']))->addClass(ZBX_STYLE_WORDWRAP),
 		$item['delay'],
 		$item['history'],
 		$item['trends'],
diff --git a/frontends/php/include/views/configuration.trigger.prototype.edit.php b/frontends/php/include/views/configuration.trigger.prototype.edit.php
index 9e6e25d341..f3f316dd30 100644
--- a/frontends/php/include/views/configuration.trigger.prototype.edit.php
+++ b/frontends/php/include/views/configuration.trigger.prototype.edit.php
@@ -213,7 +213,7 @@ if ($data['expression_constructor'] == IM_TREE) {
 							->setChecked($i == 0)
 							->onClick('check_target(this, '.TRIGGER_EXPRESSION.');')
 						: null,
-					$e['list'],
+					(new CDiv($e['list']))->addClass(ZBX_STYLE_WORDWRAP),
 					!$data['limited']
 						? (new CCol(
 							(new CSimpleButton(_('Remove')))
diff --git a/frontends/php/include/views/configuration.trigger.prototype.list.php b/frontends/php/include/views/configuration.trigger.prototype.list.php
index c1930c9f11..2bf0e1f2e7 100644
--- a/frontends/php/include/views/configuration.trigger.prototype.list.php
+++ b/frontends/php/include/views/configuration.trigger.prototype.list.php
@@ -141,7 +141,7 @@ foreach ($this->data['triggers'] as $trigger) {
 		$checkBox,
 		getSeverityCell($trigger['priority'], $this->data['config']),
 		$description,
-		$expression,
+		(new CDiv($expression))->addClass(ZBX_STYLE_WORDWRAP),
 		$status,
 		$data['tags'][$triggerid]
 	]);
diff --git a/frontends/php/include/views/configuration.triggers.edit.php b/frontends/php/include/views/configuration.triggers.edit.php
index 38e22d0340..ceb4371d47 100644
--- a/frontends/php/include/views/configuration.triggers.edit.php
+++ b/frontends/php/include/views/configuration.triggers.edit.php
@@ -187,7 +187,7 @@ $triggersFormList->addRow(
 
 // Append expression table to form list.
 if ($data['expression_constructor'] == IM_TREE) {
-	$expressionTable = (new CTable())
+	$expression_table = (new CTable())
 		->setAttribute('style', 'width: 100%;')
 		->setHeader([
 			$readonly ? null : _('Target'),
@@ -227,7 +227,7 @@ if ($data['expression_constructor'] == IM_TREE) {
 				unset($obj);
 			}
 
-			$expressionTable->addRow(
+			$expression_table->addRow(
 				new CRow([
 					!$readonly
 						? (new CCheckBox('expr_target_single', $e['id']))
@@ -235,7 +235,7 @@ if ($data['expression_constructor'] == IM_TREE) {
 							->onClick('check_target(this, '.TRIGGER_EXPRESSION.');')
 							->removeId()
 						: null,
-					$e['list'],
+					(new CDiv($e['list']))->addClass(ZBX_STYLE_WORDWRAP),
 					!$readonly
 						? (new CCol(
 							(new CSimpleButton(_('Remove')))
@@ -277,7 +277,7 @@ if ($data['expression_constructor'] == IM_TREE) {
 		$wrapOutline,
 		BR(),
 		BR(),
-		(new CDiv([$expressionTable, $testButton]))
+		(new CDiv([$expression_table, $testButton]))
 			->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
 			->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
 	]);
@@ -432,7 +432,7 @@ if ($data['recovery_expression_constructor'] == IM_TREE) {
 							->onClick('check_target(this, '.TRIGGER_RECOVERY_EXPRESSION.');')
 							->removeId()
 						: null,
-					$e['list'],
+					(new CDiv($e['list']))->addClass(ZBX_STYLE_WORDWRAP),
 					!$readonly
 						? (new CCol(
 							(new CSimpleButton(_('Remove')))
diff --git a/frontends/php/include/views/configuration.triggers.list.php b/frontends/php/include/views/configuration.triggers.list.php
index c02ec8a59d..c9bf78df85 100644
--- a/frontends/php/include/views/configuration.triggers.list.php
+++ b/frontends/php/include/views/configuration.triggers.list.php
@@ -231,7 +231,7 @@ foreach ($data['triggers'] as $tnum => $trigger) {
 	if ($data['showInfoColumn']) {
 		$info_icons = [];
 		if ($trigger['status'] == TRIGGER_STATUS_ENABLED && $trigger['error']) {
-			$info_icons[] = makeErrorIcon($trigger['error']);
+			$info_icons[] = makeErrorIcon((new CDiv($trigger['error']))->addClass(ZBX_STYLE_WORDWRAP));
 		}
 	}
 
@@ -283,7 +283,7 @@ foreach ($data['triggers'] as $tnum => $trigger) {
 		$data['show_value_column'] ? $trigger_value : null,
 		$hosts,
 		$description,
-		$expression,
+		(new CDiv($expression))->addClass(ZBX_STYLE_WORDWRAP),
 		$status,
 		$data['showInfoColumn'] ? makeInformationList($info_icons) : null,
 		$data['tags'][$triggerid]
diff --git a/frontends/php/include/views/js/configuration.discovery.edit.js.php b/frontends/php/include/views/js/configuration.discovery.edit.js.php
index 903b732854..0b0516ff2e 100644
--- a/frontends/php/include/views/js/configuration.discovery.edit.js.php
+++ b/frontends/php/include/views/js/configuration.discovery.edit.js.php
@@ -21,7 +21,7 @@
 			(new CInput('radio', 'uniqueness_criteria', '#{dcheckid}'))
 				->addClass(ZBX_STYLE_CHECKBOX_RADIO)
 				->setId('uniqueness_criteria_#{dcheckid}'),
-			(new CLabel([new CSpan(), '#{name}'], 'uniqueness_criteria_#{dcheckid}'))
+			(new CLabel([new CSpan(), '#{name}'], 'uniqueness_criteria_#{dcheckid}'))->addClass(ZBX_STYLE_WORDWRAP)
 				->addClass(ZBX_STYLE_WORDWRAP)
 		]))
 			->setId('uniqueness_criteria_row_#{dcheckid}')
@@ -53,7 +53,7 @@
 				)
 				->addRow(
 					(new CLabel(_('Key'), 'key_'))->setAsteriskMark(),
-					(new CTextBox('key_'))
+					(new CTextBox('key_', '', false, DB::getFieldLength('items', 'key_')))
 						->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH)
 						->setAriaRequired(),
 					'newCheckKeyRow'
@@ -650,7 +650,9 @@
 			jQuery('#add_new_dcheck').prop('disabled', false);
 
 			if (validationErrors.length) {
-				var content = jQuery('<span>');
+				var content = jQuery('<div>')
+						.addClass('<?= ZBX_STYLE_WORDWRAP ?>')
+						.css({whiteSpace: 'normal'});
 
 				for (var i = 0; i < validationErrors.length; i++) {
 					if (content.html() !== '') {
diff --git a/frontends/php/js/main.js b/frontends/php/js/main.js
index 59f21580f6..ee1955a3cf 100644
--- a/frontends/php/js/main.js
+++ b/frontends/php/js/main.js
@@ -460,7 +460,7 @@ var hintBox = {
 		}
 
 		if (!empty(className)) {
-			box.append(jQuery('<span></span>').addClass(className).html(hintText));
+			box.append(jQuery('<div></div>').addClass(className).html(hintText));
 		}
 		else {
 			box.html(hintText);
diff --git a/include/common.h b/include/common.h
index 83e3360f83..78aaf492ca 100644
--- a/include/common.h
+++ b/include/common.h
@@ -1121,6 +1121,10 @@ void	zbx_backtrace(void);
 int	int_in_list(char *list, int value);
 int	ip_in_list(const char *list, const char *ip);
 
+#define VALUE_ERRMSG_MAX	128
+const char	*zbx_truncate_itemkey(const char *key, const size_t char_max, char *buf, const size_t buf_len);
+const char	*zbx_truncate_value(const char *val, const size_t char_max, char *buf, const size_t buf_len);
+
 /* IP range support */
 #define ZBX_IPRANGE_V4	0
 #define ZBX_IPRANGE_V6	1
@@ -1196,6 +1200,7 @@ size_t	zbx_utf8_char_len(const char *text);
 size_t	zbx_strlen_utf8(const char *text);
 size_t	zbx_strlen_utf8_nchars(const char *text, size_t utf8_maxlen);
 size_t	zbx_strlen_utf8_nbytes(const char *text, size_t maxlen);
+size_t	zbx_charcount_utf8_nbytes(const char *text, size_t maxlen);
 
 int	zbx_is_utf8(const char *text);
 #define ZBX_UTF8_REPLACE_CHAR	'?'
diff --git a/include/db.h b/include/db.h
index 2e3fa95d28..f4dfcc1918 100644
--- a/include/db.h
+++ b/include/db.h
@@ -105,7 +105,7 @@ struct	_DC_TRIGGER;
 #define INTERFACE_PORT_LEN_MAX		(INTERFACE_PORT_LEN + 1)
 
 #define ITEM_NAME_LEN			255
-#define ITEM_KEY_LEN			255
+#define ITEM_KEY_LEN			2048
 #define ITEM_DELAY_LEN			1024
 #define ITEM_HISTORY_LEN		255
 #define ITEM_TRENDS_LEN			255
diff --git a/src/libs/zbxcommon/str.c b/src/libs/zbxcommon/str.c
index 2c5c181681..8762ed39c7 100644
--- a/src/libs/zbxcommon/str.c
+++ b/src/libs/zbxcommon/str.c
@@ -2013,6 +2013,30 @@ size_t	zbx_strlen_utf8_nbytes(const char *text, size_t maxlen)
 	return sz;
 }
 
+/******************************************************************************
+ *                                                                            *
+ * Function: zbx_charcount_utf8_nbytes                                        *
+ *                                                                            *
+ * Purpose: calculates number of chars in utf8 text limited by maxlen bytes   *
+ *                                                                            *
+ ******************************************************************************/
+size_t	zbx_charcount_utf8_nbytes(const char *text, size_t maxlen)
+{
+	size_t	n = 0;
+
+	maxlen = zbx_strlen_utf8_nbytes(text, maxlen);
+
+	while ('\0' != *text && maxlen > 0)
+	{
+		if (0x80 != (0xc0 & *text++))
+			n++;
+
+		maxlen--;
+	}
+
+	return n;
+}
+
 /******************************************************************************
  *                                                                            *
  * Function: zbx_replace_utf8                                                 *
@@ -5187,3 +5211,136 @@ void	zbx_trim_float(char *str)
 {
 	zbx_trim_number(str, 0);
 }
+
+/******************************************************************************
+ *                                                                            *
+ * Function: zbx_truncate_itemkey                                             *
+ *                                                                            *
+ * Purpose: check the item key characters length and, if the length exceeds   *
+ *          max allowable characters length, truncate the item key, while     *
+ *          maintaining the right square bracket                              *
+ *                                                                            *
+ * Parameters: key      - [IN] item key for processing                        *
+ *             char_max - [IN] item key max characters length                 *
+ *             buf      - [IN/OUT] buffer for short version of item key       *
+ *             buf_len  - [IN] buffer size for short version of item key      *
+ *                                                                            *
+ * Return value: The item key that does not exceed passed length              *
+ *                                                                            *
+ ******************************************************************************/
+const char	*zbx_truncate_itemkey(const char *key, const size_t char_max, char *buf, const size_t buf_len)
+{
+#	define ZBX_SUFFIX	"..."
+#	define ZBX_BSUFFIX	"[...]"
+
+	size_t	key_byte_count, key_char_total;
+	int	is_bracket = 0;
+	char	*bracket_l;
+
+	if (char_max >= (key_char_total = zbx_strlen_utf8(key)))
+		return key;
+
+	if (NULL != (bracket_l = strchr(key, '[')))
+		is_bracket = 1;
+
+	if (char_max < ZBX_CONST_STRLEN(ZBX_SUFFIX) + 2 * is_bracket)	/* [...] or ... */
+		return key;
+
+	if (0 != is_bracket)
+	{
+		size_t	key_char_count, param_char_count, param_byte_count;
+
+		key_char_count = zbx_charcount_utf8_nbytes(key, bracket_l - key);
+		param_char_count = key_char_total - key_char_count;
+
+		if (param_char_count <= ZBX_CONST_STRLEN(ZBX_BSUFFIX))
+		{
+			if (char_max < param_char_count + ZBX_CONST_STRLEN(ZBX_SUFFIX))
+				return key;
+
+			key_byte_count = 1 + zbx_strlen_utf8_nchars(key, char_max - param_char_count -
+					ZBX_CONST_STRLEN(ZBX_SUFFIX));
+			param_byte_count = 1 + zbx_strlen_utf8_nchars(bracket_l, key_char_count);
+
+			if (buf_len < key_byte_count + ZBX_CONST_STRLEN(ZBX_SUFFIX) + param_byte_count - 1)
+				return key;
+
+			key_byte_count = zbx_strlcpy_utf8(buf, key, key_byte_count);
+			key_byte_count += zbx_strlcpy_utf8(&buf[key_byte_count], ZBX_SUFFIX, sizeof(ZBX_SUFFIX));
+			zbx_strlcpy_utf8(&buf[key_byte_count], bracket_l, param_byte_count);
+
+			return buf;
+		}
+
+		if (key_char_count + ZBX_CONST_STRLEN(ZBX_BSUFFIX) > char_max)
+		{
+			if (char_max <= ZBX_CONST_STRLEN(ZBX_SUFFIX) + ZBX_CONST_STRLEN(ZBX_BSUFFIX))
+				return key;
+
+			key_byte_count = 1 + zbx_strlen_utf8_nchars(key, char_max - ZBX_CONST_STRLEN(ZBX_SUFFIX) -
+					ZBX_CONST_STRLEN(ZBX_BSUFFIX));
+
+			if (buf_len < key_byte_count + ZBX_CONST_STRLEN(ZBX_SUFFIX) + ZBX_CONST_STRLEN(ZBX_BSUFFIX))
+				return key;
+
+			key_byte_count = zbx_strlcpy_utf8(buf, key, key_byte_count);
+			key_byte_count += zbx_strlcpy_utf8(&buf[key_byte_count], ZBX_SUFFIX, sizeof(ZBX_SUFFIX));
+			zbx_strlcpy_utf8(&buf[key_byte_count], ZBX_BSUFFIX, sizeof(ZBX_BSUFFIX));
+
+			return buf;
+		}
+	}
+
+	key_byte_count = 1 + zbx_strlen_utf8_nchars(key, char_max - (ZBX_CONST_STRLEN(ZBX_SUFFIX) + is_bracket));
+
+	if (buf_len < key_byte_count + ZBX_CONST_STRLEN(ZBX_SUFFIX) + is_bracket)
+		return key;
+
+	key_byte_count = zbx_strlcpy_utf8(buf, key, key_byte_count);
+	zbx_strlcpy_utf8(&buf[key_byte_count], ZBX_SUFFIX, sizeof(ZBX_SUFFIX));
+
+	if (0 != is_bracket)
+		zbx_strlcpy_utf8(&buf[key_byte_count + ZBX_CONST_STRLEN(ZBX_SUFFIX)], "]", sizeof("]"));
+
+	return buf;
+
+#	undef ZBX_SUFFIX
+#	undef ZBX_BSUFFIX
+}
+
+/******************************************************************************
+ *                                                                            *
+ * Function: zbx_truncate_value                                               *
+ *                                                                            *
+ * Purpose: check the value characters length and, if the length exceeds      *
+ *          max allowable characters length, truncate the value               *
+ *                                                                            *
+ * Parameters: val      - [IN] value for processing                           *
+ *             char_max - [IN] value max characters length                    *
+ *             buf      - [IN/OUT] buffer for short version of value          *
+ *             buf_len  - [IN] buffer size for short version of value         *
+ *                                                                            *
+ * Return value: The value that does not exceed passed length                 *
+ *                                                                            *
+ ******************************************************************************/
+const char	*zbx_truncate_value(const char *val, const size_t char_max, char *buf, const size_t buf_len)
+{
+#	define ZBX_SUFFIX	"..."
+
+	size_t	key_byte_count;
+
+	if (char_max >= zbx_strlen_utf8(val))
+		return val;
+
+	key_byte_count = 1 + zbx_strlen_utf8_nchars(val, char_max - ZBX_CONST_STRLEN(ZBX_SUFFIX));
+
+	if (buf_len < key_byte_count + ZBX_CONST_STRLEN(ZBX_SUFFIX))
+		return val;
+
+	key_byte_count = zbx_strlcpy_utf8(buf, val, key_byte_count);
+	zbx_strlcpy_utf8(&buf[key_byte_count], ZBX_SUFFIX, sizeof(ZBX_SUFFIX));
+
+	return buf;
+
+#	undef ZBX_SUFFIX
+}
diff --git a/src/libs/zbxdbhigh/lld_item.c b/src/libs/zbxdbhigh/lld_item.c
index 98a51357f1..537a8e9c2e 100644
--- a/src/libs/zbxdbhigh/lld_item.c
+++ b/src/libs/zbxdbhigh/lld_item.c
@@ -927,8 +927,16 @@ static void	lld_validate_item_field(zbx_lld_item_t *item, char **field, char **f
 	}
 	else if (zbx_strlen_utf8(*field) > field_len)
 	{
+		const char	*err_val;
+		char		key_short[VALUE_ERRMSG_MAX * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1];
+
+		if (0 != (flag & ZBX_FLAG_LLD_ITEM_UPDATE_KEY))
+			err_val = zbx_truncate_itemkey(*field, VALUE_ERRMSG_MAX, key_short, sizeof(key_short));
+		else
+			err_val = zbx_truncate_value(*field, VALUE_ERRMSG_MAX, key_short, sizeof(key_short));
+
 		*error = zbx_strdcatf(*error, "Cannot %s item: value \"%s\" is too long.\n",
-				(0 != item->itemid ? "update" : "create"), *field);
+				(0 != item->itemid ? "update" : "create"), err_val);
 	}
 	else
 	{
@@ -1508,8 +1516,12 @@ static void	lld_items_validate(zbx_uint64_t hostid, zbx_vector_ptr_t *items, zbx
 
 		if (NULL != zbx_hashset_search(&items_keys, &item->key))
 		{
+			char key_short[VALUE_ERRMSG_MAX * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1];
+
 			*error = zbx_strdcatf(*error, "Cannot %s item: item with the same key \"%s\" already exists.\n",
-						(0 != item->itemid ? "update" : "create"), item->key);
+						(0 != item->itemid ? "update" : "create"),
+						zbx_truncate_itemkey(item->key, VALUE_ERRMSG_MAX,
+						key_short, sizeof(key_short)));
 
 			if (0 != item->itemid)
 			{
@@ -1599,9 +1611,13 @@ static void	lld_items_validate(zbx_uint64_t hostid, zbx_vector_ptr_t *items, zbx
 
 				if (0 == strcmp(item->key, row[0]))
 				{
+					char key_short[VALUE_ERRMSG_MAX * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1];
+
 					*error = zbx_strdcatf(*error, "Cannot %s item:"
 							" item with the same key \"%s\" already exists.\n",
-							(0 != item->itemid ? "update" : "create"), item->key);
+							(0 != item->itemid ? "update" : "create"),
+							zbx_truncate_itemkey(item->key, VALUE_ERRMSG_MAX,
+							key_short, sizeof(key_short)));
 
 					if (0 != item->itemid)
 					{
diff --git a/src/libs/zbxdbhigh/proxy.c b/src/libs/zbxdbhigh/proxy.c
index 091f8dd517..88a71ca851 100644
--- a/src/libs/zbxdbhigh/proxy.c
+++ b/src/libs/zbxdbhigh/proxy.c
@@ -2753,21 +2753,23 @@ static int	parse_history_data_row_itemid(const struct zbx_json_parse *jp_row, zb
  ******************************************************************************/
 static int	parse_history_data_row_hostkey(const struct zbx_json_parse *jp_row, zbx_host_key_t *hk)
 {
-	char	buffer[MAX_STRING_LEN];
+	size_t str_alloc;
 
-	if (SUCCEED != zbx_json_value_by_name(jp_row, ZBX_PROTO_TAG_HOST, buffer, sizeof(buffer), NULL))
+	str_alloc = 0;
+	zbx_free(hk->host);
+
+	if (SUCCEED != zbx_json_value_by_name_dyn(jp_row, ZBX_PROTO_TAG_HOST, &hk->host, &str_alloc, NULL))
 		return FAIL;
 
-	hk->host = zbx_strdup(hk->host, buffer);
+	str_alloc = 0;
+	zbx_free(hk->key);
 
-	if (SUCCEED != zbx_json_value_by_name(jp_row, ZBX_PROTO_TAG_KEY, buffer, sizeof(buffer), NULL))
+	if (SUCCEED != zbx_json_value_by_name_dyn(jp_row, ZBX_PROTO_TAG_KEY, &hk->key, &str_alloc, NULL))
 	{
 		zbx_free(hk->host);
 		return FAIL;
 	}
 
-	hk->key = zbx_strdup(hk->key, buffer);
-
 	return SUCCEED;
 }
 
@@ -3010,6 +3012,7 @@ static int	agent_item_validator(DC_ITEM *item, zbx_socket_t *sock, void *args, c
 static int	sender_item_validator(DC_ITEM *item, zbx_socket_t *sock, void *args, char **error)
 {
 	zbx_host_rights_t	*rights;
+	char			key_short[VALUE_ERRMSG_MAX * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1];
 
 	if (0 != item->host.proxy_hostid)
 		return FAIL;
@@ -3020,7 +3023,8 @@ static int	sender_item_validator(DC_ITEM *item, zbx_socket_t *sock, void *args,
 			if (0 == item->allow_traps)
 			{
 				*error = zbx_dsprintf(*error, "cannot process HTTP agent item \"%s\" trap:"
-						" trapping is not enabled", item->key_orig);
+						" trapping is not enabled", zbx_truncate_itemkey(item->key_orig,
+						VALUE_ERRMSG_MAX, key_short, sizeof(key_short)));
 				return FAIL;
 			}
 			break;
@@ -3028,7 +3032,9 @@ static int	sender_item_validator(DC_ITEM *item, zbx_socket_t *sock, void *args,
 			break;
 		default:
 			*error = zbx_dsprintf(*error, "cannot process item \"%s\" trap:"
-					" item type \"%d\" cannot be used with traps", item->key_orig, item->type);
+					" item type \"%d\" cannot be used with traps",
+					zbx_truncate_itemkey(item->key_orig, VALUE_ERRMSG_MAX, key_short,
+					sizeof(key_short)), item->type);
 			return FAIL;
 	}
 
@@ -3046,7 +3052,8 @@ static int	sender_item_validator(DC_ITEM *item, zbx_socket_t *sock, void *args,
 		if (FAIL == ret)
 		{
 			*error = zbx_dsprintf(*error, "cannot process item \"%s\" trap: %s",
-					item->key_orig, zbx_socket_strerror());
+					zbx_truncate_itemkey(item->key_orig, VALUE_ERRMSG_MAX, key_short,
+					sizeof(key_short)), zbx_socket_strerror());
 			return FAIL;
 		}
 	}
diff --git a/src/libs/zbxdbupgrade/dbupgrade_4000.c b/src/libs/zbxdbupgrade/dbupgrade_4000.c
index 25ad7de428..9e22d74927 100644
--- a/src/libs/zbxdbupgrade/dbupgrade_4000.c
+++ b/src/libs/zbxdbupgrade/dbupgrade_4000.c
@@ -252,6 +252,52 @@ static int	DBpatch_4000004(void)
 	return SUCCEED;
 }
 
+static int	DBpatch_4000005(void)
+{
+	return DBdrop_foreign_key("items", 1);
+}
+static int	DBpatch_4000006(void)
+{
+	return DBdrop_index("items", "items_1");
+}
+
+static int	DBpatch_4000007(void)
+{
+	const ZBX_FIELD	field = {"key_", "", NULL, NULL, 2048, ZBX_TYPE_CHAR, ZBX_NOTNULL, 0};
+
+	return DBmodify_field_type("items", &field, NULL);
+}
+
+static int	DBpatch_4000008(void)
+{
+#ifdef HAVE_MYSQL
+	return DBcreate_index("items", "items_1", "hostid,key_(1021)", 0);
+#else
+	return DBcreate_index("items", "items_1", "hostid,key_", 0);
+#endif
+}
+
+static int	DBpatch_4000009(void)
+{
+	const ZBX_FIELD	field = {"hostid", NULL, "hosts", "hostid", 0, 0, 0, ZBX_FK_CASCADE_DELETE};
+
+	return DBadd_foreign_key("items", 1, &field);
+}
+
+static int	DBpatch_4000010(void)
+{
+	const ZBX_FIELD	field = {"key_", "", NULL, NULL, 2048, ZBX_TYPE_CHAR, ZBX_NOTNULL, 0};
+
+	return DBmodify_field_type("item_discovery", &field, NULL);
+}
+
+static int	DBpatch_4000011(void)
+{
+	const ZBX_FIELD	field = {"key_", "", NULL, NULL, 2048, ZBX_TYPE_CHAR, ZBX_NOTNULL, 0};
+
+	return DBmodify_field_type("dchecks", &field, NULL);
+}
+
 #endif
 
 DBPATCH_START(4000)
@@ -263,5 +309,12 @@ DBPATCH_ADD(4000001, 0, 0)
 DBPATCH_ADD(4000002, 0, 0)
 DBPATCH_ADD(4000003, 0, 0)
 DBPATCH_ADD(4000004, 0, 0)
+DBPATCH_ADD(4000005, 0, 0)
+DBPATCH_ADD(4000006, 0, 0)
+DBPATCH_ADD(4000007, 0, 0)
+DBPATCH_ADD(4000008, 0, 0)
+DBPATCH_ADD(4000009, 0, 0)
+DBPATCH_ADD(4000010, 0, 0)
+DBPATCH_ADD(4000011, 0, 0)
 
 DBPATCH_END()
diff --git a/src/zabbix_agent/active.c b/src/zabbix_agent/active.c
index 19927d351f..1a5738055e 100644
--- a/src/zabbix_agent/active.c
+++ b/src/zabbix_agent/active.c
@@ -335,7 +335,8 @@ static int	parse_list_of_checks(char *str, const char *host, unsigned short port
 {
 	const char		*__function_name = "parse_list_of_checks";
 	const char		*p;
-	char			name[MAX_STRING_LEN], key_orig[MAX_STRING_LEN], expression[MAX_STRING_LEN],
+	size_t			name_alloc = 0, key_orig_alloc = 0;
+	char			*name = NULL, *key_orig = NULL, expression[MAX_STRING_LEN],
 				tmp[MAX_STRING_LEN], exp_delimiter;
 	zbx_uint64_t		lastlogsize;
 	struct zbx_json_parse	jp;
@@ -387,16 +388,18 @@ static int	parse_list_of_checks(char *str, const char *host, unsigned short port
 			goto out;
 		}
 
-		if (SUCCEED != zbx_json_value_by_name(&jp_row, ZBX_PROTO_TAG_KEY, name, sizeof(name), NULL) ||
+		if (SUCCEED != zbx_json_value_by_name_dyn(&jp_row, ZBX_PROTO_TAG_KEY, &name, &name_alloc, NULL) ||
 				'\0' == *name)
 		{
 			zabbix_log(LOG_LEVEL_WARNING, "cannot retrieve value of tag \"%s\"", ZBX_PROTO_TAG_KEY);
 			continue;
 		}
 
-		if (SUCCEED != zbx_json_value_by_name(&jp_row, ZBX_PROTO_TAG_KEY_ORIG, key_orig, sizeof(key_orig), NULL)
-				|| '\0' == *key_orig) {
-			zbx_strlcpy(key_orig, name, sizeof(key_orig));
+		if (SUCCEED != zbx_json_value_by_name_dyn(&jp_row, ZBX_PROTO_TAG_KEY_ORIG, &key_orig, &key_orig_alloc,
+				NULL) || '\0' == *key_orig)
+		{
+			size_t offset = 0;
+			zbx_strcpy_alloc(&key_orig, &key_orig_alloc, &offset, name);
 		}
 
 		if (SUCCEED != zbx_json_value_by_name(&jp_row, ZBX_PROTO_TAG_DELAY, tmp, sizeof(tmp), NULL) ||
@@ -480,7 +483,7 @@ static int	parse_list_of_checks(char *str, const char *host, unsigned short port
 				goto out;
 			}
 
-			if (SUCCEED != zbx_json_value_by_name(&jp_row, "name", name, sizeof(name), NULL))
+			if (SUCCEED != zbx_json_value_by_name_dyn(&jp_row, "name", &name, &name_alloc, NULL))
 			{
 				zabbix_log(LOG_LEVEL_WARNING, "cannot retrieve value of tag \"%s\"", "name");
 				continue;
@@ -527,6 +530,8 @@ static int	parse_list_of_checks(char *str, const char *host, unsigned short port
 out:
 	zbx_vector_str_clear_ext(&received_metrics, zbx_str_free);
 	zbx_vector_str_destroy(&received_metrics);
+	zbx_free(key_orig);
+	zbx_free(name);
 
 	zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
 
diff --git a/src/zabbix_sender/zabbix_sender.c b/src/zabbix_sender/zabbix_sender.c
index 086991e0a8..25c73ef2ff 100644
--- a/src/zabbix_sender/zabbix_sender.c
+++ b/src/zabbix_sender/zabbix_sender.c
@@ -1021,11 +1021,11 @@ static char	*zbx_fgets_alloc(char **buffer, size_t *buffer_alloc, FILE *fp)
 int	main(int argc, char **argv)
 {
 	FILE			*in;
-	char			*in_line = NULL, hostname[MAX_STRING_LEN], key[MAX_STRING_LEN], *key_value = NULL,
-				clock[32], *error = NULL;
+	char			*in_line = NULL, hostname[MAX_STRING_LEN], *key = NULL, *key_value = NULL, clock[32],
+				*error = NULL;
 	int			total_count = 0, succeed_count = 0, buffer_count = 0, read_more = 0, ret = FAIL,
 				timestamp;
-	size_t			in_line_alloc = MAX_BUFFER_LEN, key_value_alloc = 0;
+	size_t			in_line_alloc = MAX_BUFFER_LEN, key_alloc = 0, key_value_alloc = 0;
 	double			last_send = 0;
 	const char		*p;
 	zbx_thread_args_t	thread_args;
@@ -1167,7 +1167,13 @@ int	main(int argc, char **argv)
 					zbx_strlcpy(hostname, ZABBIX_HOSTNAME, sizeof(hostname));
 			}
 
-			if ('\0' == *p || NULL == (p = get_string(p, key, sizeof(key))) || '\0' == *key)
+			if (key_alloc != in_line_alloc)
+			{
+				key_alloc = in_line_alloc;
+				key = (char *)zbx_realloc(key, key_alloc);
+			}
+
+			if ('\0' == *p || NULL == (p = get_string(p, key, key_alloc)) || '\0' == *key)
 			{
 				zabbix_log(LOG_LEVEL_CRIT, "[line %d] 'Key' required", total_count);
 				ret = FAIL;
@@ -1279,6 +1285,7 @@ int	main(int argc, char **argv)
 		if (in != stdin)
 			fclose(in);
 
+		zbx_free(key);
 		zbx_free(key_value);
 		zbx_free(in_line);
 	}
diff --git a/src/zabbix_server/escalator/escalator.c b/src/zabbix_server/escalator/escalator.c
index 9fed50edeb..d2393a8238 100644
--- a/src/zabbix_server/escalator/escalator.c
+++ b/src/zabbix_server/escalator/escalator.c
@@ -1771,7 +1771,10 @@ static int	check_escalation_trigger(zbx_uint64_t triggerid, unsigned char source
 
 		if (ITEM_STATUS_DISABLED == items[i].status)
 		{
-			*error = zbx_dsprintf(*error, "item \"%s\" disabled.", items[i].key_orig);
+			char key_short[VALUE_ERRMSG_MAX * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1];
+
+			*error = zbx_dsprintf(*error, "item \"%s\" disabled.", zbx_truncate_itemkey(items[i].key_orig,
+					VALUE_ERRMSG_MAX, key_short, sizeof(key_short)));
 			break;
 		}
 		if (HOST_STATUS_NOT_MONITORED == items[i].host.status)
@@ -1874,7 +1877,11 @@ static int	check_escalation(const DB_ESCALATION *escalation, const DB_ACTION *ac
 			}
 			else if (ITEM_STATUS_DISABLED == item.status)
 			{
-				*error = zbx_dsprintf(*error, "item \"%s\" disabled.", item.key_orig);
+				char key_short[VALUE_ERRMSG_MAX * ZBX_MAX_BYTES_IN_UTF8_CHAR + 1];
+
+				*error = zbx_dsprintf(*error, "item \"%s\" disabled.",
+						zbx_truncate_itemkey(item.key_orig, VALUE_ERRMSG_MAX,
+						key_short, sizeof(key_short)));
 			}
 			else if (HOST_STATUS_NOT_MONITORED == item.host.status)
 			{
diff --git a/tests/libs/zbxcommon/Makefile.am b/tests/libs/zbxcommon/Makefile.am
index 00a17df5c3..b7bdae252c 100644
--- a/tests/libs/zbxcommon/Makefile.am
+++ b/tests/libs/zbxcommon/Makefile.am
@@ -15,7 +15,9 @@ SERVER_tests = \
 	zbx_trim_integer \
 	zbx_variant_compare \
 	zbx_user_macro_parse \
-	convert_to_utf8
+	convert_to_utf8 \
+	zbx_truncate_itemkey \
+	zbx_truncate_value
 endif
 
 noinst_PROGRAMS = $(SERVER_tests)
@@ -298,6 +300,7 @@ zbx_user_macro_parse_LDFLAGS = @SERVER_LDFLAGS@
 
 zbx_user_macro_parse_CFLAGS = $(COMMON_COMPILER_FLAGS)
 
+
 convert_to_utf8_SOURCES = \
      convert_to_utf8.c \
      $(COMMON_SRC_FILES)
@@ -311,4 +314,32 @@ convert_to_utf8_LDFLAGS = @SERVER_LDFLAGS@
 
 convert_to_utf8_CFLAGS = $(COMMON_COMPILER_FLAGS)
 
+
+zbx_truncate_itemkey_SOURCES = \
+	zbx_truncate_itemkey.c \
+	$(COMMON_SRC_FILES)
+
+zbx_truncate_itemkey_LDADD = \
+	$(COMMON_LIB_FILES)
+
+zbx_truncate_itemkey_LDADD += @SERVER_LIBS@
+
+zbx_truncate_itemkey_LDFLAGS = @SERVER_LDFLAGS@
+
+zbx_truncate_itemkey_CFLAGS = $(COMMON_COMPILER_FLAGS)
+
+
+zbx_truncate_value_SOURCES = \
+	zbx_truncate_value.c \
+	$(COMMON_SRC_FILES)
+
+zbx_truncate_value_LDADD = \
+	$(COMMON_LIB_FILES)
+
+zbx_truncate_value_LDADD += @SERVER_LIBS@
+
+zbx_truncate_value_LDFLAGS = @SERVER_LDFLAGS@
+
+zbx_truncate_value_CFLAGS = $(COMMON_COMPILER_FLAGS)
+
 endif
diff --git a/tests/libs/zbxcommon/zbx_truncate_itemkey.c b/tests/libs/zbxcommon/zbx_truncate_itemkey.c
new file mode 100644
index 0000000000..9d4e2b07aa
--- /dev/null
+++ b/tests/libs/zbxcommon/zbx_truncate_itemkey.c
@@ -0,0 +1,45 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2019 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "zbxmocktest.h"
+#include "zbxmockutil.h"
+#include "zbxmockassert.h"
+
+void	zbx_mock_test_entry(void **state)
+{
+	size_t		key_len, buf_len;
+	char		*buf;
+	const char	*key, *exp_result, *act_result;
+
+	ZBX_UNUSED(state);
+
+	key = zbx_mock_get_parameter_string("in.key");
+	key_len = zbx_mock_get_parameter_uint64("in.key_len");
+	buf_len = zbx_mock_get_parameter_uint64("in.buf_len");
+
+	buf = (char *)zbx_malloc(NULL, buf_len);
+
+	exp_result = zbx_mock_get_parameter_string("out.key");
+
+	act_result = zbx_truncate_itemkey(key, key_len, buf, buf_len);
+
+	zbx_mock_assert_str_eq("return value", exp_result, act_result);
+
+	zbx_free(buf);
+}
diff --git a/tests/libs/zbxcommon/zbx_truncate_itemkey.yaml b/tests/libs/zbxcommon/zbx_truncate_itemkey.yaml
new file mode 100644
index 0000000000..25136f12a0
--- /dev/null
+++ b/tests/libs/zbxcommon/zbx_truncate_itemkey.yaml
@@ -0,0 +1,309 @@
+test case: "#0 condition 1.1"
+in:
+  key: "0123456789[]"
+  key_len: 5
+  buf_len: 6
+out:
+  key: "...[]"
+---
+test case: "#1 condition 1.2"
+in:
+  key: "0123456789[]"
+  key_len: 10
+  buf_len: 11
+out:
+  key: "01234...[]"
+---
+test case: "#2 condition 1.3"
+in:
+  key: "0123456789[a]"
+  key_len: 10
+  buf_len: 11
+out:
+  key: "0123...[a]"
+---
+test case: "#3 condition 1.4"
+in:
+  key: "0123456789[ab]"
+  key_len: 10
+  buf_len: 11
+out:
+  key: "012...[ab]"
+---
+test case: "#4 condition 1.5"
+in:
+  key: "0123456789[abc]"
+  key_len: 10
+  buf_len: 11
+out:
+  key: "01...[abc]"
+---
+test case: "#5 condition 1.6"
+in:
+  key: "0123456789[abc]"
+  key_len: 10
+  buf_len: 10
+out:
+  key: "0123456789[abc]"
+---
+test case: "#6 condition 2.1"
+in:
+  key: "0123456789[aaaaabbbbbccccc]"
+  key_len: 10
+  buf_len: 11
+out:
+  key: "01...[...]"
+---
+test case: "#7 condition 2.2"
+in:
+  key: "0123456789[abcd]"
+  key_len: 10
+  buf_len: 10
+out:
+  key: "0123456789[abcd]"
+---
+
+test case: "#8 condition 3.1"
+in:
+  key: "k[aaaaabbbbbccccc]"
+  key_len: 18
+  buf_len: 19
+out:
+  key: "k[aaaaabbbbbccccc]"
+---
+test case: "#9 condition 3.2"
+in:
+  key: "k[aaaaabbbbbccccc]"
+  key_len: 19
+  buf_len: 20
+out:
+  key: "k[aaaaabbbbbccccc]"
+---
+test case: "#10 condition 3.3"
+in:
+  key: "k[aaaaabbbbbccccc]"
+  key_len: 17
+  buf_len: 18
+out:
+  key: "k[aaaaabbbbbc...]"
+---
+test case: "#11 condition 3.4"
+in:
+  key: "k[aaaaabbbbbccccc]"
+  key_len: 6
+  buf_len: 7
+out:
+  key: "k[...]"
+---
+test case: "#12 condition 3.5"
+in:
+  key: "[aaaaabbbbbccccc]"
+  key_len: 5
+  buf_len: 6
+out:
+  key: "[...]"
+---
+test case: "#13 condition 3.6"
+in:
+  key: "[aaaaabbbbbccccc]"
+  key_len: 4
+  buf_len: 5
+out:
+  key: "[aaaaabbbbbccccc]"
+---
+
+test case: "#14 condition 4.1"
+in:
+  key: "aaaaabbbbbccccc"
+  key_len: 15
+  buf_len: 16
+out:
+  key: "aaaaabbbbbccccc"
+---
+test case: "#15 condition 4.2"
+in:
+  key: "aaaaabbbbbccccc"
+  key_len: 16
+  buf_len: 17
+out:
+  key: "aaaaabbbbbccccc"
+---
+test case: "#16 condition 4.3"
+in:
+  key: "aaaaabbbbbccccc"
+  key_len: 14
+  buf_len: 15
+out:
+  key: "aaaaabbbbbc..."
+---
+test case: "#17 condition 4.4"
+in:
+  key: "aaaaabbbbbccccc"
+  key_len: 2
+  buf_len: 3
+out:
+  key: "aaaaabbbbbccccc"
+---
+test case: "#18 condition 4.5"
+in:
+  key: "aaaaabbbbbccccc"
+  key_len: 3
+  buf_len: 4
+out:
+  key: "..."
+---
+
+
+test case: "#0 ru condition 1.1"
+in:
+  key: "фывапролдж[]"
+  key_len: 5
+  buf_len: 6
+out:
+  key: "...[]"
+---
+test case: "#1 ru condition 1.2"
+in:
+  key: "фывапролдж[]"
+  key_len: 10
+  buf_len: 16
+out:
+  key: "фывап...[]"
+---
+test case: "#2 ru condition 1.3"
+in:
+  key: "фывапролдж[ф]"
+  key_len: 10
+  buf_len: 16
+out:
+  key: "фыва...[ф]"
+---
+test case: "#3 ru condition 1.4"
+in:
+  key: "фывапролдж[фы]"
+  key_len: 10
+  buf_len: 16
+out:
+  key: "фыв...[фы]"
+---
+test case: "#4 ru condition 1.5"
+in:
+  key: "фывапролдж[фыв]"
+  key_len: 10
+  buf_len: 16
+out:
+  key: "фы...[фыв]"
+---
+test case: "#5 ru condition 1.6"
+in:
+  key: "фывапролдж[фыв]"
+  key_len: 10
+  buf_len: 15
+out:
+  key: "фывапролдж[фыв]"
+---
+test case: "#6 ru condition 2.1"
+in:
+  key: "фывапролдж[фывапролдж]"
+  key_len: 10
+  buf_len: 13
+out:
+  key: "фы...[...]"
+---
+test case: "#7 ru condition 2.2"
+in:
+  key: "фывапролдж[фывапролдж]"
+  key_len: 10
+  buf_len: 12
+out:
+  key: "фывапролдж[фывапролдж]"
+---
+
+test case: "#8 ru condition 3.1"
+in:
+  key: "я[фывапролджэю]"
+  key_len: 15
+  buf_len: 0
+out:
+  key: "я[фывапролджэю]"
+---
+test case: "#9 ru condition 3.2"
+in:
+  key: "я[фывапролджэю]"
+  key_len: 16
+  buf_len: 0
+out:
+  key: "я[фывапролджэю]"
+---
+test case: "#10 ru condition 3.3"
+in:
+  key: "я[фывапролджэю]"
+  key_len: 14
+  buf_len: 24
+out:
+  key: "я[фывапрол...]"
+---
+test case: "#11 ru condition 3.4"
+in:
+  key: "я[фывапролдж]"
+  key_len: 6
+  buf_len: 8
+out:
+  key: "я[...]"
+---
+test case: "#12 ru condition 3.5"
+in:
+  key: "[фывапролдж]"
+  key_len: 5
+  buf_len: 6
+out:
+  key: "[...]"
+---
+test case: "#13 ru condition 3.6"
+in:
+  key: "[фывапролдж]"
+  key_len: 4
+  buf_len: 5
+out:
+  key: "[фывапролдж]"
+---
+
+test case: "#14 ru condition 4.1"
+in:
+  key: "фывапролдж"
+  key_len: 10
+  buf_len: 0
+out:
+  key: "фывапролдж"
+---
+test case: "#15 ru condition 4.2"
+in:
+  key: "фывапролдж"
+  key_len: 11
+  buf_len: 0
+out:
+  key: "фывапролдж"
+---
+test case: "#16 ru condition 4.3"
+in:
+  key: "фывапролдж"
+  key_len: 9
+  buf_len: 16
+out:
+  key: "фывапр..."
+---
+test case: "#17 ru condition 4.4"
+in:
+  key: "фывапролдж"
+  key_len: 2
+  buf_len: 0
+out:
+  key: "фывапролдж"
+---
+test case: "#18 ru condition 4.5"
+in:
+  key: "фывапролдж"
+  key_len: 3
+  buf_len: 4
+out:
+  key: "..."
diff --git a/tests/libs/zbxcommon/zbx_truncate_value.c b/tests/libs/zbxcommon/zbx_truncate_value.c
new file mode 100644
index 0000000000..21977f12cb
--- /dev/null
+++ b/tests/libs/zbxcommon/zbx_truncate_value.c
@@ -0,0 +1,45 @@
+/*
+** Zabbix
+** Copyright (C) 2001-2019 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+**/
+
+#include "zbxmocktest.h"
+#include "zbxmockutil.h"
+#include "zbxmockassert.h"
+
+void	zbx_mock_test_entry(void **state)
+{
+	size_t		key_len, buf_len;
+	char		*buf;
+	const char	*key, *exp_result, *act_result;
+
+	ZBX_UNUSED(state);
+
+	key = zbx_mock_get_parameter_string("in.key");
+	key_len = zbx_mock_get_parameter_uint64("in.key_len");
+	buf_len = zbx_mock_get_parameter_uint64("in.buf_len");
+
+	buf = (char *)zbx_malloc(NULL, buf_len);
+
+	exp_result = zbx_mock_get_parameter_string("out.key");
+
+	act_result = zbx_truncate_value(key, key_len, buf, buf_len);
+
+	zbx_mock_assert_str_eq("return value", exp_result, act_result);
+
+	zbx_free(buf);
+}
diff --git a/tests/libs/zbxcommon/zbx_truncate_value.yaml b/tests/libs/zbxcommon/zbx_truncate_value.yaml
new file mode 100644
index 0000000000..a516dd80d2
--- /dev/null
+++ b/tests/libs/zbxcommon/zbx_truncate_value.yaml
@@ -0,0 +1,114 @@
+test case: "#0 condition 1.1"
+in:
+  key: "0123456789[]"
+  key_len: 5
+  buf_len: 6
+out:
+  key: "01..."
+---
+test case: "#1 condition 1.2"
+in:
+  key: "0123456789[]"
+  key_len: 10
+  buf_len: 11
+out:
+  key: "0123456..."
+---
+test case: "#2 condition 4.1"
+in:
+  key: "aaaaabbbbbccccc"
+  key_len: 15
+  buf_len: 16
+out:
+  key: "aaaaabbbbbccccc"
+---
+test case: "#3 condition 4.2"
+in:
+  key: "aaaaabbbbbccccc"
+  key_len: 16
+  buf_len: 17
+out:
+  key: "aaaaabbbbbccccc"
+---
+test case: "#4 condition 4.3"
+in:
+  key: "aaaaabbbbbccccc"
+  key_len: 14
+  buf_len: 15
+out:
+  key: "aaaaabbbbbc..."
+---
+test case: "#5 condition 4.4"
+in:
+  key: "aaaaabbbbbccccc"
+  key_len: 2
+  buf_len: 3
+out:
+  key: "aaaaabbbbbccccc"
+---
+test case: "#6 condition 4.5"
+in:
+  key: "aaaaabbbbbccccc"
+  key_len: 3
+  buf_len: 4
+out:
+  key: "..."
+---
+
+
+test case: "#0 ru condition 1.1"
+in:
+  key: "фывапролдж[]"
+  key_len: 5
+  buf_len: 8
+out:
+  key: "фы..."
+---
+test case: "#1 ru condition 1.2"
+in:
+  key: "фывапролдж[]"
+  key_len: 10
+  buf_len: 18
+out:
+  key: "фывапро..."
+---
+
+test case: "#2 ru condition 4.1"
+in:
+  key: "фывапролдж"
+  key_len: 10
+  buf_len: 0
+out:
+  key: "фывапролдж"
+---
+test case: "#3 ru condition 4.2"
+in:
+  key: "фывапролдж"
+  key_len: 11
+  buf_len: 0
+out:
+  key: "фывапролдж"
+---
+test case: "#4 ru condition 4.3"
+in:
+  key: "фывапролдж"
+  key_len: 9
+  buf_len: 16
+out:
+  key: "фывапр..."
+---
+test case: "#5 ru condition 4.4"
+in:
+  key: "фывапролдж"
+  key_len: 2
+  buf_len: 0
+out:
+  key: "фывапролдж"
+---
+test case: "#6 ru condition 4.5"
+in:
+  key: "фывапролдж"
+  key_len: 3
+  buf_len: 4
+out:
+  key: "..."
