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.