Lower overhead ADO extension wrapping #894

Merged
merged 3 commits into from Jun 16, 2015

Projects

None yet

3 participants

@kendallb

Removed static initialization of ADO extension so it will NOT wrap the factory if the Glimpse handler is not enabled in the Web.config file. This ensures there is zero overhead on production systems.

Also added support for the GlimpseDbProviderFactory to NOT wrap the connections and commands if the runtime policy is currently set to OFF, for the least amount of overhead for non logged requests if enabled on production systems.

@kendallb kendallb Removed static initialization of ADO extension so it will NOT wrap th…
…e factory if the Glimpse handler is not enabled in the Web.config file. This ensures there is zero overhead on production systems.

Also added support for the GlimpseDbProviderFactory to NOT wrap the connections and commands if the runtime policy is currently set to OFF, for the least amount of overhead for non logged requests if enabled on production systems.
a2a5e2d
@CGijbels

This would break current users and would force every user to add the following code to into their application startup code Glimpse.Settings.Initialize.Ado(); currently this is only required for NET3.5 version of the Glimpse.Ado plugin

@CGijbels

This would break current users and would force every user to add the following code to into their application startup code Glimpse.Settings.Initialize.Ado(); currently this is only required for NET3.5 version of the Glimpse.Ado plugin

@CGijbels

removing the class breaks current users especially those running the NET3.5 version as the call to Glimpse.Settings.Initialize.Ado(); won't compile any longer... so I'm wondering where you are making those calls in your application to make sure the hooks are in place?

@CGijbels

This code is a quick fix that is actually broken in certain circumstances, that is way the GlimpseConfiguration has a private instance field runtimePolicyStrategy which is initialized with a proper strategy that deals with those other situations (see InstantiateRuntimePolicyStrategy() in the Factory class). if you want to check the current runtime policy value, then it would be better to make that runtimePolicyStrategy instance field static and provide it like the GetConfiguredMessageBroker() hack method decorated with the ObsoleteAttribute. Either way, in v2 we have fixed this access issue, so it is possible to get the current runtime policy from a GlimpseRuntime.Instance

@CGijbels

I see why you would do that, although I'm wondering if checking the current runtime policy isn't adding the same overhead as those pass through calls when being wrapped by Glimpse types and Glimpse is not active? Have you metrics on that?

Either way, we could leave this in place, once the GlimpseConfiguration.GetRuntimePolicy() is properly implemented (see other remark). Just keep in mind that the current runtime policy can change and even be disabled at the end of processing a call, which means that monitoring of a request and the calls being run at that time, might still be discarded at the end. Also the implementing Glimpse wrappers, check the current MessageBroker and if that does not exist (aka Glimpse is completely disabled) then no messages are being created either, so the perf penalty should be minimal, although there will be some small overhead

@avanderhoorn
Member

To add to what @CGijbels said, I wondering if we need all the checks in GlimpseDbProviderFactory. In theory GlimpseDbProviderFactory should only be in play if Glimpse is enabled for the given request. That said I would have to test it a little more to make sure.

@kendallb

Not sure how to quote comments here? Anyway, CGijbels said:

This would break current users and would force every user to add the following code to into their application startup code Glimpse.Settings.Initialize.Ado(); currently this is only required for NET3.5 version of the Glimpse.Ado plugin

Quite possibly as I am not sure how this works, but the big difference with not having this there is that if you do not have Glimpse enabled at all in your Web.config file, nothing gets initialized and no wrapping of the factory providers happens at all. Which is what you want on a production system so you can turn it on only if you need to track down specific problems. Normally it would be left completely off and have zero overhead.

Now what happens at least on my system is that the AdoInspector() class is called by the normal Glimpse startup code (I believe from within BeginRequest in the HttpHandler) and does all the correct initialization there. But the code that calls AdoInspector() is designed to do nothing when Glimpse is not enabled in the Web.config file. So at least for my case, the static init code is not required at all and I wonder why it was necessary in the first place? Does the normal startup code not run on other platforms? It is only the ADO and EF extensions that somehow required the hack to always init at startup so maybe this is no longer necessary?

For me it is critical that systems like this can be compiled in and be ready to use when we need them, but have zero overhead in production systems. And that is currently not the case with the ADO extension.

@kendallb

This code is a quick fix that is actually broken in certain circumstances, that is way the GlimpseConfiguration has a private instance field runtimePolicyStrategy which is initialized with a proper strategy that deals with those other situations (see InstantiateRuntimePolicyStrategy() in the Factory class). if you want to check the current runtime policy value, then it would be better to make that runtimePolicyStrategy instance field static and provide it like the GetConfiguredMessageBroker() hack method decorated with the ObsoleteAttribute. Either way, in v2 we have fixed this access issue, so it is possible to get the current runtime policy from a GlimpseRuntime.Instance

I actually looked at doing it in the GlimpseRuntime class also, and I am glad to know in v2 there is a way for someone to be able to find the single instance of GlimpseRuntime and be able to work out what the current strategy is.

@kendallb

I see why you would do that, although I'm wondering if checking the current runtime policy isn't adding the same overhead as those pass through calls when being wrapped by Glimpse types and Glimpse is not active? Have you metrics on that?

I have not measured it directly, but have debugged into the code to see what is happening. IF glimpse is not enabled in the web.config file, the wrapping of the DB classes still happens, so there is an overhead for every single call to DB connections and commands, since they are always wrapped. None of the logging happens though, since the timer stategy and message broker are both null.

However in the case where Glimpse is enabled in the web.config file but not enabled for the request, the wrapped classes will not run any of the timing code but WILL run all of the logging code not related to timing and pass it to the message broker, since the message broker is NOT null in this case. This includes overhead in the the DB reader, DB connection and DB command classes. Look for every piece of code that has an if (MessageBroker != null) in it and every bit of that code executes for EVERY request. Regardless of whether the Glimpse runtime strategy is off or not.

The code change I made takes a quick look at the HttpRequestStore to find the currently configured runtime strategy (which is set up in BeginRequest, so long before it should be needed) and then does not bother wrapping the classes if the strategy is off. This has the benefit of not running any of the message broker stuff when it is not needed, but also completely eliminates any overhead imposed by the class wrappers, since everything is wrapped (every property call etc). So yes, there is a small overhead at the point when you need to wrap the DB classes to determine if it should be wrapped, but it should be significantly less than the total overhead the wrapping imposes.

Also it should be noted that the overhead would be a lot less if the MessageBroker was null when the runtime strategy is OFF, which it currently is not. It would seem the ADO classes were written under the assumption that it would be null in that case, so the overhead would be lower.

But even so I would argue the total overhead of wrapping every single access to the DB classes even if they do basically nothing is a whole lot less if you never wrap them in the first place.

@kendallb

To add to what @CGijbels said, I wondering if we need all the checks in GlimpseDbProviderFactory. In theory GlimpseDbProviderFactory should only be in play if Glimpse is enabled for the given request. That said I would have to test it a little more to make sure.

I don't think that is possible due to the way that the wrapping is done for the ADO extension. All the code in DbProviderFactoriesExecutionTask only happens once, when the application is first starting up. It finds all the registered DB providers and then wraps them, so we can insert our hooks as necessary. Ideally we would only wrap the DB providers on a per request basis, but that is not possible since those classes are used globally by all requests.

So the wrapping is set up once when the application first starts up, and then it is up to the factory class itself to impose as low overhead as possible on a per request basis.

@CGijbels
Member

@kendallb thanks for the comments! I've updated them to show how to add quotes, it is merely preceding them with a >

For me it is critical that systems like this can be compiled in and be ready to use when we need them, but have zero overhead in production systems. And that is currently not the case with the ADO extension.

You are right about the ADOplugins actually running some code, although minor, even when Glimpse is completely disabled. If you want to be 100% sure then you need to remove the Glimpse.Ado and Glimpse.EFx assemblies from your production bin directory (changing web.config to enable Glimpse results in a application restart as well, so adding the additional assemblies then might be a workaround)

Does the normal startup code not run on other platforms? It is only the ADO and EF extensions that somehow required the hack to always init at startup so maybe this is no longer necessary?

If I remember correctly, having the inspector code run on BeginRequest was sometimes too late, especially when dealing with EF, that's why we had to explicitly configure the interceptors at Application_Start in global.asax with code like Glimpse.Settings.Initialize.Ado(); or Glimpse.Settings.Initialize.EF(); (which is still the case for NET35), that's why it has been replaced with the PreApplicationStartMethodAttribute as from NET40 to make sure we don't have a compilation dependency and only a runtime dependency on Glimpse. The exact reason why there were issues with EF is something @avanderhoorn will be able to tell (I think)

I actually looked at doing it in the GlimpseRuntime class also, and I am glad to know in v2 there is a way for someone to be able to find the single instance of GlimpseRuntime and be able to work out what the current strategy is.

Yep, the thing is that the runtimePolicyStrategy is injected in the constructor by the Factory class, that's why you couldn't see it inside the GlimpseRuntime directly. v2 has a proper access to the current Glimpse Request context

However in the case where Glimpse is enabled in the web.config file but not enabled for the request, the wrapped classes will not run any of the timing code but WILL run all of the logging code not related to timing and pass it to the message broker, since the message broker is NOT null in this case. This includes overhead in the the DB reader, DB connection and DB command classes. Look for every piece of code that has an if (MessageBroker != null) in it and every bit of that code executes for EVERY request. Regardless of whether the Glimpse runtime strategy is off or not.

true, the problem or thing to keep in mind here is that there is only a current runtime policy that you can ask for, but during the same request the returned value may change, but even after said that, I do agree that there is a performance impact, even when it is small, it is still there.

So yes, there is a small overhead at the point when you need to wrap the DB classes to determine if it should be wrapped, but it should be significantly less than the total overhead the wrapping imposes.

It will be less in the cases where actual logging would take place, but checking the current value will execute a delegate, check a dictionary, ... but it should be less impacting, normally

Also it should be noted that the overhead would be a lot less if the MessageBroker was null when the runtime strategy is OFF, which it currently is not. It would seem the ADO classes were written under the assumption that it would be null in that case, so the overhead would be lower.

Nope, the broker is set at initialization time and is independent of Glimpse monitoring a request or not, it is static 😉 so it will only be null when Glimpse is configured Off

But even so I would argue the total overhead of wrapping every single access to the DB classes even if they do basically nothing is a whole lot less if you never wrap them in the first place.

I agree, we just need to find the best way with the least impact on existing userbases

So the wrapping is set up once when the application first starts up, and then it is up to the factory class itself to impose as low overhead as possible on a per request basis.

I think your final comment is what we should try to achieve, which means we need to keep the PreApplicationStartMethodAttribute in the AssemblyInfo.cs files, otherwise we are going to have a breaking change. But checking if we need to wrap is something that can be done while being backward compatible (at least nobody should be checking a Glimpse specific wrapper in its code as it could absent as well if Glimpse is configured Off in the web.config)

So to wrap up, if you could undo some of the removals, and adjust the code inside the GlimpseConfiguration to use the private runtimePolicyStrategy (initialized by this code) in an extra Obsolete marked static method, then that might work and still be backward compatible.

I hope all of the above makes sense? If not then let us know and we'll see where we can help you further or clarify things further

@kendallb

I think your final comment is what we should try to achieve, which means we need to keep the PreApplicationStartMethodAttribute in the AssemblyInfo.cs files, otherwise we are going to have a breaking change. But checking if we need to wrap is something that can be done while being backward compatible (at least nobody should be checking a Glimpse specific wrapper in its code as it could absent as well if Glimpse is configured Off in the web.config)

Right, a small overhead in the wrappers at wrap time is probably decent. The most critical part is making sure there is zero impact (or close to zero) for production. If we check for the MessageBroker = null we can easily detect the case when Glimpse is entirely off in the Web.config file and avoid doing anything in that case. A small overhead for that check in the factory to create commands and connections will be nothing. Then we can leave the static init startup code in place.

true, the problem or thing to keep in mind here is that there is only a current runtime policy that you can ask for, but during the same request the returned value may change, but even after said that, I do agree that there is a performance impact, even when it is small, it is still there.

So the runtime policy may change AFTER the request has started? What would the use cases for that be, and is it expected that a DB connection created at request start time can turn on/off the logging during the handling of the request? If that is the case then checking in the wrapper if you should wrap the connection is probably not going to work, as if it starts in the OFF state but then gets turned on for a single controller or something it would never be wrapped and the logging would be lost.

If we want that to work with minimal overhead when Glimpse enabled but is currently set to a runtime policy of OFF (something I think is critical to ensure impact on requests you are not logging is low), then we would need a really fast way to know if the runtime policy is off so you can call that instead everywhere that the current code is checking for a null message broker?

@kendallb

So to wrap up, if you could undo some of the removals, and adjust the code inside the GlimpseConfiguration to use the private runtimePolicyStrategy (initialized by this code) in an extra Obsolete marked static method, then that might work and still be backward compatible.

I looked at doing that initially but I was concerned about the overhead of calling that callback, since won't it end up running all the runtime policy determination code? It seemed faster to me to check what is stored in the request context, since that is the cached result of having already executed that code, but I can see if the policy can change dynamically that might cause a problem.

I think it would be too much overhead to call this every time you need to log something to see if the policy is turned on, but it could be used before you wrap something the connections and command I suppose. Just not sure what would happen if the policy is OFF when the connection is created and then turns to ON when commands are executed?

@kendallb kendallb Put static initialization code back and improved the mechanism at run…
…time to determine if we should wrap DB connections and commands.
0caaffe
@kendallb

Ok, changes are made. Let me know if this is more like what you expected.

@CGijbels
Member

So the runtime policy may change AFTER the request has started? What would the use cases for that be, and is it expected that a DB connection created at request start time can turn on/off the logging during the handling of the request? If that is the case then checking in the wrapper if you should wrap the connection is probably not going to work, as if it starts in the OFF state but then gets turned on for a single controller or something it would never be wrapped and the logging would be lost.

Yep, it will change, but it can only become more restrictive, which means once it is Off it remains Off, but it is possible that it is On and becomes Off as a result of executing one or more IRuntimePolicy implementations. So what could happen is that a connection is being wrapped at the beginning of the request and maybe some commands as well, but that at the end for instance, some final commands (although less likely there would be some after Glimpse processed the request) might be unwrapped, but then again, that is not an issue as it first was enabled for the request. In case of a configured Off state in the web.config no wrapping will be done because Glimpse won't allow you to.

If we want that to work with minimal overhead when Glimpse enabled but is currently set to a runtime policy of OFF (something I think is critical to ensure impact on requests you are not logging is low), then we would need a really fast way to know if the runtime policy is off so you can call that instead everywhere that the current code is checking for a null message broker?

I was thinking in the lines of exposing the default runtime policy, aka the one read from the web.config and passed in into the GlimpseConfiguration. So the logic could be

  • check the default, configured, runtime policy, if it is Off then no wrapping should be done
  • check the MessageBroker for null , if it is null, then no wrapping should be done either as messages can't be sent anyway
  • check the current runtime policy for an up-to-date value of the current request, if Off then no wrapping should be done
  • all other cases => wrap

I looked at doing that initially but I was concerned about the overhead of calling that callback, since won't it end up running all the runtime policy determination code? It seemed faster to me to check what is stored in the request context, since that is the cached result of having already executed that code, but I can see if the policy can change dynamically that might cause a problem.

as you can see at the code I mentioned then you'll notice it will not evaluate the configured IRuntimePolicy instances, it will merely look up the current value inside the dictionary, just like you proposed, but with the additional check if the key exists, either way, by reusing that delegate, we can be sure the same check is only implemented once.

So the above will make sure it will become faster when no wrapping needs to be done, but it will become slightly slower when it does, on the other hand the impact should be negligible as a monitored request has more overhead than such a check, and once you are creating many connections or commands that need to be wrapped, then you have another problem 😉

@CGijbels CGijbels commented on an outdated diff Mar 31, 2015
source/Glimpse.Core/Framework/GlimpseConfiguration.cs
@@ -704,5 +704,11 @@ public static IMessageBroker GetConfiguredMessageBroker()
{
return messageBroker;
}
+
+ [Obsolete("HACK: To support TraceListener with TraceSource via web.config")]
@CGijbels
CGijbels Mar 31, 2015 Member

maybe change the message to something like HACK: To prevent unnecessary wrapping of SQL connections, commands, ... ?

@CGijbels CGijbels and 1 other commented on an outdated diff Mar 31, 2015
...Glimpse.Ado/AlternateType/GlimpseDbProviderFactory.cs
@@ -31,9 +33,27 @@ public override bool CanCreateDataSourceEnumerator
private TProviderFactory InnerFactory { get; set; }
+ private static bool ShouldNotWrap()
+ {
@CGijbels
CGijbels Mar 31, 2015 Member

maybe first check against the configured default runtime policy as in GlimpseConfiguration.GetDefaultRuntimePolicy() == RuntimePolicy.Off

@kendallb
kendallb Mar 31, 2015

Ok, I added this functionality and added the call. However I left the first check against the MessageBroker, since I know that is going to be null when Glimpse HttpHandler is not configured at all in the Web.config file (not sure what the default runtime policy would be in that case?). Mostly to make sure in production cases where it is off, it short circuits as soon as possible with the least amount of overhead.

If the runtime policy is going to be OFF if not configured in the web.config file as handler, then maybe the MessageBroker check is not needed?

@CGijbels CGijbels commented on an outdated diff Mar 31, 2015
...Glimpse.Ado/AlternateType/GlimpseDbProviderFactory.cs
@@ -53,7 +78,12 @@ public override DbConnectionStringBuilder CreateConnectionStringBuilder()
public override DbDataAdapter CreateDataAdapter()
{
- return new GlimpseDbDataAdapter(InnerFactory.CreateDataAdapter());
+ var adapter = InnerFactory.CreateDataAdapter();
+ if (ShouldNotWrap())
+ {
+ return adapter;
+ }
+ return new GlimpseDbDataAdapter(adapter);
}
@CGijbels
CGijbels Mar 31, 2015 Member

Maybe invert the check? As in IsAdoMonitoringNeeded() ? and then wrap if needed?

@CGijbels CGijbels and 1 other commented on an outdated diff Mar 31, 2015
...Glimpse.Ado/AlternateType/GlimpseDbProviderFactory.cs
@@ -31,9 +33,27 @@ public override bool CanCreateDataSourceEnumerator
private TProviderFactory InnerFactory { get; set; }
+ private static bool ShouldNotWrap()
+ {
+ if (GlimpseConfiguration.GetConfiguredMessageBroker() == null)
+ {
+ return true;
+ }
+ if (GlimpseConfiguration.GetRuntimePolicyStategy()() == RuntimePolicy.Off)
+ {
+ return true;
+ }
+ return false;
+ }
+
@CGijbels
CGijbels Mar 31, 2015 Member

maybe move this method to the bottom of the file instead of at the top, the public methods here are the important ones...

@kendallb
kendallb Mar 31, 2015

This is a fallback from my old Pascal programming days and wanting to define functions before they are called. lol.

@CGijbels
Member

@kendallb it is looking good, some minor remarks and we should be good to go

Once we have a final version, we need to have @avanderhoorn or @nikmd23 have a final look, as we need somebody less involved in the PR to get a clear view and merge it in the end...
Oh, and you'll have to sign the CLA and mail it to anthony dot vanderhoorn at the google place so that we can pull in the code

@kendallb

I was thinking in the lines of exposing the default runtime policy, aka the one read from the web.config and passed in into the GlimpseConfiguration. So the logic could be

That makes sense. Is that something we can do now or in v2? Also we should make sure that when this PR is pulled over that the equivalent is done in the v2 tree. Is that something you want me to look at? I have not looked at the v2 code at all yet.

as you can see at the code I mentioned then you'll notice it will not evaluate the configured IRuntimePolicy instances, it will merely look up the current value inside the dictionary, just like you proposed, but with the additional check if the key exists, either way, by reusing that delegate, we can be sure the same check is only implemented once.

Yes, I figured that out when I debugged into the code to see what it did :)

Oh, and you'll have to sign the CLA and mail it to anthony dot vanderhoorn at the google place so that we can pull in the code

I will get that done ASAP.

@kendallb

Changes made, let me know if it is good. I will get the CLA signed and sent off.

@avanderhoorn
Member

Currently on my mobile at the moment, so haven't been been able to catch up on all of the latest, but one thing that concerns me about this, is the overhead of conducting the check in the first place. I'm wondering if there is a better way of doing this which would mean that te factory would effectively be a null version in cases were Glimpse is disabled. Not sure exactly how this could be down but just thinking.

And yes, the init code was implemented they way it was because of how early EF starts initializing and what problems we have with trying to wire up our observers post EF getting started.

@CGijbels
Member

@kendallb for me this is looking good
@avanderhoorn the way it is changed now means that:

  • when the Gimpse HttpModule is not available in config but the Glimpse.Ado assembly is, then the GlimpseConfiguration.GetConfiguredMessageBroker() will return null as no initialization has been done and the static messageBroker field inside the GlimpseConfiguration will remain null : this means performance win in that situation and no side effects at all
  • when the GlimpseConfiguration.GetConfiguredMessageBroker() returns non null value, then this means the Glimpse HttpModule is registered, but then we have the second fallback scenario, where we check for the default runtime policy as it is configured in the web.config. If it is configured as Off then no wrapping will be done either, the call to GlimpseConfiguration.GetDefaultRuntimePolicy() returns the static field defaultRuntimePolicy from the GlimpseConfiguration, set only once : this means in case Glimpse is configured to be Off, no wrapping will be done and no side effects
  • in case Glimpse HttpModule is active and the default runtime policy is not null then we need to check the current value, which will be done each time a connection, command, adapter is created. This check will add an extra overhead in those cases where Glimpse is active for the request which is different for the current situation, but if Glimpse is active then this additional check can be neglected when looking at the bigger impact the whole request monitoring has, but if Glimpse is inactive for the request because cookie is not set for instance, then you have a performance gain again.

So I wouldn't worry to much about it, and if a user is creating a lot of connections, commands or adapters, then they have another issue and will loose the most time waiting for the DB to return a response 😉

@CGijbels
Member

@kendallb

That makes sense. Is that something we can do now or in v2? Also we should make sure that when this PR is pulled over that the equivalent is done in the v2 tree. Is that something you want me to look at? I have not looked at the v2 code at all yet.

That shouldn't be an issue, normally we can just merge the change in, as we merge the master branch into the v2 branch at regular intervals

@kendallb
kendallb commented Apr 3, 2015

How long does it take for the merges to get pushed into an official release on NuGet?

@avanderhoorn
Member

Sorry been focused on my new baby. Is this all ready to go @CGijbels @kendallb @nikmd23

@kendallb

I think so. It was waiting on someone else to approve and pull in to the main branch I believe.

Regards,

Kendall Bennett
CEO & Co-Founder
www.AMain.com | 530-894-0797 | 800-705-2215
424 Otterson Drive, Chico, California 95928

On Apr 23, 2015, at 4:19 PM, Anthony van der Hoorn notifications@github.com wrote:

Sorry been focused on my new baby. Is this all ready to go @CGijbels https://github.com/CGijbels @kendallb https://github.com/kendallb @nikmd23 https://github.com/nikmd23

Reply to this email directly or view it on GitHub #894 (comment).

@avanderhoorn
Member

@kendallb Just wondering if you had a chance to sign the CLA. I was hoping to get this into the next release.

@kendallb

I did and I asked to have it sent off. Did you not get it? I can check how it was sent.

Sent from my iPhone

Kendall Bennett
CEO & Founder
www.AMain.comhttp://www.amain.com/ | 530-894-0797tel:530-894-0797 | 800-705-2215tel:800-705-2215
424 Otterson Drive, Chico, California 95928x-apple-data-detectors://2/1

On Jun 12, 2015, at 11:33 AM, Anthony van der Hoorn <notifications@github.commailto:notifications@github.com> wrote:

@kendallbhttps://github.com/kendallb Just wondering if you had a chance to sign the CLA. I was hoping to get this into the next release.


Reply to this email directly or view it on GitHubhttps://github.com/Glimpse/Glimpse/pull/894#issuecomment-111582871.

@avanderhoorn
Member

No, not that I have seen.

@kendallb

I checked and I emailed it to glimpseproject@gmail.commailto:glimpseproject@gmail.com. If there is another email address I should send it to, which one should I use?

Regards,

Kendall Bennett
CEO & Co-Founder
www.AMain.comhttp://www.AMain.com | 530-894-0797 | 800-705-2215
424 Otterson Drive, Chico, California 95928

On Jun 12, 2015, at 12:46 PM, Anthony van der Hoorn <notifications@github.commailto:notifications@github.com> wrote:

No, not that I have seen.


Reply to this email directly or view it on GitHubhttps://github.com/Glimpse/Glimpse/pull/894#issuecomment-111597661.

@avanderhoorn
Member

Sorry that it got missed that that address. Have recieved it now and we are good to go.

@avanderhoorn avanderhoorn merged commit 61857be into Glimpse:master Jun 16, 2015

1 check passed

default Finished TeamCity Build Glimpse :: Continuous Integration : Tests passed: 942, ignored: 10
Details
@avanderhoorn avanderhoorn added this to the vNext milestone Jun 16, 2015
@avanderhoorn avanderhoorn self-assigned this Jun 16, 2015
@kendallb

Cool

Sent from my iPhone

Kendall Bennett
CEO & Founder
www.AMain.comhttp://www.amain.com/ | 530-894-0797tel:530-894-0797 | 800-705-2215tel:800-705-2215
424 Otterson Drive, Chico, California 95928x-apple-data-detectors://2/1

On Jun 16, 2015, at 9:36 AM, Anthony van der Hoorn <notifications@github.commailto:notifications@github.com> wrote:

Sorry that it got missed that that address. Have recieved it now and we are good to go.


Reply to this email directly or view it on GitHubhttps://github.com/Glimpse/Glimpse/pull/894#issuecomment-112490932.

@kendallb

Hi Guys,

Just checked to see if there are new NuGet builds for MVC4 and ADO that have this, but they are still all from 2014? Is this something that will get rebuilt at some point?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment