zeoslib  UNKNOWN
 All Files
ZSqlMonitor.pas
Go to the documentation of this file.
1 {*********************************************************}
2 { }
3 { Zeos Database Objects }
4 { SQL Monitor component }
5 { }
6 { Originally written by Sergey Seroukhov }
7 { }
8 {*********************************************************}
9 
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
12 { }
13 { License Agreement: }
14 { }
15 { This library is distributed in the hope that it will be }
16 { useful, but WITHOUT ANY WARRANTY; without even the }
17 { implied warranty of MERCHANTABILITY or FITNESS FOR }
18 { A PARTICULAR PURPOSE. See the GNU Lesser General }
19 { Public License for more details. }
20 { }
21 { The source code of the ZEOS Libraries and packages are }
22 { distributed under the Library GNU General Public }
23 { License (see the file COPYING / COPYING.ZEOS) }
24 { with the following modification: }
25 { As a special exception, the copyright holders of this }
26 { library give you permission to link this library with }
27 { independent modules to produce an executable, }
28 { regardless of the license terms of these independent }
29 { modules, and to copy and distribute the resulting }
30 { executable under terms of your choice, provided that }
31 { you also meet, for each linked independent module, }
32 { the terms and conditions of the license of that module. }
33 { An independent module is a module which is not derived }
34 { from or based on this library. If you modify this }
35 { library, you may extend this exception to your version }
36 { of the library, but you are not obligated to do so. }
37 { If you do not wish to do so, delete this exception }
38 { statement from your version. }
39 { }
40 { }
41 { The project web site is located on: }
42 { http://zeos.firmos.at (FORUM) }
43 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
44 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
45 { }
46 { http://www.sourceforge.net/projects/zeoslib. }
47 { }
48 { }
49 { Zeos Development Group. }
50 {********************************************************@}
51 
52 unit ZSqlMonitor;
53 
54 interface
55 
56 {$I ZComponent.inc}
57 
58 uses
59  SysUtils, Classes, Contnrs, {$IFDEF MSEgui}mclasses,{$ENDIF}
60  ZClasses, ZCompatibility, ZDbcIntfs, ZDbcLogging;
61 
62 type
63 
64  {** Repeat declaration of TZLoggingEvent. }
65  TZLoggingEvent = ZDbcLogging.TZLoggingEvent;
66 
67  {** Repeat declaration of TZLoggingFormatter. }
68  IZLoggingFormatter = ZDbcLogging.IZLoggingFormatter;
69  TZLoggingFormatter = ZDbcLogging.TZLoggingFormatter;
70 
71  {** Declares event before logging. }
72  TZTraceEvent = procedure(Sender: TObject; Event: TZLoggingEvent;
73  var LogTrace: Boolean) of object;
74 
75  {** Declares event after logging. }
76  TZTraceLogEvent = procedure(Sender: TObject; Event: TZLoggingEvent) of object;
77 
78  {**
79  Implements an object to log events from SQL client.
80  }
81  TZSQLMonitor = class(TComponent, IZLoggingListener, IZInterface)
82  private
83  FActive: Boolean;
84  FAutoSave: Boolean;
85  FFileName: string;
86  FMaxTraceCount: Integer;
87  FTraceList: TObjectList;
88  FOnTrace: TZTraceEvent;
89  FOnLogTrace: TZTraceLogEvent;
90  FLoggingFormatter : IZLoggingFormatter;
91 
92  function GetTraceCount: Integer;
93  function GetTraceItem(Index: Integer): TZLoggingEvent;
94  procedure SetActive(const Value: Boolean);
95  procedure SetMaxTraceCount(const Value: Integer);
96 
97  procedure TruncateTraceList(Count: Integer);
98  procedure DoTrace(Event: TZLoggingEvent; var LogTrace: Boolean);
99  procedure DoLogTrace(Event: TZLoggingEvent);
100  public
101  constructor Create(AOwner: TComponent); override;
102  destructor Destroy; override;
103 
104  procedure LogEvent(Event: TZLoggingEvent);
105  procedure Save();
106  procedure SaveToFile(const FileName: string);
107 
108  property TraceCount: Integer read GetTraceCount;
109  property TraceList[Index: Integer]: TZLoggingEvent read GetTraceItem;
110  property LoggingFormatter: IZLoggingFormatter read FLoggingFormatter write FLoggingFormatter;
111  published
112  property Active: Boolean read FActive write SetActive default False;
113  property AutoSave: Boolean read FAutoSave write FAutoSave default False;
114  property FileName: string read FFileName write FFileName;
115  property MaxTraceCount: Integer read FMaxTraceCount write SetMaxTraceCount;
116 
117  property OnTrace: TZTraceEvent read FOnTrace write FOnTrace;
118  property OnLogTrace: TZTraceLogEvent read FOnLogTrace write FOnLogTrace;
119  end;
120 
121 implementation
122 
123 {$IFDEF WITH_UNITANSISTRINGS}
124 uses AnsiStrings;
125 {$ENDIF}
126 
127 { TZSQLMonitor }
128 
129 {**
130  Constructs this object and assignes main properties.
131  @param AOwner a component owner.
132 }
133 constructor TZSQLMonitor.Create(AOwner: TComponent);
134 begin
135  inherited Create(AOwner);
136  FTraceList := TObjectList.Create;
137  FMaxTraceCount := 100;
138 end;
139 
140 {**
141  Destroys this object and cleanups the memory.
142 }
143 destructor TZSQLMonitor.Destroy;
144 begin
145  SetActive(False);
146  FTraceList.Free;
147  inherited Destroy;
148 end;
149 
150 {**
151  Gets a number of stored logging events.
152  @returns a number of stored logging events.
153 }
154 function TZSQLMonitor.GetTraceCount: Integer;
155 begin
156  Result := FTraceList.Count;
157 end;
158 
159 {**
160  Gets a logging event by it's index.
161  @param Index an event index.
162  @retuns a requested event object.
163 }
164 function TZSQLMonitor.GetTraceItem(Index: Integer): TZLoggingEvent;
165 begin
166  Result := TZLoggingEvent(FTraceList[Index]);
167 end;
168 
169 {**
170  Sets an active state for this monitor.
171  @param Value <code>True</code> to activate this monitor
172  and <code>False</code> to deactivate it.
173 }
174 procedure TZSQLMonitor.SetActive(const Value: Boolean);
175 begin
176  if FActive <> Value then
177  begin
178  if Value then
179  DriverManager.AddLoggingListener(Self)
180  else
181  if Assigned(DriverManager) then
182  DriverManager.RemoveLoggingListener(Self);
183  FActive := Value;
184  end;
185 end;
186 
187 {**
188  Sets a new number of logging events in the storage.
189  @param Value a new number of logging events.
190 }
191 procedure TZSQLMonitor.SetMaxTraceCount(const Value: Integer);
192 begin
193  if Value <> FMaxTraceCount then
194  begin
195  FMaxTraceCount := Value;
196  TruncateTraceList(Value);
197  end;
198 end;
199 
200 {**
201  Truncates a storage of logging events to the specified limit.
202  @param Count a number of events in the storage.
203 }
204 procedure TZSQLMonitor.TruncateTraceList(Count: Integer);
205 begin
206  while FTraceList.Count > Count do
207  FTraceList.Delete(0);
208 end;
209 
210 {**
211  Invokes an event listener after logging event.
212  @param Event a logging event object.
213 }
214 procedure TZSQLMonitor.DoLogTrace(Event: TZLoggingEvent);
215 begin
216  if Assigned(FOnLogTrace) then
217  FOnLogTrace(Self, Event);
218 end;
219 
220 {**
221  Invokes an event listener before logging event.
222  @param Event a logging event object.
223  @param LogTrace a flag which switches storing the event.
224 }
225 procedure TZSQLMonitor.DoTrace(Event: TZLoggingEvent;
226  var LogTrace: Boolean);
227 begin
228  if Assigned(FOnTrace) then
229  FOnTrace(Self, Event, LogTrace);
230 end;
231 
232 {**
233  Saves the logging events into predefined file
234  set in FileName property.
235 }
236 procedure TZSQLMonitor.Save;
237 begin
238  SaveToFile(FFileName);
239 end;
240 
241 {**
242  Saves the logging events to the specified file.
243  @param FileName a name of the file to write the events.
244 }
245 procedure TZSQLMonitor.SaveToFile(const FileName: string);
246 var
247  I: Integer;
248  Stream: TFileStream;
249 Temp: Ansistring;
250 Buffer: PAnsiChar;
251 begin
252  if not FileExists(FileName) then
253  Stream := TFileStream.Create(FileName, fmCreate)
254  else
255  Stream := TFileStream.Create(FileName, fmOpenWrite or fmShareDenyWrite);
256  try
257  for I := 0 to FTraceList.Count - 1 do
258  begin
259  Temp := AnsiString(TZLoggingEvent(FTraceList[I]).AsString + LineEnding);
260  Buffer := PAnsiChar(Temp);
261  Stream.Write(Buffer^, {$IFDEF WITH_STRLEN_DEPRECATED}AnsiStrings.{$ENDIF}StrLen(Buffer) * sizeof(Ansichar));
262  end;
263  finally
264  Stream.Free;
265  end;
266 end;
267 
268 {**
269  Handles a new incoming logging event.
270  @param Event an incoming logging event.
271 }
272 procedure TZSQLMonitor.LogEvent(Event: TZLoggingEvent);
273 var
274  LogTrace: Boolean;
275  Stream: TFileStream;
276 Temp: Ansistring;
277 Buffer: PAnsiChar;
278 begin
279  LogTrace := True;
280  DoTrace(Event, LogTrace);
281  if not LogTrace then Exit;
282 
283  { Store the event. }
284  if FMaxTraceCount <> 0 then
285  begin
286  if FMaxTraceCount > 0 then
287  TruncateTraceList(FMaxTraceCount - 1);
288  FTraceList.Add(TZLoggingEvent.Create(Event.Category, Event.Protocol,
289  Event.Message, Event.ErrorCode, Event.Error));
290  end;
291 
292  { Save the event. }
293  if FAutoSave and (FFileName <> '') then
294  begin
295  if not FileExists(FFileName) then
296  Stream := TFileStream.Create(FFileName, fmCreate)
297  else
298  Stream := TFileStream.Create(FFileName, fmOpenReadWrite or fmShareDenyWrite);
299  try
300  Stream.Seek(0, soFromEnd);
301  Temp := AnsiString(Event.AsString(FLoggingFormatter) + LineEnding);
302  Buffer := PAnsiChar(Temp);
303  Stream.Write(Buffer^, {$IFDEF WITH_STRLEN_DEPRECATED}AnsiStrings.{$ENDIF}StrLen(Buffer)*sizeof(Ansichar));
304  finally
305  Stream.Free;
306  end;
307  end;
308 
309  DoLogTrace(Event);
310 end;
311 
312 end.