How to get the log and result of websocket async_to_sync calling

I have websocket and simply send the mesasges to channel_layer

from channels.layers import get_channel_layer
    channel_layer = get_channel_layer()
    async_to_sync(channel_layer.group_send)(
        '{}'.format(mychannelname),
        {
            "type": "chat_message",
            "message": "send you"
        }
    )

It seems works well and messages goes to client browser, however I want to know if it works well or not from server.

Is it possible or can I get the number of clients connected to channel?

My consumers.py makes channels

import json

from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncWebsocketConsumer


class ChatConsumer(AsyncWebsocketConsumer):
    
    async def connect(self):

        self.room_group_name = self.scope["url_route"]["kwargs"]["room_name"]

        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )
        await self.accept()
        await self.send(text_data=json.dumps({
            'channel_name': self.channel_name
        }))
    async def disconnect(self, close_code):
        print("some disconnect")
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        print("receive data",text_data_json)
    
        print("channel_name:",self.channel_name)
        print("group_name:",self.room_group_name)
        if text_data_json['type'] == "register":
            self.user_id = text_data_json['message']
        print("user_id is:",self.user_name)

        #res = await self.save_message_to_db(message)
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': "nicelydone",
            }
        )

    async def chat_message(self, event):
        print("someone call chat_message")
        message = event['message']
        await self.send(text_data=json.dumps({
            'message': message
        }))

How to confirm if messages are reaching connected clients:
One way to check if each client is receiving the message is to implement an acknowledgment system. When a client receives a message in the chat_message method, you can have the client send an acknowledgment message back to the server.

Here’s an example of how you can do it:

socket.onmessage = function(event) {
    const data = JSON.parse(event.data);
    console.log("Received message:", data.message);

    // Send acknowledgment back to the server
    socket.send(JSON.stringify({
        'type': 'acknowledgment',
        'message': 'Message received'
    }));
};

Then, on the server, you can handle this acknowledgment in the receive method to confirm delivery:

async def receive(self, text_data):
    text_data_json = json.loads(text_data)
    message_type = text_data_json.get('type')

    if message_type == "acknowledgment":
        print(f"Acknowledgment received from {self.channel_name}")

    # Continue with the rest of your logic here...

This way, each time the client receives a message, they send back an acknowledgment that you can log or track on the server.

How to get the number of connected clients in a channel group:
Django Channels doesn’t directly provide a built-in method to get the number of clients in a group. However, you can keep track of this manually by maintaining a count of active connections. For example:

  • Increment a counter when connect is called.
  • Decrement the counter when disconnect is called.

You could use a cache like Redis to store and retrieve this count, which will persist across different worker processes.

Here’s how you might implement this:

from asgiref.sync import async_to_sync
from django.core.cache import cache

class ChatConsumer(AsyncWebsocketConsumer):

    async def connect(self):
        self.room_group_name = self.scope["url_route"]["kwargs"]["room_name"]

        # Increment connected client count
        await self.update_client_count(1)
        await self.channel_layer.group_add(self.room_group_name, self.channel_name)
        await self.accept()

    async def disconnect(self, close_code):
        # Decrement connected client count
        await self.update_client_count(-1)
        await self.channel_layer.group_discard(self.room_group_name, self.channel_name)

    @database_sync_to_async
    def update_client_count(self, delta):
        current_count = cache.get(self.room_group_name, 0)
        new_count = current_count + delta
        cache.set(self.room_group_name, new_count)
        print(f"Current clients in {self.room_group_name}: {new_count}")

Here, cache can be set up to use Redis or Memcached, allowing you to store the room_group_name as the key and the count as the value.

This way, update_client_count will keep track of the current active connections in your channel group, and you can retrieve the number of connected clients by calling cache.get(room_group_name) wherever needed.

Back to Top