///
/// Copyright © 2003-2008 JetBrains s.r.o.
/// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder).
///
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading;
using System.Windows.Forms;
using ICSharpCode.SharpZipLib.GZip;
using JetBrains.Omea.Base;
using JetBrains.Omea.GUIControls;
using JetBrains.Omea.OpenAPI;
namespace JetBrains.Omea
{
///
/// Manages writing of the log file and the usage log.
///
internal class LogManager
{
private static string _logDir;
private static string _logName;
private static OmniaMeaTraceListener _traceListener;
private static string _usageLogId;
#if USAGE_LOG
private static StreamWriter _usageLogWriter;
#endif
internal static void InitializeLog()
{
_logDir = RegUtil.LogPath;
if ( _logDir == null )
{
_logDir = Application.StartupPath;
}
string logName = "Omea-" + DateTime.Now.ToString( "yyMMdd-HHmm" ) + ".log";
if ( _logDir != "" )
{
_logName = Path.Combine( _logDir, logName );
try
{
Directory.CreateDirectory( _logDir );
StreamWriter fs = File.CreateText( _logName );
fs.Close();
}
catch( Exception )
{
// don't fail if the log dir is set to a folder where we do not have write access
_logDir = "";
}
}
if ( _logDir != "" )
{
_traceListener = new OmniaMeaTraceListener( _logName );
Debug.Listeners.Add( _traceListener );
Trace.WriteLine( "Starting Omea" );
}
}
internal static void InitializeUsageLog()
{
_usageLogId = Core.SettingStore.ReadString( "MainFrame", "UsageLogID ");
if ( string.IsNullOrEmpty( _usageLogId ) )
{
_usageLogId = Guid.NewGuid().ToString();
Core.SettingStore.WriteString( "MainFrame", "UsageLogID", _usageLogId );
}
Core.AddExceptionReportData( "ID " + _usageLogId );
}
///
/// Deletes log files that are older than the specified number of days.
///
/// Maximum log age, in days.
internal static void DeleteOldLogs( int maxAge )
{
if( _logDir != "" )
{
// Find the log files, their name format is: "Omea-" + DateTime.Now.ToString( "yyMMdd-HHmm" ) + ".log"
DirectoryInfo dirLogs = new DirectoryInfo( _logDir );
ArrayList logFiles = new ArrayList();
logFiles.AddRange( dirLogs.GetFiles( "Omea-??????-????.log" ) ); // Add Omea log files
logFiles.AddRange( dirLogs.GetFiles( "Omea-??????-????.log.gz" ) ); // Add the log files that were packed for submitting along with an exception
foreach( FileInfo logFile in logFiles )
{
try
{
if( (DateTime.Now - logFile.LastWriteTime).TotalDays >= maxAge )
logFile.Delete();
}
catch( Exception )
{
}
}
}
}
///
/// Generates an unique name for a usage log file and opens the file.
///
internal static void InitUsageLog()
{
#if USAGE_LOG
string usageLogName = Path.Combine( _logDir, "UsageLog.txt" );
bool usageLogEnabled = Core.SettingStore.ReadBool( "MainFrame", "UsageLogEnabled", true );
if ( usageLogEnabled )
{
if ( _usageLogWriter == null )
{
_usageLogWriter = new StreamWriter( usageLogName, true );
WriteToUsageLog( "[Run] Starting [" + Core.ProductName + "] ver [" + Core.ProductVersion + "]" );
}
}
else
{
if ( _usageLogWriter != null )
{
_usageLogWriter.Close();
}
_usageLogWriter = null;
File.Delete( usageLogName );
}
#endif
}
///
/// Writes a string to the usage log.
///
internal static void WriteToUsageLog( string text )
{
#if USAGE_LOG
if ( _usageLogWriter != null )
{
_usageLogWriter.Write( DateTime.Now.ToString( "dd.MM.yyyy HH:mm:ss " ) + text + "\n" );
}
#endif
}
internal static bool UsageLogEnabled
{
get
{
#if USAGE_LOG
return _usageLogWriter != null;
#else
return false;
#endif
}
}
///
/// Submits the usage log to the server.
///
internal static void SubmitUsageLog()
{
#if USAGE_LOG
if ( _usageLogWriter == null )
{
return;
}
_usageLogWriter.Close();
_usageLogWriter = null;
string usageLogName = Path.Combine( _logDir, "UsageLog.txt" );
string usageLogID = Core.SettingStore.ReadString( "MainFrame", "UsageLogID ");
WebClient client = new WebClient();
try
{
client.UploadFile( "http://collect-it.jetbrains.net/" + usageLogID, "POST", usageLogName );
File.Delete( usageLogName );
}
catch( Exception ex )
{
Trace.WriteLine( "Error submitting usage log: " + ex );
}
InitUsageLog();
#endif
}
internal static void CloseUsageLog()
{
#if USAGE_LOG
if ( _usageLogWriter != null )
{
_usageLogWriter.Close();
_usageLogWriter = null;
}
#endif
}
public static void SubmitErrorLog()
{
if ( _logName == null )
{
return;
}
_traceListener.Close();
Debug.Listeners.Remove( _traceListener );
Exception submitError = null;
using( new WaitCursorDisplayer() )
{
try
{
string gzLogName = _logName + ".gz";
Stream fileStream = new FileStream( gzLogName, FileMode.Create );
GZipOutputStream gzStream = new GZipOutputStream( fileStream );
Stream logStream = new FileStream( _logName, FileMode.Open );
if ( logStream.Length > 1000000 )
{
logStream.Position = logStream.Length - 1000000;
}
int bytesRemaining = (int) (logStream.Length - logStream.Position);
byte[] buffer = new byte[65536] ;
while( bytesRemaining > 0 )
{
int blockSize = Math.Min( bytesRemaining, 65536 );
bytesRemaining -= blockSize;
logStream.Read( buffer, 0, blockSize );
gzStream.Write( buffer, 0, blockSize );
}
logStream.Close();
gzStream.Close();
WebClient client = new WebClient();
client.UploadFile( "http://collect-it.jetbrains.net/" + _usageLogId, "POST", gzLogName );
File.Delete( gzLogName );
}
catch( Exception ex )
{
submitError = ex;
}
}
_traceListener = new OmniaMeaTraceListener( _logName );
Debug.Listeners.Add( _traceListener );
if ( submitError != null )
{
Trace.WriteLine( "Error submitting log: " + submitError.ToString() );
}
}
}
internal class OmniaMeaTraceListener: TextWriterTraceListener
{
private bool _NewLine = true;
internal OmniaMeaTraceListener( string filename )
: base( filename )
{
}
public override void Write( string message )
{
try
{
if ( _NewLine )
WriteDate();
base.Write(message);
Writer.Flush();
}
catch( Exception )
{
// ignore
}
}
public override void WriteLine( string message )
{
try
{
if ( _NewLine )
WriteDate();
base.WriteLine( message );
Writer.Flush();
_NewLine = true;
}
catch( Exception )
{
// ignore
}
}
private void WriteDate()
{
base.Write( DateTime.Now.ToString( "dd.MM.yyyy HH:mm:ss.fff " ) );
string threadName = Thread.CurrentThread.Name;
base.Write( "[" + ( !string.IsNullOrEmpty( threadName ) ? threadName [0] : '?' ) + "] " );
_NewLine = false;
}
}
}