Websites auf Azure legen Diagnoseinformationen (Fehler Berichte, IIS Logs, Git Logs oder eigene Logfiles) als Text-Datei auf dem Server ab. Diese lassen sich relativ einfach via FTP auslesen. Der FTP Endpunkt für eine Website in West-Europa sollte dieser sei:
ftp://waws-prod-am2-001.ftp.azurewebsites.windows.net
Zu sehen ist die natürlich auch im Azure Management:
Programmatischer Zugriff
Um die Logs weiterzuverarbeiten kann man diese natürlich auch programmatisch herunterladen – der FTP Zugriff ist ja schon relativ lang im .NET Framework möglich. Allerdings hatte ich nie was damit zutun, sodass es für eine Premiere war ;)
Der Code stamt zum großen Teil aus diesem MSDN Forenbeitrag.
1: class Program
2: {3: static void Main(string[] args)
4: {5: const string userName = "SITENAME\\ACC";
6: const string password = "PW";
7: const string ftpPath = "ftp://waws-prod-am2-001.ftp.azurewebsites.windows.net/LogFiles/http/RawLogs/";
8: const string destinationPath = @"C:\Users\Foobar\Buzz\Demo";
9: 10: 11: string[] files = GetFileListFromFtp(ftpPath, userName, password);
12: foreach (string file in files)
13: {14: Console.WriteLine("Download File {0} from FTP.", file);
15: DownloadSingleFileFromFtp(ftpPath, file, destinationPath, userName, password); 16: } 17: 18: Console.WriteLine("And done...");
19: 20: Console.ReadLine(); 21: } 22: 23: 24: public static string[] GetFileListFromFtp(string path, string userName, string password)
25: {26: var result = new StringBuilder();
27: WebResponse response = null;
28: StreamReader reader = null;
29: try
30: {31: var reqFTP = (FtpWebRequest)WebRequest.Create(new Uri(path));
32: reqFTP.UseBinary = true;
33: reqFTP.Credentials = new NetworkCredential(userName, password);
34: reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;35: reqFTP.Proxy = null;
36: reqFTP.KeepAlive = false;
37: reqFTP.UsePassive = false;
38: response = reqFTP.GetResponse();39: reader = new StreamReader(response.GetResponseStream());
40: string line = reader.ReadLine();
41: while (line != null)
42: { 43: result.Append(line);44: result.Append("\n");
45: line = reader.ReadLine(); 46: }47: // to remove the trailing '\n'
48: result.Remove(result.ToString().LastIndexOf('\n'), 1);
49: return result.ToString().Split('\n');
50: }51: catch (Exception)
52: {53: if (reader != null)
54: { 55: reader.Close(); 56: }57: if (response != null)
58: { 59: response.Close(); 60: } 61: 62: throw;
63: } 64: } 65: 66: public static void DownloadSingleFileFromFtp(string sourcePath, string file, string destinationPath, string userName, string password)
67: {68: var reqFTP = (FtpWebRequest)WebRequest.Create(new Uri(sourcePath + file));
69: reqFTP.Credentials = new NetworkCredential(userName, password);
70: reqFTP.KeepAlive = false;
71: reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;72: reqFTP.UseBinary = true;
73: reqFTP.Proxy = null;
74: reqFTP.UsePassive = false;
75: var response = (FtpWebResponse)reqFTP.GetResponse(); 76: var responseStream = response.GetResponseStream();77: var writeStream = new FileStream(Path.Combine(destinationPath, file), FileMode.Create);
78: const int length = 2048;
79: var buffer = new Byte[length];
80: if (responseStream != null)
81: {82: int bytesRead = responseStream.Read(buffer, 0, length);
83: while (bytesRead > 0)
84: { 85: writeStream.Write(buffer, 0, bytesRead); 86: bytesRead = responseStream.Read(buffer, 0, length); 87: } 88: } 89: writeStream.Close(); 90: response.Close(); 91: 92: } 93: }Der Username und das Passwort kann im Azure Website Management Portal gesetzt werden. Dies ist auch der User, der für ein evtl. Git-Deployment berechtigt ist.
Ergebnis:
Die Dateien in dem Ordner werden alle heruntergeladen.
Der Code ist natürlich auch auf GitHub zu finden.