OT: A Question of Communication

OT: A Question of Communication

Old forum URL: forums.lhotka.net/forums/t/190.aspx


razorkai posted on Wednesday, May 24, 2006

Hi guys.

This is slightly off topic but I know there is a lot of clever folk hanging around here so I thought I'd bounce it off the forum.  This is a long one, so hope someone can be bothered to read it.

We have a requirement to be able to view information about the Csla activity both in respect to the Dataportal XYZ calls on the server and the Dataportal XYZ calls on the client.  Fortunately the framework supports this very nicely with some events.

In the client DataPortal we have two events we can hook up to from the UI

DataPortalInvoke
DataPortalInvokeComplete

In the server DataPortal we have two events we can catch in our object base classes

DataPortal_OnDataPortalInvoke
DataPortal_OnDataPortalInvokeComplete

This means we could effectively record information about what calls were made and when for both an individual client app on a user's PC and for the server side code for multiple users.  I have customised DataPortalEventArgs slightly to pass more information about what method is being processed and what the class of the BO concerned is.  So far so good.  The question is how to extract this information.  I don't want just a simple log file, ideally the event data should be extracted to some sort of live viewer so we can see an (almost) real time view of our apps/dataportals.  We should like to be able to choose a client app on another PC, connect to it and receive data from the events above.  Ideally the connection should trigger the event hookup to start so we don't have a performance hit when not connected.  Not entirely sure how to deal with the server side, as the objects reside within IIS.

I have looked at a number of different technologies so far in terms of the connection to a client app concept.  First off I looked at TcpListener and TcpClient.  This works relatively well, except things get a little complicated if you allow more than one monitor to connect to the same application at once.  I also had issues trying to read an object from a network stream.  Secondly I looked at remoting with client activated objects, but was put off by Ingo Rammer suggesting in an article in his website that we basically should not use remote delegates - the very concept I was thinking of using to pass the Dataportal event data across.  Finally I have been looking at pumping the data into an MSMQ and reading it from there.  This has been the best approach so far but I have issues trying to deal with multiple monitors looking at the same queue at the same time.

If anyone has any thoughts on any of these or a different approach to this problem I would love to hear them as I have been fighting with this for over a week and need to make some progress.

Many thanks for reading!

John.

Gwinsee replied on Wednesday, May 24, 2006

Razor,

If you don't mind dipping into the Win32 API (specifically OutputDebugString), you might want to take a look at DebugView from sysinternals.com (http://www.sysinternals.com/Utilities/DebugView.html).  I'm not sure if it will handle multiple client monitors but it's an idea for you to toss around.

- Gwin 

Bayu replied on Saturday, May 27, 2006

Hello,

For our server we use something incredulously simple: RSS.

Although we do not comply with any standard, we were inspired by the simplicity of this Really Simple Syndication. All logged data is simply made available over a (secured) custom-format xml-feed which can be read extremely easy, it's all plain xml.

This is not applicable to client apps of course as there is no trivial way to service an RSS feed on an arbitrary client.

The reason I wanted to mention the above though is because you mention some difficulty with getting your recorded events to remote machines. Maybe consider xml as a carrier? It's all just read-only, right?

I'm going to think about this some more, maybe I can think of a more elaborate solution which would provide a single way to get the logs both from servers and clients.

Bayu

razorkai replied on Wednesday, June 07, 2006

Bayu.

Any further developments here?  I am interested in your thoughts on this.  How do you output your RSS feed?  What I mean is do you always output the feed regardless of whether somone is listening and does this affect performance at all?

John.

rkelley replied on Wednesday, June 28, 2006

John,

Are you still working on this or did you find a solution? I am interested in doing the same thing. If you are still working on it maybe two heads will be better than one, if not and you did not find a solution if I continue down this path I will let you know what I find.

Ryan

RockfordLhotka replied on Wednesday, June 28, 2006

I would recommend looking at log4net or Enterprise Library (which has a logging component). Or just directly using the trace/log capabilities of .NET 2.0 itself. If you are using VB, the My namespace includes some nice logging abstractions.

All three solutions offer a great deal of flexibility, since they all work with the concept of a "listener". Your code is the source of log events, and you can hook listeners to the events (with control over what listeners "hear" what events). These listeners might write to a log file, the system event log, MSMQ, whatever.

I like log4net because it is the most mature of the three, and thus has the most pre-existing listeners that you can just use. This includes some listeners that provide centralization through queues, remoting, etc.

In short, why re-invent the wheel when both open-source and Microsoft are hard at work solving the problem?

razorkai replied on Thursday, June 29, 2006

In the end I did write my own custom TraceListener that writes data out to an MSMQ.  I looked at log4net but did not have the time to read all the docs and it seemed easier to just do it myself.  The only thing that I regret is that I had to modify the Csla code to get more information from the DataPortal events.  This makes applying the frequent updates a bit of a pain as I have to merge them in.  At present I am using this method to log server side calls only as it was decided that this was the priority.  It turned out that this was relatively easy.  I have added a webservice to my remote DataPortal that allows me to turn profiling on and off.  The service actually adds/removes an instance of my custome tracelistener from the server side process.  My custom BO base classes all check for the existence of a specifically named TraceListener before outputting any information.  This all works nicely.  It is invisaged that it will be extended to monitor the actual client apps at some point.  I would certainly be interested in anything you come up with Ryan, as the solution we have is still not ideal.

Jurjen replied on Thursday, June 29, 2006

Hi,

This type of  functionality is standard available in Petar's ActiveObjects extension of CSLA.
Check out : http://csla.kozul.info/

HTH
Jurjen.

razorkai replied on Thursday, June 29, 2006

Hi Jurgen.

Specifically what functionallity are you referring to. I have briefly looked at Active Objects several times but not found anything of particular interest.

John.

Jurjen replied on Thursday, June 29, 2006

John,

You''re right, this is not documented on the site, but if you search the archives of the old forum on www.searchcsla.com searching for ActiveLog you'll find several references to it.

It's some sort of monitor wich shows how much data is being transferred between your app and the dataportal.

As I understand it, this feature is implemented in the ActiveTracker application wich you can download from the above mentioned site.

Jurjen.

rkelley replied on Thursday, June 29, 2006

Thanks Jurjen, I will look into the ActiveLog a bit further. I am already using ActiveObjects just for other reasons, and I had forgotten it was there.

RockfordLhotka replied on Thursday, June 29, 2006

I am interested in exactly what extra information you chose to put into the args parameter? I realize that the info provided today is very minimal, and am open to adding extra info in future versions.
 
Rocky

razorkai replied on Thursday, June 29, 2006

The info I have added fully describes the call that the DataPortal is processing .  The current Csla can let you know through an event (OnDataPortalInvoke & OnDataPortalInvokeComplete) that a DataPortal xyz method has been called and when it has completed, but not what the call was.  Stuff like

BusinessObject class
name of the static method that was called
parameters passed in
time the call started

etc

I will attach my modified DataPortalEventArgs class in case you are interested.  Some of it may not make sense without seeeing how it is used, but it will give you an idea.  The code all seems to work nicely, but is far from production ready and has not been fully tested.

RockfordLhotka replied on Thursday, June 29, 2006

That is interesting, thanks.
 
I don't think, in the general case, that I'd choose to quite follow the same path. Instead, I think I'd rather do less work in the data portal itself, and just provide references so you could do more work in your OnDataPortal/Complete method implementaitons.
 
For instance, rather than stripping the property values out of the object, I think I'd rather pass the object reference. That way there's no real cost in the case that you don't do anything with that data.
 
I'm also not keen on walking the stack trace like you do. I think there's got to be a better way to find and identify the method that is being invoked - one that doesn't require liberal use of the NoInlining attribute and the expense of the stack walk.
 
But on the whole, I see the value in all the information you added and it helps me understand what you are after - thank you!
 
Rocky

razorkai replied on Thursday, June 29, 2006

RockfordLhotka:
I'm also not keen on walking the stack trace like you do.

Nether am I <g>. 

RockfordLhotka:

I think there's got to be a better way to find and identify the method that is being invoked - one that doesn't require liberal use of the NoInlining attribute and the expense of the stack walk.

As yet I haven't figured out another way to get that information.  I'm all ears if someone else can suggest how it could be done.....

nemaroller replied on Thursday, September 07, 2006

"I'm also not keen on walking the stack trace like you do. I think there's got to be a better way to find and identify the method that is being invoked - one that doesn't require liberal use of the NoInlining attribute and the expense of the stack walk."

Rocky, Its funny you mention this - because the property get/set examples for a root business class in the CSLA framework make heavy use of NoInlining and forces the framework to use System.Diagnostics.StackTrace to find the property name in a call to CanRead, CanWrite, PropertyHasChanged, etc. The alternative being supplying the literal string name of the property to those methods.

Which makes me wonder if something is fundamentally flawed about how that's structured. I have concerns about this - and if at some point you did too - I would like to know how or for what reason you calmed those fears.


RockfordLhotka replied on Thursday, September 07, 2006

nemaroller:
"I'm also not keen on walking the stack trace like you do. I think there's got to be a better way to find and identify the method that is being invoked - one that doesn't require liberal use of the NoInlining attribute and the expense of the stack walk."

Rocky, Its funny you mention this - because the property get/set examples for a root business class in the CSLA framework make heavy use of NoInlining and forces the framework to use System.Diagnostics.StackTrace to find the property name in a call to CanRead, CanWrite, PropertyHasChanged, etc. The alternative being supplying the literal string name of the property to those methods.

Which makes me wonder if something is fundamentally flawed about how that's structured. I have concerns about this - and if at some point you did too - I would like to know how or for what reason you calmed those fears.



Oh, that's easy Smile [:)]

If you look at the way data binding works in both Windows and Web Forms, you'll find that they make liberal use of various non-performant, but highly flexible and dynamic, technologies - most notably reflection. The overhead of my little System.Diagnostics call is trivial when stacked up against all the other overhead involved in the data binding model...

Beyond which, I specifically put the overloads that accept the string property name so you can avoid that overhead if desired. And if you are using code generation I absolutely recommend using the string literal overloads, because a code generator won't do a typo like a human coder.

Now if we had our own programming language, rather than C# or VB, then we could solve this problem. And to some degree, code generators are just fancy compilers, so you can argue that we do have our own language in a sense. And if you use one of these custom langauges, you can avoid the issue.

But if you want to use a lower-level language like VB or C#, then you have to play by their rules - and so the tradeoff is between maintainability and performance. My default is that maintainability wins unless performance is proven to be a problem...

The templates in the book are all designed around the idea of a human programmer writing all the code. Since my default priority is maintainability, that's why I use the auto-detecting overloads in the templates and snippets.

If I implemented a code generator in the book, my code generation templates would use the string literal overloads, because that's the clear choice for code that is not written or touched by human beings.

But what I'd really like to do (in a universe where I had infinite time) is create a true programming language at a higher level than VB or C#. One where you never have to write that ~14 lines of code per property, but instead just write one line. To me that would be the ideal solution!

nemaroller replied on Thursday, September 07, 2006

Thanks for the reply.

I personally suggested we drop the NoInlining attribute - mostly because it would not be clear to new developers or developers that would later maintain the code for what reason it was applied - plus the stack inspection hit would be removed.

Additionally, modifying your DefineACSLAProperty snippet allows designing a snippet that replaces the literals with the property name,  the error that would typically be introduced in hand-typing or copy/pasting the property name is eliminated.

public $PropertyType$ $PropertyName$
{
  get
  {
    CanReadProperty("$PropertyName$",true) ;
    return $PrivateVariable$;
  }
  set
  {
    CanWriteProperty("$PropertyName$",true);
    if (!$PrivateVariable$.Equals(value))
    {
      $PrivateVariable$ = value;
      PropertyHasChanged("$PropertyName$");
    }
  }
}

RockfordLhotka replied on Thursday, September 07, 2006

That's just fine - this is the type of flexibility I built into the framework, with the intent that people could make up their own minds about which approach to take.
 
Rocky

I personally suggested we drop the NoInlining attribute - mostly because it would not be clear to new developers or developers that would later maintain the code for what reason it was applied - plus the stack inspection hit would be removed.

Additionally, since the power of snippets allows designing a snippet that replaces the literals with the property name,  the error that would typically be introduced in hand-typing or copy/pasting the property name is eliminated.

Copyright (c) Marimer LLC