diff --git a/docs/images/client_connection_increasing_constantly.jpg b/docs/images/client_connection_increasing_constantly.jpg
new file mode 100644
index 000000000..3b59f0f57
Binary files /dev/null and b/docs/images/client_connection_increasing_constantly.jpg differ
diff --git a/docs/tsg.md b/docs/tsg.md
index 0c6bd6aeb..0f30deb22 100644
--- a/docs/tsg.md
+++ b/docs/tsg.md
@@ -7,8 +7,9 @@ This guidance is to provide useful troubleshooting guide based on the common iss
- [404 returned for client requests](#random_404_returned_for_client_requests)
- [401 Unauthorized returned for client requests](#401_unauthorized_returned_for_client_requests)
- [500 Error when negotiate](#500_error_when_negotiate)
-- [Client connection drop](#client_connection_drop)
-- [Server connection drop](#server_connection_drop)
+- [Client connection drops](#client_connection_drop)
+- [Client connection increases constantly](#client_connection_increases_constantly)
+- [Server connection drops](#server_connection_drop)
## Access token too long
@@ -30,7 +31,7 @@ With SDK version **1.0.6** or higher, `/negotiate` will throw `413 Payload Too L
### Solution:
By default, claims from `context.User.Claims` are included when generating JWT access token to **ASRS**(**A**zure **S**ignal**R** **S**ervice), so that the claims are preserved and can be passed from **ASRS** to the `Hub` when the client connects to the `Hub`.
-In some cases, `context.User.Claims` are leveraged to store lots of information for app server, most of which are not used by `Hub`s but by other components.
+In some cases, `context.User.Claims` are leveraged to store lots of information for app server, most of which are not used by `Hub`s but by other components.
The generated access token is passed through the network, and for WebSocket/SSE connections, access tokens are passed through query strings. So as the best practice, we suggest only passing **necessary** claims from the client through **ASRS** to your app server when the Hub needs.
@@ -64,11 +65,11 @@ Take ASP.NET Core one for example (ASP.NET one is similar):
Take Chrome as an example, you can use **F12** to open the console window, and switch to **Network** tab. You might need to refresh the page using **F5** to capture the network from the very beginning.

-
+
2. From C# client:
You can view local web traffics using [Fiddler](https://www.telerik.com/fiddler). WebSocket traffics are supported since Fiddler 4.5.
-
+

@@ -79,20 +80,20 @@ Take ASP.NET Core one for example (ASP.NET one is similar):
1. ASP.Net "No server available" error [#279](https://github.com/Azure/azure-signalr/issues/279)
2. ASP.Net "The connection is not active, data cannot be sent to the service." error [#324](https://github.com/Azure/azure-signalr/issues/324)
3. "An error occurred while making the HTTP request to https://. This could be due to the fact that the server certificate is not configured properly with HTTP.SYS in the HTTPS case. This could also be caused by a mismatch of the security binding between the client and the server."
-
+
### Root cause:
Azure Service only supports TLS1.2 for security concerns. With .NET framework, it is possible that TLS1.2 is not the default protocol. As a result, the server connections to ASRS can not be successfully established.
### Troubleshooting Guide
1. If this error can be repro-ed locally, uncheck *Just My Code* and throw all CLR exceptions and debug the app server locally to see what exception throws.
* Uncheck *Just My Code*
-
+

* Throw CLR exceptions
-
+

* See the exceptions throw when debugging the app server side code:
-
+

2. For ASP.NET ones, you can also add following code to your `Startup.cs` to enable detailed trace and see the errors from the log.
@@ -176,7 +177,7 @@ For security concerns, extend TTL is not encouraged. We suggest adding reconnect
## 500 Error when negotiate: Azure SignalR Service is not connected yet, please try again later.
### Root cause
-This error is reported when there is no server connection to Azure SignalR Service connected.
+This error is reported when there is no server connection to Azure SignalR Service connected.
### Troubleshooting Guide
Please enable server-side trace to find out the error details when the server tries to connect to Azure SignalR Service.
@@ -190,6 +191,18 @@ Server side logging for ASP.NET Core SignalR integrates with the `ILogger` based
logging.AddDebug();
})
```
+Logger categories for Azure SignalR always starts with `Microsoft.Azure.SignalR`. To enable detailed logs from Azure SignalR, configure the preceding prefixes to `Debug` level in your **appsettings.json** file like below:
+```JSON
+{
+ "Logging": {
+ "LogLevel": {
+ ...
+ "Microsoft.Azure.SignalR": "Debug",
+ ...
+ }
+ }
+}
+```
#### Enable server side traces for ASP.NET SignalR
When using SDK version >= `1.0.0`, you can enable traces by adding the following to `web.config`: ([Details](https://github.com/Azure/azure-signalr/issues/452#issuecomment-478858102))
@@ -214,7 +227,7 @@ When using SDK version >= `1.0.0`, you can enable traces by adding the following
```
-## Client connection drop
+## Client connection drops
When the client is connected to the Azure SignalR, the persistent connection between the client and Azure SignalR can sometimes drop for different reasons. This section describes several possibilities causing such connection drop and provides some guidance on how to identify the root cause.
@@ -236,8 +249,54 @@ Client connections can drop under various circumstances:
2. Check app server-side event log to see if the app server restarted
3. Create an issue to us providing the time frame, and email the resource name to us
+
+
+## Client connection increases constantly
+It might be caused by improper usage of client connection. If someone forgets to stop/dispose SignalR client, the connection remains open.
+
+### Possible errors seen from the SignalR's metrics blade
+Client connections rise constantly for a long time in Azure SignalR's metrics blade.
+
+
+### Root cause:
+SignalR client connection's `DisposeAsync` never be called, the connection keeps open.
+
+### Troubleshooting Guide
+1. Check if the SignalR client **never** close.
+
+### Solution
+Check if you close connection. Please manually call `HubConnection.DisposeAsync()` to stop the connection after using it.
+
+For example:
+
+```C#
+var connection = new HubConnectionBuilder()
+ .WithUrl(...)
+ .Build();
+try
+{
+ await connection.StartAsync();
+ // Do your stuff
+ await connection.StopAsync();
+}
+finally
+{
+ await connection.DisposeAsync();
+}
+```
+
+### Common Improper Client Connection Usage
+
+#### Azure Function Example
+This issue often occurs when someone establishes SignalR client connection in Azure Function method instead of making it a static member to your Function class. You might expect only one client connection is established, but you see client connection count increases constantly in metrics blade, all these connections drop only after the Azure Function or Azure SignalR service restarts. This is because for **each** request, Azure Function creates **one** client connection, if you don't stop client connection in Function method, the client keeps the connections alive to Azure SignalR service.
+
+#### Solution
+1. Remember to close client connection if you use SignalR clients in Azure function or use SignalR client as a singleton.
+1. Instead of using SignalR clients in Azure function, you can create SignalR clients anywhere else and use [Azure Functions Bindings for Azure SignalR Service](https://github.com/Azure/azure-functions-signalrservice-extension) to [negotiate](https://github.com/Azure/azure-functions-signalrservice-extension/blob/dev/samples/simple-chat/csharp/FunctionApp/Functions.cs#L22) the client to Azure SignalR. And you can also utilize the binding to [send messages](https://github.com/Azure/azure-functions-signalrservice-extension/blob/dev/samples/simple-chat/csharp/FunctionApp/Functions.cs#L40). Samples to negotiate client and send messages can be found [here](https://github.com/Azure/azure-functions-signalrservice-extension/tree/dev/samples). Further information can be found [here](https://github.com/Azure/azure-functions-signalrservice-extension).
+1. When you use SignalR clients in Azure function, there might be a better architecture to your scenario. Check if you design a proper serverless architecture. You can refer to [Real-time serverless applications with the SignalR Service bindings in Azure Functions](https://www.nuget.org/packages/Microsoft.Azure.WebJobs.Extensions.SignalRService).
+
-## Server connection drop
+## Server connection drops
When the app server starts, in the background, the Azure SDK starts to initiate server connections to the remote Azure SignalR. As described in [Internals of Azure SignalR Service](internal.md), Azure SignalR routes incoming client traffics to these server connections. Once a server connection is dropped, all the client connections it serves will be closed too.
diff --git a/version.props b/version.props
index d53fe165a..e8cb5427a 100644
--- a/version.props
+++ b/version.props
@@ -11,7 +11,7 @@
- 1.0.0
+ 1.0.1
$(ManagementSDKPackageVersionPrefix)-preview1-$(BuildNumber)
$(ManagementSDKPackageVersionPrefix)