#1 Re: Source Code repository » Introducing enhanced logging mechanism » 2015-08-28 09:46:03

I'm wanting to put in code like the following:

ILog := TSynLog.Enter(self,'param1'+param1+'param2'+param2);

However it won't compile in D2007.
Any ideas what I can do to make something like it work?

#2 Re: Source Code repository » Introducing enhanced logging mechanism » 2015-06-20 10:44:36

AB: Pleasure. Feel free to include the code into synlog and advise if you think I've missed anything in my formatting.
I'm also looking to improve the logview program based on this change for myself, perhaps with a diagram interface and/or automated log checking.
Any ideas where to start looking for existing code that does this?

#3 Re: Source Code repository » Introducing enhanced logging mechanism » 2015-06-19 13:56:24

I've looked at the data available for logging and come up with my own enter line format, which I think is reasonably parseable:

code address, ['-', instance address,] {' ', [ounitname, '.',] [instance class name, '@',] osymname, ' (', oline, ')',} ['  ', extra text]

Where:
[] and {} delimit sections which will hide/show depending on data availability or WithUnitName setting.
Instance is always assumed to be self and the methodname parameter I'd regard as extra text.
Not sure if I've made a mess of the MethodNameLocal item in my code though.
Two spaces before extra text to indicate free form text follows.
There are two sources for unit, which if produce different text would show both separated with '/'.
Instance class name is only shown if different from osymname class.

I don't know how involved it is changing the logviewer, but from what I've seen there aren't any changes necessary there.
Added in TSynMapFile = class:

  private
    class procedure GetLog(aAddressAbsolute: PtrUInt; out ounitname,
      osymname: rawutf8; out oline: integer); static;

Added before implementation - this allows lazy programmer to use self parameter in non-class procedure/function to no ill effect:

const self = nil;

This is a fix of class procedure TSynMapFile.Log to return data instead of logging it:

class procedure TSynMapFile.GetLog(aAddressAbsolute: PtrUInt; out ounitname, osymname : rawutf8;out oline : integer);
var u, s, Line, offset: integer;
begin
  ounitname := '';
  osymname := '';
  oline := -1;
  if (aAddressAbsolute=0) or (InstanceMapFile=nil) then
    exit;
  with InstanceMapFile do
    begin
      if not HasDebugInfo then exit;
      offset := AbsoluteToOffset(aAddressAbsolute);
      s := FindSymbol(offset);
      u := FindUnit(offset,Line);
      if s<0 then begin
        if u<0 then begin
          exit;
        end;
      end else
        if (u>=0) and (s>=0) then
          if u=fUnitSynLogIndex  then
            exit else // don't log stack trace internal to SynLog.pas :)
          if (u=fUnitSystemIndex) and (PosEx('Except',Symbols[s].Name)>0) then
            exit; // do not log stack trace of System.SysRaiseException
      if u>=0 then begin
        ounitname := Units[u].Symbol.Name;
        if s>=0 then
          if Symbols[s].Name=Units[u].Symbol.Name then
            s := -1;
      end;
      if s>=0 then
        osymname := Symbols[s].Name;
      if Line>0 then
        oline := Line;
    end;
end;

And changed procedure TSynLog.AddRecursion:

procedure TSynLog.AddRecursion(aIndex: integer; aLevel: TSynLogInfo);
type
  {$ifdef FPC}{$PACKRECORDS 1}{$endif}
  TTypeInfo = {$ifndef FPC}packed{$endif} record
    Kind: byte;
    Name: ShortString;
  end;
  {$ifdef FPC}{$PACKRECORDS C}{$endif}
  TClassType =
    {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
    packed
    {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
    record
     ClassType: TClass;
     ParentInfo: pointer;
     PropCount: SmallInt;
     UnitName: ShortString;
  end;
  PTypeInfo = ^TTypeInfo;
  PClassType = ^TClassType;
var Info: PTypeInfo;
    MS: cardinal;
    cunitname,csymname:string;
    ounitname,osymname:rawutf8;
    dotpos,oline : integer;
label DoEnt;
// normal procedure or function:
// Details: code address,                          {' ', [ounitname, '.',]                             osymname, ' (', oline, ')',} ['  ', extra text].
// method:
// Details: code address, ['-', instance address,] {' ', [ounitname, '.',] [instance class name, '@',] osymname, ' (', oline, ')',} ['  ', extra text].
begin
  with fThreadContext^ do
  if cardinal(aIndex)<cardinal(RecursionCount) then
  with Recursion[aIndex] do begin
    if aLevel<>sllLeave then begin
      TSynMapFile.GetLog(Caller,ounitname,osymname,oline);
      fWriter.AddPointer(Caller);
      if Instance<>nil then begin
        fWriter.Add('-');
        fWriter.AddPointer(PtrUInt(Instance));
      end;
      if ClassType<>nil then begin
        if fFamily.WithUnitName then begin
          Info := PPointer(PtrInt(ClassType)+vmtTypeInfo)^;
          if Info<>nil then begin
            {$ifdef FPC}
            cunitname := PClassType(GetFPCTypeData(pointer(Info)))^.UnitName;
            {$else}
            cunitname := PClassType(@Info^.Name[ord(Info^.Name[0])+1])^.UnitName;
            {$endif}
            if cunitname = '' then
            else
              if (ounitname <> cunitname) and (ounitname <> '') then
                ounitname := cunitname + '/' + ounitname;
          end;
        end;
        // classname:
        csymname := PShortString(PPointer(PtrInt(ClassType)+vmtClassName)^)^;
        if (osymname = '') then begin
          if (csymname <> '') then
            osymname := csymname + '@';
        end else begin
          if (csymname <> '') then
            if (csymname <> osymname) then begin
              dotpos := pos('.',osymname);
              if dotpos <> 0 then
                if csymname <> copy(osymname,1,dotpos-1) then
                  osymname := csymname + '@' + osymname
            end;
        end;
      end;
      if (fFamily.WithUnitName and (ounitname <> ''))
      or (osymname <> '') then begin
        fWriter.Add(' ');
        if (fFamily.WithUnitName and (ounitname <> '')) then begin
          fWriter.AddShort(ounitname);
          fWriter.Add('.');
        end;
        if (osymname <> '') then
          fWriter.AddShort(osymname);
        if (oline <> -1) then begin
          fWriter.Add(' ');
          fWriter.Add('(');
          fWriter.Add(oline);
          fWriter.Add(')');
        end;
      end;
      if MethodName<>nil then begin // extra text!
        fWriter.Add(' ');
        fWriter.Add(' ');
//        if MethodNameLocal<>mnLeave then begin
          fWriter.AddNoJSONEscape(MethodName);
//          if MethodNameLocal=mnEnter then
//            MethodNameLocal := mnLeave;
//        end;
      end;
    end;
    // Timestamp - start and stop.
    if fFamily.HighResolutionTimeStamp and (fFrequencyTimeStamp<>0) then
DoEnt:case aLevel of
        sllEnter: EnterTimeStamp := fCurrentTimeStamp;
        sllLeave: begin
                    if fFrequencyTimeStamp=0 then
                      MS := 0 else // avoid div per 0 exception
                      MS := ((fCurrentTimeStamp-EnterTimeStamp)*(1000*1000))div fFrequencyTimeStamp;
                    fWriter.AddMicroSec(MS);
                  end;
      end
    else
      if aLevel in [sllEnter,sllLeave] then
        begin
          QueryPerformanceCounter(fCurrentTimeStamp);
          dec(fCurrentTimeStamp,fStartTimeStamp);
          goto DoEnt;
        end;
  end;
  fWriter.AddEndOfLine(aLevel);
end;

Hope it is helpful to someone.

#4 Re: mORMot 1 » Delphi2007 [Pascal Fatal Error] SynLog.pas(2745): F2084 Internal Error » 2015-06-18 07:18:28

Found it, installed it and seems the problem has gone.  Thanks.
I see there are a bunch of IDE fixes there on Andy's website.
So I installed the others too.  My c:\installs\fixesforDelphi directory is getting full.
Not sure now about the vclfixpack.pas whether it conflicts with syncommons.pas and whether it should go before or after it in uses clause.

#5 Re: mORMot 1 » Delphi2007 [Pascal Fatal Error] SynLog.pas(2745): F2084 Internal Error » 2015-06-17 18:12:37

Yes, that's true.  Sorry, I didn't state in my original post that it compiles fine.  It's just the IDE gives that error and as a result some of the IDE assist features do not work so I had to figure out some sort of workaround or I'm stuck with a lot of asynchronous event driven code to debug and no help from the IDE.  I will most likely forget to uncomment the line when compiling for test or live.  I'm guessing if I moved that {$STACKFRAMES ON} section to the end of the unit just before the initialization section, it would be less of an issue.

#6 mORMot 1 » Delphi2007 [Pascal Fatal Error] SynLog.pas(2745): F2084 Internal Error » 2015-06-17 14:34:53

docme
Replies: 4

In Delphi 2007 (Version 11.0.2902.10471) IDE, I'm getting an IDE error when using relatively new (1 day old download of) synlog.pas from mORMot_and_Open_Source_friends_2015-06-16_112651_4986fea04f.
If I comment out the {$STACKFRAMES OFF} with '//', then it doesn't keep repeating '[Pascal Fatal Error] SynLog.pas(2745): F2084 Internal Error: AV06419F0F-W0000001C-1' in the build messages view.
Not sure if this causes issues I don't know about.

#7 Re: Source Code repository » Introducing enhanced logging mechanism » 2015-06-15 15:32:32

I'm enjoying the logging simplicity:

var ILog: ISynLog;
begin
  ILog := TSynLog.Enter;

But I have a rather messy user defined hierarchy of classes and cross-unit-inherited methods and when it is used for class methods, I'm wanting to also store the self value (and perhaps class type) also.
I've tried using:

  ILog := TSynLog.Enter(self,'something');

and

  ILog := TSynLog.Enter(self);

However these remove the unit name (and the .mab method name) from the log file line, which I want to keep there.
Any pointers as to how I can do this?
TIA

#8 Low level and performance » CSV faster code » 2014-03-28 08:53:16

docme
Replies: 1

Existing AddCSV code:

  for i := 0 to high(Integers) do begin
    Add(Integers[i]);
    Add(',');
  end;
  CancelLastComma;

faster code?:

  Add(Integers[0]);
  for i := 1 to high(Integers) do begin
    Add(',');
    Add(Integers[i]);
  end;

// for works same as a while loop.

#9 Re: Source Code repository » Introducing enhanced logging mechanism » 2014-03-27 13:37:29

Curious why the log PerformRotation procedure renames all the log files in sequence; instead of just making the new log file the next number up. (like Delphi history files).  Could be either way I think - boolean property driven feature.

Board footer

Powered by FluxBB