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.