~ubuntu-branches/ubuntu/saucy/monodevelop/saucy-proposed

« back to all changes in this revision

Viewing changes to src/core/MonoDevelop.Core/MonoDevelop.Core/LoggingService.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields, 1840cc1
  • Date: 2012-02-05 10:49:36 UTC
  • mfrom: (10.2.12)
  • Revision ID: package-import@ubuntu.com-20120205104936-f3dutq6lnseokb6d
Tags: 2.8.6.3+dfsg-1
[1840cc1] Imported Upstream version 2.8.6.3+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
using System;
30
30
using System.Collections.Generic;
 
31
using System.IO;
 
32
using System.Linq;
31
33
 
32
34
using MonoDevelop.Core.Logging;
33
35
 
71
73
                                }
72
74
                        }
73
75
                }
 
76
 
 
77
                static FilePath GenericLogFile {
 
78
                        get { return "MonoDevelop.log"; }
 
79
                }
 
80
 
 
81
                static string FormattedGenericLogFile (int value)
 
82
                {
 
83
                        return string.Format ("MonoDevelop-{0}.log", value);
 
84
                }
 
85
 
 
86
                static string FormattedUniqueFileName (DateTime timestamp)
 
87
                {
 
88
                        return string.Format ("MonoDevelop.{0}.log", timestamp.ToString ("yyyy-MM-dd__HH-mm-ss"));
 
89
                }
 
90
                
 
91
                public static void Initialize (bool redirectOutput)
 
92
                {
 
93
                        PurgeOldLogs ();
 
94
                        
 
95
                        if (Platform.IsWindows || redirectOutput)
 
96
                                RedirectOutputToLogFile ();
 
97
                }
 
98
                
 
99
                static void PurgeOldLogs ()
 
100
                {
 
101
                        // Delete all logs older than 30 days
 
102
                        if (!Directory.Exists (UserProfile.Current.LogDir))
 
103
                                return;
 
104
 
 
105
                        var files = Directory.EnumerateFiles (UserProfile.Current.LogDir, "MonoDevelop.*.log")
 
106
                                .Select (f => new FileInfo (f))
 
107
                                .Where (f => f.CreationTimeUtc < DateTime.UtcNow.Subtract (TimeSpan.FromDays (30)));
 
108
 
 
109
                        foreach (var v in files)
 
110
                                v.Delete ();
 
111
                }
 
112
                
 
113
                static void RedirectOutputToLogFile ()
 
114
                {
 
115
                        FilePath logDir = UserProfile.Current.LogDir;
 
116
                        if (!Directory.Exists (logDir))
 
117
                                Directory.CreateDirectory (logDir);
 
118
                
 
119
                        try {
 
120
                                if (Platform.IsWindows) {
 
121
                                        //TODO: redirect the file descriptors on Windows, just plugging in a textwriter won't get everything
 
122
                                        RedirectOutputToFileWindows (logDir);
 
123
                                } else {
 
124
                                        RedirectOutputToFileUnix (logDir);
 
125
                                }
 
126
                        } catch {
 
127
                        }
 
128
                }
 
129
 
 
130
                static IEnumerable<string> GetGenericLogFiles (FilePath logDirectory)
 
131
                {
 
132
                        // Look for MonoDevelop.log and also MonoDevelop-XXX.log and move them to MonoDevelop.{timestamp}.log files
 
133
                        // as we cannot symlink on windows and we want 'MonoDevelop.log' to be the newest log file
 
134
                        string additonalGenericLogs = Path.GetFileNameWithoutExtension (GenericLogFile) + "-";
 
135
                        return Directory.GetFiles (logDirectory)
 
136
                                .Where (f => f == GenericLogFile || f.StartsWith (additonalGenericLogs))
 
137
                                .OrderBy (f => f);
 
138
                }
 
139
 
 
140
                static void RedirectOutputToFileWindows (FilePath logDirectory)
 
141
                {
 
142
                        // First try to move any generic MonoDevelop.log files to a timestamped filename
 
143
                        foreach (var path in GetGenericLogFiles (logDirectory)) {
 
144
                                try {
 
145
                                        var creationTime = File.GetCreationTime (path);
 
146
                                        var destination = logDirectory.Combine (FormattedUniqueFileName (creationTime));
 
147
                                        File.Copy (path, destination, true);
 
148
                                        File.Delete (path);
 
149
                                } catch {}
 
150
                        }
 
151
 
 
152
                        // Find the first free filename, try MonoDevelop.log first and then MonoDevelop-{0}.log
 
153
                        int count = 0;
 
154
                        var newLogFileName = GenericLogFile;
 
155
                        var existingFiles = GetGenericLogFiles (logDirectory).Select (f => Path.GetFileName (f)).ToList ();
 
156
                        while (existingFiles.Contains (newLogFileName))
 
157
                                newLogFileName = FormattedGenericLogFile (count ++);
 
158
 
 
159
                        var logFile = new StreamWriter (logDirectory.Combine (newLogFileName));
 
160
                        logFile.AutoFlush = true;
 
161
                        Console.SetOut (logFile);
 
162
                        Console.SetError (logFile);
 
163
                }
 
164
                
 
165
                static void RedirectOutputToFileUnix (FilePath logDirectory)
 
166
                {
 
167
                        const int STDOUT_FILENO = 1;
 
168
                        const int STDERR_FILENO = 2;
 
169
                        
 
170
                        Mono.Unix.Native.OpenFlags flags = Mono.Unix.Native.OpenFlags.O_WRONLY
 
171
                                | Mono.Unix.Native.OpenFlags.O_CREAT | Mono.Unix.Native.OpenFlags.O_TRUNC;
 
172
                        var mode = Mono.Unix.Native.FilePermissions.S_IFREG
 
173
                                | Mono.Unix.Native.FilePermissions.S_IRUSR | Mono.Unix.Native.FilePermissions.S_IWUSR
 
174
                                | Mono.Unix.Native.FilePermissions.S_IRGRP | Mono.Unix.Native.FilePermissions.S_IWGRP;
 
175
                        
 
176
                        var file = logDirectory.Combine (FormattedUniqueFileName (DateTime.Now));
 
177
                        int fd = Mono.Unix.Native.Syscall.open (file, flags, mode);
 
178
                        if (fd < 0)
 
179
                                //error
 
180
                                return;
 
181
                        try {
 
182
                                int res = Mono.Unix.Native.Syscall.dup2 (fd, STDOUT_FILENO);
 
183
                                if (res < 0)
 
184
                                        //error
 
185
                                        return;
 
186
                                
 
187
                                res = Mono.Unix.Native.Syscall.dup2 (fd, STDERR_FILENO);
 
188
                                if (res < 0)
 
189
                                        //error
 
190
                                        return;
 
191
 
 
192
                                var genericLog = logDirectory.Combine (GenericLogFile);
 
193
                                File.Delete (genericLog);
 
194
                                Mono.Unix.Native.Syscall.symlink (file, genericLog);
 
195
                        } finally {
 
196
                                Mono.Unix.Native.Syscall.close (fd);
 
197
                        }
 
198
                }
74
199
                
75
200
                internal static RemoteLogger RemoteLogger {
76
201
                        get {