diff --git a/src/lua/ipc.c b/src/lua/ipc.c
index 270bbfadb720dc3faf2407e0a4ed0a13ca402239..0b8244a51a06a9f7c3131df0d9a9ba32b8d23f21 100644
--- a/src/lua/ipc.c
+++ b/src/lua/ipc.c
@@ -257,6 +257,18 @@ lbox_ipc_channel_is_closed(struct lua_State *L)
 	return 1;
 }
 
+static int
+lbox_ipc_channel_to_string(struct lua_State *L)
+{
+	struct ipc_channel *ch = lbox_check_channel(L, 1, "");
+	if (ipc_channel_is_closed(ch)) {
+		lua_pushstring(L, "channel: closed");
+	} else {
+		lua_pushfstring(L, "channel: %d", (int)ipc_channel_count(ch));
+	}
+	return 1;
+}
+
 static int
 lbox_ipc_cond(struct lua_State *L)
 {
@@ -318,11 +330,21 @@ lbox_ipc_cond_wait(struct lua_State *L)
 	return 1;
 }
 
+static int
+lbox_ipc_cond_to_string(struct lua_State *L)
+{
+	struct ipc_cond *cond = lbox_check_cond(L, 1, "");
+	(void)cond;
+	lua_pushstring(L, "cond");
+	return 1;
+}
+
 void
 tarantool_lua_ipc_init(struct lua_State *L)
 {
 	static const struct luaL_reg channel_meta[] = {
 		{"__gc",	lbox_ipc_channel_gc},
+		{"__tostring",	lbox_ipc_channel_to_string},
 		{"is_full",	lbox_ipc_channel_is_full},
 		{"is_empty",	lbox_ipc_channel_is_empty},
 		{"put",		lbox_ipc_channel_put},
@@ -339,6 +361,7 @@ tarantool_lua_ipc_init(struct lua_State *L)
 
 	static const struct luaL_reg cond_meta[] = {
 		{"__gc",	lbox_ipc_cond_gc},
+		{"__tostring",	lbox_ipc_cond_to_string},
 		{"signal",	lbox_ipc_cond_signal},
 		{"broadcast",	lbox_ipc_cond_broadcast},
 		{"wait",	lbox_ipc_cond_wait},
diff --git a/test/app/ipc.result b/test/app/ipc.result
index 88e4a24cc7649c4b668eb5fb68b7d858457e20c7..432229f7da276564474ead2a1b2fab6ddff519a4 100644
--- a/test/app/ipc.result
+++ b/test/app/ipc.result
@@ -58,6 +58,10 @@ ch:get(.1, nil, unpack(ignored_args))
 ---
 - null
 ...
+tostring(ch)
+---
+- 'channel: 0'
+...
 ch:put()
 ---
 - error: 'usage: channel:put(var [, timeout])'
@@ -70,6 +74,10 @@ ch:put('test')
 ---
 - true
 ...
+tostring(ch)
+---
+- 'channel: 1'
+...
 ch:get()
 ---
 - test
@@ -390,6 +398,10 @@ ch:is_closed()
 ---
 - true
 ...
+tostring(ch)
+---
+- 'channel: closed'
+...
 ch = fiber.channel(1)
 ---
 ...
@@ -556,6 +568,10 @@ refs -- must be zero
 c = fiber.cond()
 ---
 ...
+tostring(c)
+---
+- cond
+...
 -- args validation
 c.wait()
 ---
diff --git a/test/app/ipc.test.lua b/test/app/ipc.test.lua
index 95402107811de3df9fec61946851c5b50c7f86d8..328755338192abe149ee70aad69179c1fc8cdead 100644
--- a/test/app/ipc.test.lua
+++ b/test/app/ipc.test.lua
@@ -17,9 +17,11 @@ ch:is_empty(unpack(ignored_args))
 ch:get(.1)
 ch:get(.1, nil)
 ch:get(.1, nil, unpack(ignored_args))
+tostring(ch)
 ch:put()
 ch:count()
 ch:put('test')
+tostring(ch)
 ch:get()
 ch:put('test', nil), ch:get()
 ch:put('test', nil, unpack(ignored_args)), ch:get()
@@ -108,6 +110,7 @@ ch:get()
 ch:get()
 ch:put(10)
 ch:is_closed()
+tostring(ch)
 
 ch = fiber.channel(1)
 ch:put(true)
@@ -189,6 +192,7 @@ refs -- must be zero
 
 -- fiber.cond
 c = fiber.cond()
+tostring(c)
 -- args validation
 c.wait()
 c.wait('1')