View Full Version : Sending log without error
peter Harris
27-Feb-2008, 06:59 PM
I have just purchased EurekaLog and wonder how I managed without it. It really is a very comprehensive and easy to use tool - thank you.
I wonder if it is possible to allow end users to generate a log and attachments to be sent by Email without generating an error. There is a function EurekaLogSendEmail but this seems to use the MAPI EMail client but I have users who do not have an Email client installed and I wonder if it is possible to use SMTP for this.
I can achieve what I want by forcing an error on clicking a button like this
procedure TViewlog.BitBtn1Click(Sender: TObject);
begin
raise exception.create('Eureka Log')
end;
but this is a little messy and I thought there may be a function to do this for me.
Any suggestions?
Peter
skydvrz
27-Feb-2008, 07:55 PM
Peter - be careful what you ask for. SMTP servers located at ISPs typically expect a user to poll their POP3 (incoming) mail first, before allowing the user to connect and send an email. This provides a modicum of security and is designed to prevent spam. POP3 requires a valid user name and password. SMTP usually doesn't use passwords.
The bottom line is that if your user has not checked email in the last 10-15 minutes, the SMTP error-log send won't go through. Sometimes it will work, sometimes not. :eek:
If you are developing a product for internal use inside a corporate LAN, then you might not have any issues - depending on how your IT department has configured your internal email servers. My code runs both inside and outside our corporate LAN, so I ran across this problem early on.
I switched to an open-sourced web-based bug logging system for just this reason. EurekaLog can be configured to send log files to your web server, instead of trying to get through the SMTP security jungle.
Using a web-based error log collection scheme also gets around most corporate and desktop firewalls, since they almost always allow HTML in/out.
I use an Apache web server and Mantis to capture incoming EurekaLog error logs. Both products are free.
Mantis can be used to assign bugs to specific developers and email them when new bugs come in. There is more value to the system than just working around the SMTP security problem.
peter Harris
28-Feb-2008, 09:56 AM
Thanks. That explains why it hasnt worked when I try it from another place! (Behind the NHS net firewall!)
Another problem this has highlighted is that even if I use the native EMail client (Outlook) the errorlog is stripped off because it has a .zip extension. To send zipped files as attachments they have to be renamed.
I can see a bit of work is needed Hmmm!
Peter
skydvrz
28-Feb-2008, 02:25 PM
The stripping off of zip file attachments is controlled by IT policy. They can turn that lovely feature on/off. Turning on zip file filtering is kind of naive, since it doesn't give you that much more security from virus infection, and most virus scanners can look inside zips anyway.
I am the IT manager at my company and I shut the zip filtering OFF. It causes too many problems with legitimate file attachments.
You can work around the whole log-zip filtering and email client problem using HTML over TCP/IP port 80. You can still use zips over HTML if you are concerned about bandwidth and security.
peter Harris
28-Feb-2008, 03:12 PM
Unfortunately since the NHS Net is the biggest (ie costliest) IT Project (ie disaster) in the world there is no chance of influencing their policy!
I will have a think about work-arounds. I didnt really want to go to the trouble of setting up a web-base help desk as I have gone down that route before and found it more trouble than it was worth. However I may revisit the idea.
Is it complex getting the bug report files to integrate into the web system? I am not the worlds most accomplished PHP script writer!
Peter
skydvrz
28-Feb-2008, 03:56 PM
Paul,
In the interest of full disclosure, I *do* write a lot of PHP code, so maybe that is why it was easy for me to set up Mantis :D
That being said, once I got past having to change some unreasonable default values in the Mantis PHP setup code, it all started to work fine and was well worth the effort.
The trick to getting the latest version of Mantis to work is changing the max number of password failures to something greater than 1. During the account adding process, it automatically blows one login attempt, thereby disabling any newly added accounts. :rolleyes:
This sort of saws off the limb of the tree you were sitting on. You can still access the admin account (don't blow THAT password!), but you can't add any new accounts until you fix the problem.
Change the PHP code to allow say 5 blown passwords, and it works fine. You just change one of the constants in a config file - a one line change.
You need MySQL which comes in the Mantis distribution, or you can use an existing MySQL installation.
You also need Apache or some other web server that supports PHP, and you need PHP itself. Obviously, you need to set up Apache on a PC that doesn't already have a web server running on it, or you will have to use some port other than 80. A non-standard HTML port could be problematic with your external users and their firewalls.
Configure your applications to send EurekaLog files to the bug server URL, using a "reporter" login.
Last, you need to set up port forwarding and IPs to make your shiny new bug server visible to external users.
When your app sends a EurekaLog error message to Mantis, it fills in most of the bug database fields automatically. It also sends the zip to the bug server, which gets stored in one of the MySQL tables as a BLOB record. When a new bug comes in, you will get an email from Mantis telling you about it, if you set Mantis up to do automated mailings. Since Mantis is inside your firewall, there should be no issues with sending email.
When you receive a Mantis bug report email, you just click on the link in the message. It takes you to the web site where you can look at the nice neat bug report.
You can click on the Mantis web page link to the zip file to open it and import the ELF file into your IDE/EL. You can also view the screen shot PNG or any other stuff you add to the zip payload. It is not much different than using direct email delivery of an EL log file.
Also - once you get the whole bug tracking system set up, it takes just a couple minutes to add new projects to it. You get one-stop-shopping for all your bug reports for all your projects.
peter Harris
28-Feb-2008, 04:07 PM
Thanks Ive had a look at it and it looks OK. I will have a play
Thanks for your advice
Peter
peter Harris
29-Feb-2008, 06:03 AM
Kevin - a load of thanks. Have installed Mantis on my website and it looks to be just what I need. I got a bit stuck at first as the installer told me my host had the wrong version of MySQL but someone on the mantis discussion forum pointed me to an earlier version that worked immediately
Many thanks
I will now have a go at integrating EurekaLog
Peter
peter Harris
29-Feb-2008, 02:43 PM
Got it all working and it is absolutely brilliant. Works absolutely seamlessly. Thanks for the suggestion.
Only problem is that my app tries to send an email as well but I think I know why.
Back to my original question - is it possible to force EurekaLog to send its log/files on demand without simulating an error which is what I am doing now?
Peter
peter Harris
29-Feb-2008, 02:45 PM
Another thing - if sending to website in this way, there isnt a prompt for "what did you do to cause this error"
Peter
skydvrz
29-Feb-2008, 09:03 PM
Only problem is that my app tries to send an email as well but I think I know why.
You have to blank out all the eurekalog email settings for the project.
is it possible to force EurekaLog to send its log/files on demand without simulating an error which is what I am doing now?
That is a question for Fabio :)
I only send logs when there is a crash, so I don't know enough to answer your question.
I do batch up a text log my app creates as the user does various things with the program, in case the end-user is doing some involved multi-step process to make my application crash. EL zips up this log along with the crash log and a screen shot and sends it to Mantis.
I don't want to see the run-time log, unless there is a problem - then it comes in handy for debugging.
skydvrz
29-Feb-2008, 09:12 PM
Another thing - if sending to website in this way, there isnt a prompt for "what did you do to cause this error"
I haven't tried that - I just refer to that runtime log I told you about, and it tells me what the end user was doing - not only at the time of the crash, but for the last couple days.
My logger saves the unit name, function name, line number and other info something like this:
[ ] -----------------------Startup @ 21-Nov-2007 10:10:49----------------------------
[I] EXE Name/Date: CopWrangler.exe:11/21/2007 8:15:50 AM FileVersion: 1.7.0.34, FileSize: 0, Comment: Member Applications, Host: crustycrab
21-Nov-2007 10:10:51 [I] ..\Lib\dglib\DGLIB.pas:3413 (DGLIB.PruneLogs) "Log prune in progress"
21-Nov-2007 10:10:51 [I] ..\Lib\dglib\DGLIB.pas:3429 (DGLIB.PruneLogs) "Log prune Complete"
21-Nov-2007 11:18:26 [E] cwMain.pas:2333 (cwMain.TcwMainForm.FormShow) "Invalid username/password: . Shutting down!"
peter Harris
01-Mar-2008, 01:20 PM
My logger saves the unit name, function name, line number and other info
If you don't mind me asking, how do you obtain the unit name, function name and line number?
I have been trying to log this info and not had any joy unless I hard code it.
Peter
skydvrz
01-Mar-2008, 02:11 PM
There are a bunch of debug functions in the Jedi JCL that return the unit/function/line number. They are in the JCLDebug unit.
Here is one of my logging functions:
TYPE
TLogLevel = (EDEBUG, EINFO, EWARN, EERROR);
TLogLevelRec = RECORD
Tag: STRING[8];
Abbrev: STRING[1];
END;
CONST
CurrLogLevel: TLogLevel = EDEBUG; // unit global
LogLevelNames: ARRAY[TLogLevel] OF TLogLevelRec =
(
(Tag: 'Debug'; Abbrev: 'D'), // normal debug - end user
(Tag: 'Info'; Abbrev: 'I'),
(Tag: 'Warning'; Abbrev: 'W'),
(Tag: 'Error'; Abbrev: 'E')
);
PROCEDURE LogMsg(CONST Msg : STRING; CONST LogLevel : TLogLevel);
VAR
Strg : STRING;
BEGIN
IF (LogLevel >= CurrLogLevel) THEN BEGIN
Strg := Format('[%s] %s:%u (%s) "%s"',
[LogLevelNames[LogLevel].Abbrev, FileByLevel(1),
LineByLevel(1), ProcByLevel(1), Msg]);
AppWriteLog(Strg);
END;
END;
AppWriteLog comes from the VG2 component library, but you could use any sort of text file writing method. The AppWriteLog function is thread safe, but LogMsg is not.
You probably need a log pruning function too, since text logs can get huge if your code is really chatty.
// prune complete lines of text off file (if necessary) until it is
// less than or equal to the max desired size in bytes. Works on very large text files.
// Eats head, leaves tail
PROCEDURE PruneTextFile(FName : STRING; MaxSizeBytes : Cardinal);
VAR
FIn,
FOut : TFileStream;
SR : TSearchRec;
TempName,
FileDir : STRING;
I : Integer;
R,
N : Longword;
Buff : ARRAY[0..$FFFF] OF Byte;
FoundEOL : Boolean;
S : Cardinal;
BEGIN
TRY
IF SysUtils.FindFirst(FName, faAnyFile, SR) <> 0 THEN // measure the file size
EXIT;
FINALLY
SysUtils.FindClose(SR);
END;
I := SR.Size;
IF (I AND $80000000) > 0 THEN BEGIN // test if integer wrapped on 2 Gb boundary
S := I AND $7FFFFFFF; // promote signed 32 bit int into unsigned 32 bit integer
S := S OR $80000000;
END
ELSE
S := I; // less than 2 Gb, so just copy it
IF S < MaxSizeBytes THEN
EXIT; // below size threshold, so exit
// open input text file
FileDir := AddBackSlash(ExtractFileDir(FName));
// create a temp file to copy tail to
DGGetTempFileName(FileDir, 'tmp', TempName);
Fin := TFileStream.Create(FName, fmOpenRead);
N := S - MaxSizeBytes; // calc approx amount of file head to chop off to achieve the desired size
Fin.Seek(N, soBeginning);
// read a (max) 64k block of file
R := Fin.Read(Buff, SizeOf(Buff));
FoundEOL := FALSE;
// search for cr/lf in initial block
// Bump N to first character of first desired line
FOR I := 0 TO R - 1 DO
IF (Buff[i] = $d) AND (Buff[I + 1] = $a) THEN BEGIN
INC(N, I + 2);
Fin.Seek(N, soBeginning); // seek to first complete line past max size of text file
FoundEOL := TRUE;
Break;
END;
IF NOT FoundEOL THEN BEGIN
Fin.Free; // error - could not find EOL in 64k worth of data
SysUtils.DeleteFile(TempName);
EXIT;
END;
// create a temp file
FOut := TFileStream.Create(TempName, fmOpenWrite);
// copy tail of source file to temp file
FOut.CopyFrom(Fin, S - N);
// clean up streams, since we are done with them
Fin.Free;
FOut.Free;
// delete the input file
SysUtils.DeleteFile(FName);
// rename the temp file to the original input file name
RenameFile(TempName, FName);
END;
peter Harris
01-Mar-2008, 03:08 PM
Thanks Thats very helpful. I already have a thread-safe logging routine which timestamps log events. However I was stuck with how to get the unit info.
I had read that there was a JCLDebug unit that could do it but I hadn't worked out how to do it.
Peter
admin
03-Mar-2008, 10:06 AM
Hi,
why do not add these new features suggestion in the suggestion forum? :)
peter Harris
03-Mar-2008, 10:20 AM
I will do that. Being a newby here I didn't want to appear too pushy ;)
admin
03-Mar-2008, 10:30 AM
Perfect! :)
vBulletin® v3.8.2, Copyright ©2000-2012, Jelsoft Enterprises Ltd.