CobaltFusion / DebugViewPP

DebugView++, collects, views, filters your application logs, and highlights information that is important to you!
Boost Software License 1.0
1k stars 143 forks source link

Blank log viewer, does not display messages/logs although it is receiving them #258

Closed codenotes closed 7 years ago

codenotes commented 7 years ago

The app does not seem to actually display any log messages although it is definitely getting/processing them. Just a blank white area in the app.

Have tried 2 ways:

Have a UDP source listening, and can send data from a client to debugview (I can see it reacting in the status bar) but that app displays nothing. I can save the log file, and in a text editor, there is definitely the right data in there...but again, the window itself never fills or shows any data. GDI issue? Something specific to my machine or setup? This is Windows 10 x64.

I have also tried dragging a file into the app...the drag seems to complete ok, but, again, nothing is displayed where I would expect the app to display the files contents?

janwilmans commented 7 years ago

Are you sure no filters are defined? check both the tabs on View / Filter settings dialog image

codenotes commented 7 years ago

The precompiled binaries/install do display correctly when I remove all filters. But my source build (debug or release) does not. Definitely no filters present in these and they are getting messages but displaying nothing.

If you can tell me roughly where in the source a message is sent to display, I can set breakpoints and track down what's going on.

codenotes commented 7 years ago

For completion. I would also add, that the version of the app that DOES work is 1.2.0.4. Unfortunately, the build I am working with, which does not display anything is 1.7.0.25.

I would work with 1.2, however that lacks a UDP option which I need, so I need to get 1.7 to work. Again, if you can give me some sense of where in the code the handoff to the GUI is, I can likely find out what is going on. Maybe a bad device context or something?

janwilmans commented 7 years ago

Did you try the binaries of 1.7 ? You can get them from the releases section.

The point you are looking for is cmainframe::add message

codenotes commented 7 years ago

ok, so good news...the source code build (reports as 1.7.0.11, the latest beta) which I got from the releases as a .zip (did not git clone) did display correctly. The binary also works.

So, it is my cloned source that has the issues...maybe I got source in an in-between/being worked-on state from git master branch? Should I not be cloning (instead get sources from releases?)

Anyway, great news, because I can really use debugview++, it is what I have been looking for; need a better adb monitoring, debugging, and I plan to add a plugin for ROS/Robotics debugging and Unreal gaming engine...which is my main need.

janwilmans commented 7 years ago

Well, in general it is fine to just clone the repository, so I'm not sure what happened there. Ofsource the release-marked sources have been actually tested as-a-whole :) so they are a safe bet in case of problems.

Good to hear that you plan on adding plugins :), if you have any other problems, please create a new issue, or contact me directly on janwilmans at gmail.com. I will close this issue.

janwilmans commented 7 years ago

codenotes: so thanks for reporting the bugs :) both are fixed in the head right now. Turns out the 'not showing messages' was an accidentally committed experiment.

codenotes commented 7 years ago

I thought that might be the case...I do that myself on projects; I try to force myself to create new git branches when I experiment...but I don't/can't always.

Anyway good news, and I saw the new master branch is fixed which means I can fork it.

I followed your plugin code, and wrote a new plugin for my purposes (connecting to a remote TCP logging output in my environment). Followed SourceType, modded the SourceDlg, etc. and other classes and was able to get it working. A more generic plugin architecture, maybe a vtable-based COM-like thing might be a good direction...like what POCO or COM/ACtiveX does to let you create objects in a binary dll but get the pointer to the vtable back, then cast that to an interface...if I get some time, I will fork and pull req something like that...

Thank you for creating this app, it is sorely needed...I have a very sophisticated logging situation and I was pulling my hair out sorting through it. A logging app that can simultaneously pull in one or many sources, highlight, regex, etc. was what I was thinking I'd have to write myself. But I came across your app when searching and am grateful it is there. Saved me a ton of work.

janwilmans commented 7 years ago

I think 'regular' COM will introduce to more overhead (in timing delays) then I would like, but I think you are suggesting to use COM to instantiate the Logsource object and use the internal knowledge of the c++ implementation to cast it back to a regular c++ interface, right? I like that...

This way adding a plugin would be just putting a .dll in the same directory as the debugview++ executable.

See also https://github.com/djeedjay/DebugViewPP/issues/191

I would like to keep the logsources for Outputdebugstring and tailing files as part of the 'default' program. That way we keep a minimal viable product as a single executable.

I would be very grateful for any contribution you can made. Currently, I'm working on a new kind of view that can help sort out timing-issues.

This image below is just a mockup, but in GDIGraphicsPOC I'm working on the implementation.

image

janwilmans commented 7 years ago

What is also sorely needed, is the registry persistence of the logsources, so the next time you start debugview you can the last used logsources. See https://github.com/djeedjay/DebugViewPP/issues/213

I just haven't got around to it...

codenotes commented 7 years ago

I was wondering with that GDI POC was...now I see. Yeah, that would be every handy.

Well, wrt COM...I dont think one needs the COM mechanism, just to work the way COM does. You have a class in a DLL based entierely on virtual functions (an interface). Like: //in plugin DLL struct IMyplugin { virtual func1()=0; virtual func2()=0; };

void createThePlugin(void out) //factory { out=(void)new IMyplugin;

} and that plugin dll also has a factory, so from DebugView, it calls:

//From debugView: //after you load ("yourdll.dll",

include "MyPluginHeader.h" //has the interface def in it, but that's all.

IMyplugin thePlugin; extern "C" { void createThePlugin(void ** out) ;//factory }

createThePlugin((void**)thePlugin);

...and you can go to town calling the methods.

All you are doing there is passing a vtable pointer, and that works on every compiler and between versions of all compilers because C++ standardizes this...unlike exporting C++ classes, it is not subject to name mangling or issues. That is what COM does deep down.

The library POCO has an implementation of this, but it is also very easy to do oneself.

Maybe I will write this and pull request it...I have more plugins to write, and it is a little slow going to modify the app every time.

The only thing that is missing is a way to get variable data in a UI depending on what the plugin needs. You have IP and PORT there, but we need some form of meta data, field creation there...

janwilmans commented 7 years ago

Well, the poor-mans solution would be to add an 'arguments' string field that the plugin can parse. We could do that as a first implementation, but I think we could just add a GetArguments() on the plugin that returns a std::vector. Include a type in class Argument to indication the type of data (int, double, string, ipaddress) and a 'displayname' so we can just pass these values explicitly to the plugin

class Argument
{
  enum class Type { int, double, string, ipaddress };
  ... set/getters  
private:
  std::string m_displayname;
  Type m_type;
  int m_intvalue;
  double m_doublevalue;
  std::string m_stringvalue;
}
codenotes commented 7 years ago

you use boost (I love boost) so we could return a vector of "any".

The trickier part (not tricky really, just work) would be dynamically creating the windows controls on the dialog to match what the given plugin wants. Or could just be a single text field where the user types his arguments in a delimeted way like a connection string, and let the plugin just parse that. ie,

//user input on textr field on dialog arg1=hi;arg2=3.12arg3=192.168.0.1

And debugview literally just passes this string with no qualifications or validation. If the plugin doesn't like it, it can send a debug message [internal] to the gui.

BTW: how does one log to the gui directly..i see [internal] and tracked it down, but didn't look too far into it. Is there a simple function to just put a log on the GUI that comes from an internal operation (like the plugin?)

codenotes commented 7 years ago

Thinking more on this, a ListView control on SourceDlg may be all that's needed...can fill in all the data as strings there. Can ask the plugin what it wants, create fields with those names, and let the user enter a single line to enter the values. Pass the line back as a string.

janwilmans commented 7 years ago

That could work and it would be simple == I like it. The logging to the UI is done through the method LogSources::AddMessage in case you do it from the UI thread. If logging from an LogSource, it is done using LogSource::AddInternal