Extend 'slow' request logging to other server outbound requests (forms, rest, async rest) as well as the existing logging on outbound OSD requests.
Also prints out the first 100 chars of any slow request data since this can contain useful info (such as agent ID).0.7.4.1
parent
c221eaf0b0
commit
c9faf0df74
|
@ -53,19 +53,36 @@ namespace OpenSim.Framework
|
||||||
LogManager.GetLogger(
|
LogManager.GetLogger(
|
||||||
MethodBase.GetCurrentMethod().DeclaringType);
|
MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private static int m_requestNumber = 0;
|
/// <summary>
|
||||||
|
/// Request number for diagnostic purposes.
|
||||||
|
/// </summary>
|
||||||
|
public static int RequestNumber = 0;
|
||||||
|
|
||||||
// this is the header field used to communicate the local request id
|
/// <summary>
|
||||||
// used for performance and debugging
|
/// this is the header field used to communicate the local request id
|
||||||
|
/// used for performance and debugging
|
||||||
|
/// </summary>
|
||||||
public const string OSHeaderRequestID = "opensim-request-id";
|
public const string OSHeaderRequestID = "opensim-request-id";
|
||||||
|
|
||||||
// number of milliseconds a call can take before it is considered
|
/// <summary>
|
||||||
// a "long" call for warning & debugging purposes
|
/// Number of milliseconds a call can take before it is considered
|
||||||
|
/// a "long" call for warning & debugging purposes
|
||||||
|
/// </summary>
|
||||||
public const int LongCallTime = 500;
|
public const int LongCallTime = 500;
|
||||||
|
|
||||||
// dictionary of end points
|
/// <summary>
|
||||||
private static Dictionary<string,object> m_endpointSerializer = new Dictionary<string,object>();
|
/// The maximum length of any data logged because of a long request time.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This is to truncate any really large post data, such as an asset. In theory, the first section should
|
||||||
|
/// give us useful information about the call (which agent it relates to if applicable, etc.).
|
||||||
|
/// </remarks>
|
||||||
|
public const int MaxRequestDiagLength = 100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dictionary of end points
|
||||||
|
/// </summary>
|
||||||
|
private static Dictionary<string,object> m_endpointSerializer = new Dictionary<string,object>();
|
||||||
|
|
||||||
private static object EndPointLock(string url)
|
private static object EndPointLock(string url)
|
||||||
{
|
{
|
||||||
|
@ -128,12 +145,13 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
|
private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
|
||||||
{
|
{
|
||||||
int reqnum = m_requestNumber++;
|
int reqnum = RequestNumber++;
|
||||||
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
|
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
|
||||||
|
|
||||||
string errorMessage = "unknown error";
|
string errorMessage = "unknown error";
|
||||||
int tickstart = Util.EnvironmentTickCount();
|
int tickstart = Util.EnvironmentTickCount();
|
||||||
int tickdata = 0;
|
int tickdata = 0;
|
||||||
|
string strBuffer = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -148,7 +166,7 @@ namespace OpenSim.Framework
|
||||||
// If there is some input, write it into the request
|
// If there is some input, write it into the request
|
||||||
if (data != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
string strBuffer = OSDParser.SerializeJsonString(data);
|
strBuffer = OSDParser.SerializeJsonString(data);
|
||||||
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
|
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
|
||||||
|
|
||||||
if (compressed)
|
if (compressed)
|
||||||
|
@ -208,11 +226,18 @@ namespace OpenSim.Framework
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
// This just dumps a warning for any operation that takes more than 100 ms
|
|
||||||
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
if (tickdiff > LongCallTime)
|
if (tickdiff > LongCallTime)
|
||||||
m_log.DebugFormat("[WEB UTIL]: osd request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing",
|
m_log.InfoFormat(
|
||||||
reqnum,url,method,tickdiff,tickdata);
|
"[OSD REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||||
|
reqnum,
|
||||||
|
method,
|
||||||
|
url,
|
||||||
|
tickdiff,
|
||||||
|
tickdata,
|
||||||
|
strBuffer != null
|
||||||
|
? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer)
|
||||||
|
: "");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
|
@ -290,17 +315,17 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
private static OSDMap ServiceFormRequestWorker(string url, NameValueCollection data, int timeout)
|
private static OSDMap ServiceFormRequestWorker(string url, NameValueCollection data, int timeout)
|
||||||
{
|
{
|
||||||
int reqnum = m_requestNumber++;
|
int reqnum = RequestNumber++;
|
||||||
string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
|
string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
|
||||||
// m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method);
|
// m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method);
|
||||||
|
|
||||||
string errorMessage = "unknown error";
|
string errorMessage = "unknown error";
|
||||||
int tickstart = Util.EnvironmentTickCount();
|
int tickstart = Util.EnvironmentTickCount();
|
||||||
int tickdata = 0;
|
int tickdata = 0;
|
||||||
|
string queryString = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
|
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
|
||||||
request.Method = "POST";
|
request.Method = "POST";
|
||||||
request.Timeout = timeout;
|
request.Timeout = timeout;
|
||||||
|
@ -311,7 +336,7 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
if (data != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
string queryString = BuildQueryString(data);
|
queryString = BuildQueryString(data);
|
||||||
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString);
|
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString);
|
||||||
|
|
||||||
request.ContentLength = buffer.Length;
|
request.ContentLength = buffer.Length;
|
||||||
|
@ -354,11 +379,19 @@ namespace OpenSim.Framework
|
||||||
{
|
{
|
||||||
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
if (tickdiff > LongCallTime)
|
if (tickdiff > LongCallTime)
|
||||||
m_log.InfoFormat("[WEB UTIL]: form request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing",
|
m_log.InfoFormat(
|
||||||
reqnum,url,method,tickdiff,tickdata);
|
"[SERVICE FORM]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||||
|
reqnum,
|
||||||
|
method,
|
||||||
|
url,
|
||||||
|
tickdiff,
|
||||||
|
tickdata,
|
||||||
|
queryString != null
|
||||||
|
? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString
|
||||||
|
: "");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.WarnFormat("[WEB UTIL]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage);
|
m_log.WarnFormat("[SERVICE FORM]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage);
|
||||||
|
|
||||||
return ErrorResponseMap(errorMessage);
|
return ErrorResponseMap(errorMessage);
|
||||||
}
|
}
|
||||||
|
@ -639,8 +672,6 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
return new string[0];
|
return new string[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AsynchronousRestObjectRequester
|
public static class AsynchronousRestObjectRequester
|
||||||
|
@ -663,6 +694,12 @@ namespace OpenSim.Framework
|
||||||
public static void MakeRequest<TRequest, TResponse>(string verb,
|
public static void MakeRequest<TRequest, TResponse>(string verb,
|
||||||
string requestUrl, TRequest obj, Action<TResponse> action)
|
string requestUrl, TRequest obj, Action<TResponse> action)
|
||||||
{
|
{
|
||||||
|
int reqnum = WebUtil.RequestNumber++;
|
||||||
|
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
|
||||||
|
|
||||||
|
int tickstart = Util.EnvironmentTickCount();
|
||||||
|
int tickdata = 0;
|
||||||
|
|
||||||
// m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl);
|
// m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl);
|
||||||
|
|
||||||
Type type = typeof(TRequest);
|
Type type = typeof(TRequest);
|
||||||
|
@ -673,12 +710,13 @@ namespace OpenSim.Framework
|
||||||
XmlSerializer deserializer = new XmlSerializer(typeof(TResponse));
|
XmlSerializer deserializer = new XmlSerializer(typeof(TResponse));
|
||||||
|
|
||||||
request.Method = verb;
|
request.Method = verb;
|
||||||
|
MemoryStream buffer = null;
|
||||||
|
|
||||||
if (verb == "POST")
|
if (verb == "POST")
|
||||||
{
|
{
|
||||||
request.ContentType = "text/xml";
|
request.ContentType = "text/xml";
|
||||||
|
|
||||||
MemoryStream buffer = new MemoryStream();
|
buffer = new MemoryStream();
|
||||||
|
|
||||||
XmlWriterSettings settings = new XmlWriterSettings();
|
XmlWriterSettings settings = new XmlWriterSettings();
|
||||||
settings.Encoding = Encoding.UTF8;
|
settings.Encoding = Encoding.UTF8;
|
||||||
|
@ -700,6 +738,9 @@ namespace OpenSim.Framework
|
||||||
requestStream.Write(buffer.ToArray(), 0, length);
|
requestStream.Write(buffer.ToArray(), 0, length);
|
||||||
requestStream.Close();
|
requestStream.Close();
|
||||||
|
|
||||||
|
// capture how much time was spent writing
|
||||||
|
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
|
|
||||||
request.BeginGetResponse(delegate(IAsyncResult ar)
|
request.BeginGetResponse(delegate(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
response = request.EndGetResponse(ar);
|
response = request.EndGetResponse(ar);
|
||||||
|
@ -725,11 +766,9 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
}, null);
|
}, null);
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
request.BeginGetResponse(delegate(IAsyncResult res2)
|
request.BeginGetResponse(delegate(IAsyncResult res2)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -800,13 +839,35 @@ namespace OpenSim.Framework
|
||||||
|
|
||||||
}, null);
|
}, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
|
if (tickdiff > WebUtil.LongCallTime)
|
||||||
|
{
|
||||||
|
string originalRequest = null;
|
||||||
|
|
||||||
|
if (buffer != null)
|
||||||
|
{
|
||||||
|
originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
|
||||||
|
|
||||||
|
if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
|
||||||
|
originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.InfoFormat(
|
||||||
|
"[ASYNC REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||||
|
reqnum,
|
||||||
|
verb,
|
||||||
|
requestUrl,
|
||||||
|
tickdiff,
|
||||||
|
tickdata,
|
||||||
|
originalRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SynchronousRestFormsRequester
|
public static class SynchronousRestFormsRequester
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log =
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
LogManager.GetLogger(
|
|
||||||
MethodBase.GetCurrentMethod().DeclaringType);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Perform a synchronous REST request.
|
/// Perform a synchronous REST request.
|
||||||
|
@ -820,6 +881,12 @@ namespace OpenSim.Framework
|
||||||
/// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
|
/// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
|
||||||
public static string MakeRequest(string verb, string requestUrl, string obj)
|
public static string MakeRequest(string verb, string requestUrl, string obj)
|
||||||
{
|
{
|
||||||
|
int reqnum = WebUtil.RequestNumber++;
|
||||||
|
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
|
||||||
|
|
||||||
|
int tickstart = Util.EnvironmentTickCount();
|
||||||
|
int tickdata = 0;
|
||||||
|
|
||||||
WebRequest request = WebRequest.Create(requestUrl);
|
WebRequest request = WebRequest.Create(requestUrl);
|
||||||
request.Method = verb;
|
request.Method = verb;
|
||||||
string respstring = String.Empty;
|
string respstring = String.Empty;
|
||||||
|
@ -855,6 +922,9 @@ namespace OpenSim.Framework
|
||||||
{
|
{
|
||||||
if (requestStream != null)
|
if (requestStream != null)
|
||||||
requestStream.Close();
|
requestStream.Close();
|
||||||
|
|
||||||
|
// capture how much time was spent writing
|
||||||
|
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,6 +963,18 @@ namespace OpenSim.Framework
|
||||||
m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving {0} {1}", verb, requestUrl);
|
m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving {0} {1}", verb, requestUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
|
if (tickdiff > WebUtil.LongCallTime)
|
||||||
|
m_log.InfoFormat(
|
||||||
|
"[FORMS]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||||
|
reqnum,
|
||||||
|
verb,
|
||||||
|
requestUrl,
|
||||||
|
tickdiff,
|
||||||
|
tickdata,
|
||||||
|
obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
|
||||||
|
|
||||||
return respstring;
|
return respstring;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -915,17 +997,24 @@ namespace OpenSim.Framework
|
||||||
/// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
|
/// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
|
||||||
public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj)
|
public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj)
|
||||||
{
|
{
|
||||||
|
int reqnum = WebUtil.RequestNumber++;
|
||||||
|
// m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
|
||||||
|
|
||||||
|
int tickstart = Util.EnvironmentTickCount();
|
||||||
|
int tickdata = 0;
|
||||||
|
|
||||||
Type type = typeof(TRequest);
|
Type type = typeof(TRequest);
|
||||||
TResponse deserial = default(TResponse);
|
TResponse deserial = default(TResponse);
|
||||||
|
|
||||||
WebRequest request = WebRequest.Create(requestUrl);
|
WebRequest request = WebRequest.Create(requestUrl);
|
||||||
request.Method = verb;
|
request.Method = verb;
|
||||||
|
MemoryStream buffer = null;
|
||||||
|
|
||||||
if ((verb == "POST") || (verb == "PUT"))
|
if ((verb == "POST") || (verb == "PUT"))
|
||||||
{
|
{
|
||||||
request.ContentType = "text/xml";
|
request.ContentType = "text/xml";
|
||||||
|
|
||||||
MemoryStream buffer = new MemoryStream();
|
buffer = new MemoryStream();
|
||||||
|
|
||||||
XmlWriterSettings settings = new XmlWriterSettings();
|
XmlWriterSettings settings = new XmlWriterSettings();
|
||||||
settings.Encoding = Encoding.UTF8;
|
settings.Encoding = Encoding.UTF8;
|
||||||
|
@ -958,6 +1047,9 @@ namespace OpenSim.Framework
|
||||||
{
|
{
|
||||||
if (requestStream != null)
|
if (requestStream != null)
|
||||||
requestStream.Close();
|
requestStream.Close();
|
||||||
|
|
||||||
|
// capture how much time was spent writing
|
||||||
|
tickdata = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1005,6 +1097,29 @@ namespace OpenSim.Framework
|
||||||
verb, requestUrl, e.Message, e.StackTrace);
|
verb, requestUrl, e.Message, e.StackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
|
||||||
|
if (tickdiff > WebUtil.LongCallTime)
|
||||||
|
{
|
||||||
|
string originalRequest = null;
|
||||||
|
|
||||||
|
if (buffer != null)
|
||||||
|
{
|
||||||
|
originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
|
||||||
|
|
||||||
|
if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
|
||||||
|
originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_log.InfoFormat(
|
||||||
|
"[SynchronousRestObjectRequester]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
|
||||||
|
reqnum,
|
||||||
|
verb,
|
||||||
|
requestUrl,
|
||||||
|
tickdiff,
|
||||||
|
tickdata,
|
||||||
|
originalRequest);
|
||||||
|
}
|
||||||
|
|
||||||
return deserial;
|
return deserial;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue