Skip to content

Commit

Permalink
Merge pull request Azure-App-Service#46 from Azure-App-Service/user/s…
Browse files Browse the repository at this point in the history
…anmeht/LogStreamVFS

Added VFS path to log stream, fixed line break problem with logstream
  • Loading branch information
JennyLawrance authored Jun 4, 2019
2 parents 384a56e + b89e1cf commit f65680d
Showing 1 changed file with 52 additions and 12 deletions.
64 changes: 52 additions & 12 deletions Kudu.Services/Diagnostics/LogStreamManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -45,6 +44,7 @@ public class LogStreamManager
private DateTime _lastTraceTime;
private DateTime _startTime;
private TimeSpan _timeout;
private Stopwatch stopwatch;

private const string volatileLogsPath = "/appsvctmp/volatile/logs/runtime";

Expand Down Expand Up @@ -78,7 +78,7 @@ public async Task ProcessRequest(HttpContext context)
_lastTraceTime = _startTime;

DisableResponseBuffering(context);
var stopwatch = Stopwatch.StartNew();
stopwatch = Stopwatch.StartNew();

// CORE TODO Shutdown detector registration

Expand Down Expand Up @@ -126,22 +126,39 @@ public async Task ProcessRequest(HttpContext context)

if (_logFiles != null)
{
NotifyClientWithLineBreak("Starting Log Tail -n 10 of exisitng logs ----", context);

foreach (string log in _logFiles.Keys)
{
var reader = new StreamReader(log, Encoding.ASCII);

var vfsPath = GetFileVfsPath(log);

var printLine = log + " " + (!string.IsNullOrEmpty(vfsPath) ? " (" + vfsPath + ")" : "");

NotifyClientWithLineBreak(String.Format(
CultureInfo.CurrentCulture,
printLine,
DateTime.UtcNow.ToString("s"),
System.Environment.NewLine),context);

foreach (string logLine in Tail(reader, 10))
{
await context.Response.WriteAsync(
string.Format(logLine,System.Environment.NewLine));
await context.Response.WriteAsync(logLine);
await context.Response.WriteAsync(System.Environment.NewLine);
}
await context.Response.WriteAsync(System.Environment.NewLine);
}
NotifyClientWithLineBreak("Ending Log Tail of exisitng logs ---", context);
}
else
{
_tracer.TraceError("LogStream: No pervious logfiles");
Console.WriteLine("LogStream: No pervious logfiles");
}

NotifyClientWithLineBreak("Starting Live Log Stream ---", context);

// CORE TODO diagnostics setting for enabling app logging

while (!context.RequestAborted.IsCancellationRequested)
Expand Down Expand Up @@ -387,14 +404,6 @@ private void OnHeartbeat(object state)
{
TerminateClient(String.Format(CultureInfo.CurrentCulture, Resources.LogStream_Timeout, DateTime.UtcNow.ToString("s"), (int)ts.TotalMinutes, System.Environment.NewLine), context);
}
else
{
ts = DateTime.UtcNow.Subtract(_lastTraceTime);
if (ts >= HeartbeatInterval)
{
NotifyClient(String.Format(CultureInfo.CurrentCulture, Resources.LogStream_Heartbeat, DateTime.UtcNow.ToString("s"), (int)ts.TotalMinutes, System.Environment.NewLine),context);
}
}
}
catch (Exception ex)
{
Expand Down Expand Up @@ -424,12 +433,32 @@ private void OnChanged(object sender, FileSystemEventArgs e, HttpContext context
if (lines.Count() > 0)
{
_lastTraceTime = DateTime.UtcNow;
stopwatch = Stopwatch.StartNew();
NotifyClient(lines,context);
}
}
}

private async void NotifyClientWithLineBreak(string line, HttpContext context)
{
if (!context.RequestAborted.IsCancellationRequested)
{
try
{
await context.Response.WriteAsync(System.Environment.NewLine);
await context.Response.WriteAsync(line);
await context.Response.WriteAsync(System.Environment.NewLine);
}
catch (Exception)
{
_tracer.TraceError("Error notifying client");
}
}
}

/*
* CORE TODO : Rest API to watch a particular file by LogStream
* /
private string ParseRequest(HttpContext context)
{
_filter = context.Request.QueryString[FilterQueryKey];
Expand Down Expand Up @@ -484,6 +513,7 @@ private async void NotifyClient(IEnumerable<string> lines, HttpContext context)
{
try
{
await context.Response.WriteAsync(System.Environment.NewLine);
foreach (var line in lines)
{
await context.Response.WriteAsync(line);
Expand Down Expand Up @@ -664,6 +694,16 @@ public void Dispose()
GC.SuppressFinalize(this);
}

private string GetFileVfsPath(string filePath)
{
string relativePath = filePath.IndexOf("LogFiles") > 0 ? filePath.Substring(filePath.IndexOf("LogFiles")).Replace("\\", "/") : "";
string fileName = Uri.EscapeDataString(relativePath.Substring(relativePath.LastIndexOf("/")+1));
string encodedUrl = relativePath.Substring(0, relativePath.LastIndexOf("/")+1) + fileName;

return filePath.Contains("LogFiles") ?
_environment.AppBaseUrlPrefix + "/api/vfs/" + encodedUrl : "";
}

protected virtual void Dispose(bool disposing)
{
if (disposing)
Expand Down

0 comments on commit f65680d

Please sign in to comment.