TWriterAppenderUnit.pas 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. {
  2. Copyright 2005-2006 Log4Delphi Project
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. }
  13. {*----------------------------------------------------------------------------
  14. Contains the TWriterAppender class.
  15. @version 0.5
  16. @author <a href="mailto:tcmiller@users.sourceforge.net">Trevor Miller</a>
  17. ----------------------------------------------------------------------------}
  18. unit TWriterAppenderUnit;
  19. {$ifdef fpc}
  20. {$mode objfpc}
  21. {$h+}
  22. {$endif}
  23. interface
  24. uses
  25. Classes,
  26. TAppenderUnit, TLayoutUnit, TLoggingEventUnit,
  27. TLevelUnit, TPrintWriterUnit;
  28. type
  29. {*----------------------------------------------------------------------------
  30. TWriterAppender appends log events to a TWriter. This can be used in
  31. combination with streams thus allowing logging to file streams, network
  32. streams or other stream based resources.
  33. ----------------------------------------------------------------------------}
  34. TWriterAppender = class (TAppender)
  35. private
  36. protected
  37. FWriter : TPrintWriter;
  38. FImmediateFlush : Boolean;
  39. procedure WriteFooter();
  40. procedure WriteHeader();
  41. public
  42. constructor Create(); Overload;
  43. constructor Create(ALayout : TLayout; AStream : TStream); Overload;
  44. destructor Destroy; Override;
  45. procedure Close();
  46. procedure Append(AEvent : TLoggingEvent); Override;
  47. procedure SetImmediateFlush(AFlush : Boolean);
  48. procedure SetStream(AStream : TStream);
  49. function GetImmediateFlush() : Boolean;
  50. function RequiresLayout() : Boolean; Override;
  51. end;
  52. implementation
  53. uses
  54. TLogLogUnit;
  55. {*----------------------------------------------------------------------------
  56. Write a footer as produced by the embedded layout's Layout.getFooter
  57. method.
  58. ----------------------------------------------------------------------------}
  59. procedure TWriterAppender.WriteFooter();
  60. begin
  61. if (not Self.FClosed) then
  62. Self.FWriter.Println(Self.FLayout.GetFooter);
  63. end;
  64. {*----------------------------------------------------------------------------
  65. Write a header as produced by the embedded layout's Layout.getHeader method.
  66. ----------------------------------------------------------------------------}
  67. procedure TWriterAppender.WriteHeader();
  68. begin
  69. if (not Self.FClosed) then
  70. Self.FWriter.Println(Self.FLayout.GetHeader);
  71. end;
  72. {*----------------------------------------------------------------------------
  73. Instantiate a WriterAppender.
  74. ----------------------------------------------------------------------------}
  75. constructor TWriterAppender.Create();
  76. begin
  77. inherited Create;
  78. Self.FWriter := Nil;
  79. Self.FImmediateFlush := true;
  80. end;
  81. {*----------------------------------------------------------------------------
  82. Instantiate a WriterAppender and set the output destination to stream.
  83. This class does not free the TStream paramter, it is the callers duty
  84. to do so. The contained writer is, however, freed by this class.
  85. @param ALayout The layout to use
  86. @param AStream The stream to use
  87. ----------------------------------------------------------------------------}
  88. constructor TWriterAppender.Create(ALayout : TLayout; AStream : TStream);
  89. begin
  90. inherited Create;
  91. TLogLog.debug('TWriterAppender.Create');
  92. Self.FLayout := ALayout;
  93. Self.FThreshold := TLevelUnit.DEBUG;
  94. Self.FName := ClassName;
  95. Self.SetStream(AStream);
  96. Self.FImmediateFlush := true;
  97. Self.WriteHeader;
  98. end;
  99. {*----------------------------------------------------------------------------
  100. Destruct this instance by freeing the contained TWriter instance.
  101. ----------------------------------------------------------------------------}
  102. destructor TWriterAppender.Destroy;
  103. begin
  104. if not Self.FClosed then
  105. Self.Close;
  106. Self.FWriter.Free;
  107. TLogLog.debug('TWriterAppender#Destroy');
  108. inherited Destroy;
  109. end;
  110. {*----------------------------------------------------------------------------
  111. Close this appender instance. Closed appenders cannot be reused.
  112. ----------------------------------------------------------------------------}
  113. procedure TWriterAppender.Close();
  114. begin
  115. if (Self.FClosed) then
  116. exit;
  117. if (self.FLayout <> Nil) then
  118. Self.WriteFooter;
  119. Self.FClosed := true;
  120. end;
  121. {*----------------------------------------------------------------------------
  122. If the writer exists and is writable then write a log statement to the
  123. writer.
  124. @param AEvent The event to log
  125. ----------------------------------------------------------------------------}
  126. procedure TWriterAppender.Append(AEvent : TLoggingEvent);
  127. begin
  128. if (Self.FClosed) then begin
  129. if (Self.FErrorHandler <> Nil) then
  130. Self.FErrorHandler.Error(
  131. 'This appender is closed and cannot be written to.');
  132. Exit;
  133. end;
  134. Self.FWriter.Println(Self.Flayout.Format(AEvent));
  135. if not (Self.Flayout.IgnoresException) then
  136. if (AEvent.getException <> Nil) then
  137. Self.FWriter.Println('Exception: ' + AEvent.GetException.Message);
  138. end;
  139. {*----------------------------------------------------------------------------
  140. If the ImmediateFlush option is set to true, the appender will flush at the
  141. end of each write. This is the default behavior.
  142. @param AFlush Whether to flush or not
  143. ----------------------------------------------------------------------------}
  144. procedure TWriterAppender.SetImmediateFlush(AFlush : Boolean);
  145. begin
  146. Self.FImmediateFlush := AFlush;
  147. end;
  148. {*----------------------------------------------------------------------------
  149. Setup the writer to use the given stream.
  150. @param AStream The stream to write to
  151. ----------------------------------------------------------------------------}
  152. procedure TWriterAppender.SetStream(AStream : TStream);
  153. begin
  154. Self.FWriter.Free;
  155. Self.FWriter := TPrintWriter.Create(AStream);
  156. end;
  157. {*----------------------------------------------------------------------------
  158. Returns value of the ImmediateFlush option.
  159. @return True if immediate flush is set, false otherwise
  160. ----------------------------------------------------------------------------}
  161. function TWriterAppender.GetImmediateFlush() : Boolean;
  162. begin
  163. Result := Self.FImmediateFlush;
  164. end;
  165. {*----------------------------------------------------------------------------
  166. Determines if this appender requires a layout. This appender does require
  167. a layout.
  168. @return True since this appender requires a layout
  169. ----------------------------------------------------------------------------}
  170. function TWriterAppender.RequiresLayout() : Boolean;
  171. begin
  172. Result := true;
  173. end;
  174. end.