Filtering SignalR requests from ApplicationInsight - signalr

I've configured Application Insights on my web application however the telemetry is full of 'failed' requests from SingalR which makes spotting genuine issues difficult (see screenshot below). I want to filter out all SignalR requests and not send them to AI.
I've created a Telemetry Processor (see code below based on this example from MS) and registered it in the ApplicationInsights.config file, this works as expected when debugging locally and prevents any SignalR events from being sent however it doesn't seem to have any effect once the web application published and running in IIS.
public class SignalRFilter : ITelemetryProcessor
{
private ITelemetryProcessor Next { get; set; }
public SignalRFilter(ITelemetryProcessor next)
{
this.Next = next;
}
public void Process(ITelemetry item)
{
if (!OKtoSend(item))
return;
else
this.Next.Process(item);
}
private bool OKtoSend(ITelemetry item)
{
if (item is RequestTelemetry && ((RequestTelemetry)item).Url.AbsolutePath.Contains("signalr"))
return false;
else
return true;
}
}
Any suggestions?

You're looking at these requests in Live Metrics Stream. For this particular view you can filter them out on demand. Feature is available in latest 2.4-beta (the stable version should be released soon). In this case you can click on Filter button and add proper filters to every stream. Similar behavior exists for charts:
Have you checked whether you see /signair/start in you Application Insights Analytics? It might be the case that you did filter them out successfully and they only show up in Live view.

Related

How to make application insights ignore cancel

Gives a 500 response code when the cancel button is pressed multiple types by the users.
Not causing performance issues but just a lot of clutter in application insights.
Any way to filter this out would be helpful.
Nothing is shown in the telemetry to share too, only the API method that is been called with a 500 code and time. sharing the screenshot of that.
Since you know the response code is 500, you can use telemetry processor to filter out these kinds of request with code 500.
Assume you're using .NET core, you can follow the steps below:
Create a class which implements ITelemetryProcessor, then filter out the request whose response code is 500(or more conditions as per your need.). The sample code looks like below:
public class IgnoreCancelFilter : ITelemetryProcessor
{
private ITelemetryProcessor Next { get; set; }
// next will point to the next TelemetryProcessor in the chain.
public IgnoreCancelFilter(ITelemetryProcessor next)
{
this.Next = next;
}
public void Process(ITelemetry item)
{
var request = item as RequestTelemetry;
if (request != null &&
request.ResponseCode.Equals("500", StringComparison.OrdinalIgnoreCase))
{
// To filter out an item, return without calling the next processor.
return;
}
// Send everything else
this.Next.Process(item);
}
}
Then, register it in ConfigureServices method of your Startup.cs class.
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddApplicationInsightsTelemetry();
services.AddApplicationInsightsTelemetryProcessor<IgnoreCancelFilter>();
}
If the programming language is not .NET core, you can find the proper method for .NET framework / js etc. in this article.

ITelemetryProcessor behavior when deployed to AppService

I have created a custom telemetry processor which is adding customer properties to the telemetry items. When running locally, I don’t see any issue and I am seeing the properties being added(both in release and debug mode) and logged to the AppInsights.
When deployed to app service, I am seeing the logs, but the properties being added by the telemetry processor are missing.
I am using .Net Core 2.1 and the Application insights NuGet version is 2.3.0. Is there a way to debug why this is happening? Also is anyone aware if this is a known issue?
Can you share your code which adds application insights and the telemetry processor? It should be something like this:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddApplicationInsightsTelemetry();
services.AddApplicationInsightsTelemetryProcessor<MyFirstCustomTelemetryProcessor>();
// If you have more processors:
services.AddApplicationInsightsTelemetryProcessor<MySecondCustomTelemetryProcessor>();
// ...
}
Can you try to print the list of TelemetryProcessors registered with the TelemetryConfiguration instance? You can constructor inject TelemetryConfiguration to a controller class, and print out the list. Something like shown below.
string tpList;
public ValuesController(TelemetryConfiguration tc)
{
var tps = tc.TelemetryProcessors;
foreach(var tp in tps)
{
var s = tp.GetType().ToString();
tpList += s;
}
}
// GET api/values
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2", tpList };
}
This should confirm if the TelemetryProcessor is even in the config.
Also, when you say works local - do you mean when running from Visual Studio? VS alters behavior, so can try to run locally outside of VS, and see if it reproes.

JavaFx Turn-based Multiplayer Application with Google Service

Now I am using Gluon plugin and it is very helpful to start working with JavaFXPorts. I have my application ready and I can use it on computers and phones. I tested on phone with system android. Application is working good but only with my server.
I take care of the different resolutions and I think that it is good for now.
I want to have Turn-based Multiplayer Application but I have still big problem with using Google Play Service. Tutorial which show how to use this services for turn-based multiplayer application is written in pure android and use Activity. My question is maybe very simple but If I have my application view from "fxml" how to use it as an tutorial Activity?
I want to do auto-matching for my application and next I want override method takeTurn() to suit it to my application.
For example, how can I change thing like that (code below) to application in JavaFX?
I must use google services from my JavaFX(src/main/java folder) class in addition AndroidPlatformProvider.java and all methods must be in src/android/java folder. I know that I must use PlatformService and PlatformProvider. I did it as in the examples: HelloPlatform and SMSTracker .
I use methods from my interface PlatformProvider but application still crashes. :(
I only use Provider from my code of JavaFX and I don't have android Activity. I don't know how to use these method without Activity or View:
- public void onActivityResult(int request, int response, Intent data)
- public void playTurn(View view)
Can I call from google service methods to methods from my controller for view (fxml).
I don't know how these methods should working with JavaFX.
public class TbmpGameActivity extends Activity {
...
#Override
public void onActivityResult(int request, int response, Intent data) {
super.onActivityResult(request, response, data);
...
if (request == RC_SELECT_PLAYERS) {
if (response != Activity.RESULT_OK) {
// user canceled
return;
}
// Get the invitee list.
final ArrayList<String> invitees =
data.getStringArrayListExtra(Games.EXTRA_PLAYER_IDS);
// Get auto-match criteria.
Bundle autoMatchCriteria = null;
int minAutoMatchPlayers = data.getIntExtra(
Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);
int maxAutoMatchPlayers = data.getIntExtra(
Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);
if (minAutoMatchPlayers > 0) {
autoMatchCriteria = RoomConfig.createAutoMatchCriteria(
minAutoMatchPlayers, maxAutoMatchPlayers, 0);
} else {
autoMatchCriteria = null;
}
TurnBasedMatchConfig tbmc = TurnBasedMatchConfig.builder()
.addInvitedPlayers(invitees)
.setAutoMatchCriteria(autoMatchCriteria)
.build();
// Create and start the match.
Games.TurnBasedMultiplayer
.createMatch(mGoogleApiClient, tbmc)
.setResultCallback(new MatchInitiatedCallback());
}
}
}
or something like that:
// Call this method when a player has completed his turn and wants to
// go onto the next player, which may be himself.
public void playTurn(View view) {
// Get the next participant in the game-defined way, possibly round-robin.
String nextParticipantId = getNextParticipantId();
// Get the updated state. In this example, we simply retrieve a
// text string from the view. In your game, there may be more
// complicated state.
mTurnData = mDataView.getText().toString();
// At this point, you might want to show a waiting dialog so that
// the current player does not try to submit turn actions twice.
showSpinner();
// Invoke the next turn. We are converting our data to a byte array.
Games.TurnBasedMultiplayer
.takeTurn(mGoogleApiClient, mMatch.getMatchId(),
mTurnData.getBytes(Charset.forName("UTF-16")),
nextParticipantId)
.setResultCallback(this);
}
Latest version of the jfxmobile plugin (1.0.3) includes recent changes in Dalvik SDK that contains the port of JavaFX 8 to android.
In FXActivity class, it has been added a very convenient method to listen to results of intents: setOnActivityResultHandler().
This means you shouldn't add new activities to your app, and only use FXActivity. You should add an Intent to it, and set a proper result handler to the FXActivity.
Have a look at this recent post at Gluon's site. It explains how to access native services, based on the case of taking a picture with the device's camera, and waiting to get the result of it to resume the app.
Basically, this is what it is required in this case:
public void takePicture() {
// create intent
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
...
// Add result handler
FXActivity.getInstance().setOnActivityResultHandler((requestCode, resultCode, data) -> {
if (requestCode == TAKE_PICTURE && resultCode == RESULT_OK) {
...
}
});
// launch activity
FXActivity.getInstance().startActivityForResult(intent, TAKE_PICTURE);
}
Try this approach with your app.

Reliably counting the number of client connections to a SignalR hub

I'm creating a web dashboard that will display the status of our test environments.
I use a hub to connect the browser to the server and have a background task that polls the status of the environment. I only want to perform this check if at least one client is connected.
My hub looks a little like this:
public class StatusHub : Hub
{
private static int connectionCount = 0;
public override Task OnConnected()
{
Interlocked.Increment(ref connectionCount);
return base.OnConnected();
}
public override Task OnReconnected()
{
Interlocked.Increment(ref connectionCount);
return base.OnReconnected();
}
public override Task OnDisconnected()
{
Interlocked.Decrement(ref connectionCount);
return base.OnDisconnected();
}
// other useful stuff
}
This mainly works but sometimes OnConnected is called but OnDisconnected is not.
One specific case is if I open chrome and type the address of the page but don't actually navigate to it. It seems Chrome is pre-fetching the page and connecting, but never disconnecting.
So two questions:
Is this a good approach to counting connections (I'm never going to be running in a web farm environment)?
Will these zombied connections from Chrome eventually timeout (I tried setting timeouts very low but still didn't get a disconnect)?
The events will always fire. If they don't, file a bug with repro steps on github. To get a more accurate number, you can store a hashset of connection ids and get the count from that.

ASP.net how to long polling with PokeIn?

I want to make a service that notify the user in case there are some new messages sent to him. Thus I want to use some Comet framework that provide the server push ability. So I have looked into PokeIn.
Just wondering a thing. I have checked on the samples that they have on the website. None of them look into the database to retrieve new entries if there are some. But it is just a matter of modification to it I guess.
One of the sample implement this long polling by using a sleep on the server side. So if I use the same approach I can check the database, if there are any new entries, every 5 seconds. However this approach doesn't seem to be much different from when using polling on the client side with javascript.
This part is from a sample. As can be seen they put a sleep there for to update current time for everybody.
static void UpdateClients()
{
while (true)
{
//.. code to check database
if (CometWorker.ActiveClientCount > 0)
{
CometWorker.SendToAll(JSON.Method("UpdateTime", DateTime.Now));
}
Thread.Sleep(500);
}
}
So I wonder is this how I should implement the message notifier? It seems that the above approach is still going to push a huge load demand on the server side. The message notifier is intend to work same way as the one found Facebook.
You shouldn't implement this way, that sample is only implemented like that because the keep PokeIn related part is clear. You should implement SQL part as mentioned http://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events
in order to track changes on database.
So, when you have something to send, call one of the PokeIn methods for the client side delivery. I don't know, how much your application is time critical because in addition to reverse ajax, PokeIn's internal websocket feature is very easy to activate and delivers messages to client quite fast.
You can do this with database as #Zuuum said, but I implemented it in a different way.
I'm using ASP.NET MVC with PokeIn and EF in a Windows Azure environment:
I have domain events similar to this approach: Strengthening your domain: Domain Events
When someone invokes an action, that's a Unit of Work
If that UOW succeeds then I raise a domain event (e.g. ChatMessageSent)
I have subscribers for these domain events so they can receive the event and forward the message to the PokeIn listeners
I use this pattern for all my real-time needs on my game site (making moves, actions etc in a game), I don't want to advertise it here, you can find it through me if you want.
I always use this pattern as a duplex communication solution so everybody gets their update via PokeIn, even the user who invoked the action so every client will behave the same. So when someone calls an action it won't return anything except the success signal.
The next examples are won't work because they are only snippets to demonstrate the flow
Here is an action snippet from my code:
[HttpPost]
[UnitOfWork]
[RestrictToAjax]
[ValidateAntiForgeryToken]
public JsonResult Post(SendMessageViewModel msg)
{
if (ModelState.IsValid)
{
var chatMessage = new ChatMessage
{
ContainerType = msg.ContainerType,
ContainerID = msg.ContainerID,
Message = _xssEncoder.Encode(msg.Message),
User = _profileService.CurrentUser
};
_chatRepository.AddMessage(chatMessage);
OnSuccessfulUoW = () => EventBroker.Current.Send(this, new ChatMessageSentPayload(chatMessage));
}
return Json(Constants.AjaxOk);
}
And the (simplified) EventBroker implementation:
public class UnityEventBroker : EventBroker
{
private readonly IUnityContainer _container;
public UnityEventBroker(IUnityContainer container)
{
_container = container;
}
public override void Send<TPayload>(object sender, TPayload payload)
{
var subscribers = _container.ResolveAll<IEventSubscriber<TPayload>>();
if (subscribers == null) return;
foreach (var subscriber in subscribers)
{
subscriber.Receive(sender, payload);
}
}
}
And the even more simplified subscriber:
public class ChatMessageSentSubscriber : IEventSubscriber<ChatMessageSentPayload>
{
public void Receive(object sender, ChatMessageSentPayload payload)
{
var message = payload.Message;
var content = SiteContent.Global;
var clients = Client.GetClients(c => c.ContentID == message.ContainerID && c.Content == content)
.Select(c => c.ClientID)
.ToArray();
var dto = ObjectMapper.Current.Map<ChatMessage, ChatMessageSentDto>(message);
var json = PokeIn.JSON.Method("pokein", dto);
CometWorker.SendToClients(clients, json);
}
}

Resources