aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/WebUtil.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Framework/WebUtil.cs277
1 files changed, 196 insertions, 81 deletions
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index 11967c9..6a40cd5 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -53,19 +53,36 @@ namespace OpenSim.Framework
53 LogManager.GetLogger( 53 LogManager.GetLogger(
54 MethodBase.GetCurrentMethod().DeclaringType); 54 MethodBase.GetCurrentMethod().DeclaringType);
55 55
56 private static int m_requestNumber = 0; 56 /// <summary>
57 /// Request number for diagnostic purposes.
58 /// </summary>
59 public static int RequestNumber = 0;
57 60
58 // this is the header field used to communicate the local request id 61 /// <summary>
59 // used for performance and debugging 62 /// this is the header field used to communicate the local request id
63 /// used for performance and debugging
64 /// </summary>
60 public const string OSHeaderRequestID = "opensim-request-id"; 65 public const string OSHeaderRequestID = "opensim-request-id";
61 66
62 // number of milliseconds a call can take before it is considered 67 /// <summary>
63 // a "long" call for warning & debugging purposes 68 /// Number of milliseconds a call can take before it is considered
64 public const int LongCallTime = 500; 69 /// a "long" call for warning & debugging purposes
70 /// </summary>
71 public const int LongCallTime = 3000;
72
73 /// <summary>
74 /// The maximum length of any data logged because of a long request time.
75 /// </summary>
76 /// <remarks>
77 /// This is to truncate any really large post data, such as an asset. In theory, the first section should
78 /// give us useful information about the call (which agent it relates to if applicable, etc.).
79 /// </remarks>
80 public const int MaxRequestDiagLength = 100;
65 81
66 // dictionary of end points 82 /// <summary>
83 /// Dictionary of end points
84 /// </summary>
67 private static Dictionary<string,object> m_endpointSerializer = new Dictionary<string,object>(); 85 private static Dictionary<string,object> m_endpointSerializer = new Dictionary<string,object>();
68
69 86
70 private static object EndPointLock(string url) 87 private static object EndPointLock(string url)
71 { 88 {
@@ -128,12 +145,13 @@ namespace OpenSim.Framework
128 145
129 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed) 146 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
130 { 147 {
131 int reqnum = m_requestNumber++; 148 int reqnum = RequestNumber++;
132 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); 149 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
133 150
134 string errorMessage = "unknown error"; 151 string errorMessage = "unknown error";
135 int tickstart = Util.EnvironmentTickCount(); 152 int tickstart = Util.EnvironmentTickCount();
136 int tickdata = 0; 153 int tickdata = 0;
154 string strBuffer = null;
137 155
138 try 156 try
139 { 157 {
@@ -148,7 +166,7 @@ namespace OpenSim.Framework
148 // If there is some input, write it into the request 166 // If there is some input, write it into the request
149 if (data != null) 167 if (data != null)
150 { 168 {
151 string strBuffer = OSDParser.SerializeJsonString(data); 169 strBuffer = OSDParser.SerializeJsonString(data);
152 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer); 170 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(strBuffer);
153 171
154 if (compressed) 172 if (compressed)
@@ -209,11 +227,18 @@ namespace OpenSim.Framework
209 } 227 }
210 finally 228 finally
211 { 229 {
212 // This just dumps a warning for any operation that takes more than 100 ms
213 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 230 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
214 if (tickdiff > LongCallTime) 231 if (tickdiff > LongCallTime)
215 m_log.DebugFormat("[WEB UTIL]: osd request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing", 232 m_log.InfoFormat(
216 reqnum,url,method,tickdiff,tickdata); 233 "[OSD REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
234 reqnum,
235 method,
236 url,
237 tickdiff,
238 tickdata,
239 strBuffer != null
240 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer)
241 : "");
217 } 242 }
218 243
219 m_log.DebugFormat( 244 m_log.DebugFormat(
@@ -291,17 +316,17 @@ namespace OpenSim.Framework
291 316
292 private static OSDMap ServiceFormRequestWorker(string url, NameValueCollection data, int timeout) 317 private static OSDMap ServiceFormRequestWorker(string url, NameValueCollection data, int timeout)
293 { 318 {
294 int reqnum = m_requestNumber++; 319 int reqnum = RequestNumber++;
295 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown"; 320 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
296 // m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method); 321 // m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method);
297 322
298 string errorMessage = "unknown error"; 323 string errorMessage = "unknown error";
299 int tickstart = Util.EnvironmentTickCount(); 324 int tickstart = Util.EnvironmentTickCount();
300 int tickdata = 0; 325 int tickdata = 0;
326 string queryString = null;
301 327
302 try 328 try
303 { 329 {
304
305 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); 330 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
306 request.Method = "POST"; 331 request.Method = "POST";
307 request.Timeout = timeout; 332 request.Timeout = timeout;
@@ -312,7 +337,7 @@ namespace OpenSim.Framework
312 337
313 if (data != null) 338 if (data != null)
314 { 339 {
315 string queryString = BuildQueryString(data); 340 queryString = BuildQueryString(data);
316 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString); 341 byte[] buffer = System.Text.Encoding.UTF8.GetBytes(queryString);
317 342
318 request.ContentLength = buffer.Length; 343 request.ContentLength = buffer.Length;
@@ -355,11 +380,19 @@ namespace OpenSim.Framework
355 { 380 {
356 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 381 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
357 if (tickdiff > LongCallTime) 382 if (tickdiff > LongCallTime)
358 m_log.InfoFormat("[WEB UTIL]: form request <{0}> (URI:{1}, METHOD:{2}) took {3}ms overall, {4}ms writing", 383 m_log.InfoFormat(
359 reqnum,url,method,tickdiff,tickdata); 384 "[SERVICE FORM]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
385 reqnum,
386 method,
387 url,
388 tickdiff,
389 tickdata,
390 queryString != null
391 ? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString
392 : "");
360 } 393 }
361 394
362 m_log.WarnFormat("[WEB UTIL]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage); 395 m_log.WarnFormat("[SERVICE FORM]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage);
363 396
364 return ErrorResponseMap(errorMessage); 397 return ErrorResponseMap(errorMessage);
365 } 398 }
@@ -640,8 +673,6 @@ namespace OpenSim.Framework
640 673
641 return new string[0]; 674 return new string[0];
642 } 675 }
643
644
645 } 676 }
646 677
647 public static class AsynchronousRestObjectRequester 678 public static class AsynchronousRestObjectRequester
@@ -664,6 +695,12 @@ namespace OpenSim.Framework
664 public static void MakeRequest<TRequest, TResponse>(string verb, 695 public static void MakeRequest<TRequest, TResponse>(string verb,
665 string requestUrl, TRequest obj, Action<TResponse> action) 696 string requestUrl, TRequest obj, Action<TResponse> action)
666 { 697 {
698 int reqnum = WebUtil.RequestNumber++;
699 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
700
701 int tickstart = Util.EnvironmentTickCount();
702 int tickdata = 0;
703
667 // m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl); 704 // m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl);
668 705
669 Type type = typeof(TRequest); 706 Type type = typeof(TRequest);
@@ -674,12 +711,13 @@ namespace OpenSim.Framework
674 XmlSerializer deserializer = new XmlSerializer(typeof(TResponse)); 711 XmlSerializer deserializer = new XmlSerializer(typeof(TResponse));
675 712
676 request.Method = verb; 713 request.Method = verb;
714 MemoryStream buffer = null;
677 715
678 if (verb == "POST") 716 if (verb == "POST")
679 { 717 {
680 request.ContentType = "text/xml"; 718 request.ContentType = "text/xml";
681 719
682 MemoryStream buffer = new MemoryStream(); 720 buffer = new MemoryStream();
683 721
684 XmlWriterSettings settings = new XmlWriterSettings(); 722 XmlWriterSettings settings = new XmlWriterSettings();
685 settings.Encoding = Encoding.UTF8; 723 settings.Encoding = Encoding.UTF8;
@@ -701,6 +739,9 @@ namespace OpenSim.Framework
701 requestStream.Write(buffer.ToArray(), 0, length); 739 requestStream.Write(buffer.ToArray(), 0, length);
702 requestStream.Close(); 740 requestStream.Close();
703 741
742 // capture how much time was spent writing
743 tickdata = Util.EnvironmentTickCountSubtract(tickstart);
744
704 request.BeginGetResponse(delegate(IAsyncResult ar) 745 request.BeginGetResponse(delegate(IAsyncResult ar)
705 { 746 {
706 response = request.EndGetResponse(ar); 747 response = request.EndGetResponse(ar);
@@ -726,88 +767,108 @@ namespace OpenSim.Framework
726 767
727 }, null); 768 }, null);
728 }, null); 769 }, null);
729
730
731 return;
732 } 770 }
733 771 else
734 request.BeginGetResponse(delegate(IAsyncResult res2)
735 { 772 {
736 try 773 request.BeginGetResponse(delegate(IAsyncResult res2)
737 { 774 {
738 // If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't
739 // documented in MSDN
740 response = request.EndGetResponse(res2);
741
742 Stream respStream = null;
743 try 775 try
744 { 776 {
745 respStream = response.GetResponseStream(); 777 // If the server returns a 404, this appears to trigger a System.Net.WebException even though that isn't
746 deserial = (TResponse)deserializer.Deserialize(respStream); 778 // documented in MSDN
747 } 779 response = request.EndGetResponse(res2);
748 catch (System.InvalidOperationException) 780
749 { 781 Stream respStream = null;
750 } 782 try
751 finally 783 {
752 { 784 respStream = response.GetResponseStream();
753 respStream.Close(); 785 deserial = (TResponse)deserializer.Deserialize(respStream);
754 response.Close(); 786 }
787 catch (System.InvalidOperationException)
788 {
789 }
790 finally
791 {
792 respStream.Close();
793 response.Close();
794 }
755 } 795 }
756 } 796 catch (WebException e)
757 catch (WebException e)
758 {
759 if (e.Status == WebExceptionStatus.ProtocolError)
760 { 797 {
761 if (e.Response is HttpWebResponse) 798 if (e.Status == WebExceptionStatus.ProtocolError)
762 { 799 {
763 HttpWebResponse httpResponse = (HttpWebResponse)e.Response; 800 if (e.Response is HttpWebResponse)
764
765 if (httpResponse.StatusCode != HttpStatusCode.NotFound)
766 { 801 {
767 // We don't appear to be handling any other status codes, so log these feailures to that 802 HttpWebResponse httpResponse = (HttpWebResponse)e.Response;
768 // people don't spend unnecessary hours hunting phantom bugs. 803
769 m_log.DebugFormat( 804 if (httpResponse.StatusCode != HttpStatusCode.NotFound)
770 "[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}", 805 {
771 verb, requestUrl, httpResponse.StatusCode); 806 // We don't appear to be handling any other status codes, so log these feailures to that
807 // people don't spend unnecessary hours hunting phantom bugs.
808 m_log.DebugFormat(
809 "[ASYNC REQUEST]: Request {0} {1} failed with unexpected status code {2}",
810 verb, requestUrl, httpResponse.StatusCode);
811 }
772 } 812 }
773 } 813 }
814 else
815 {
816 m_log.ErrorFormat(
817 "[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}",
818 verb, requestUrl, e.Status, e.Message);
819 }
774 } 820 }
775 else 821 catch (Exception e)
776 { 822 {
777 m_log.ErrorFormat( 823 m_log.ErrorFormat(
778 "[ASYNC REQUEST]: Request {0} {1} failed with status {2} and message {3}", 824 "[ASYNC REQUEST]: Request {0} {1} failed with exception {2}{3}",
779 verb, requestUrl, e.Status, e.Message); 825 verb, requestUrl, e.Message, e.StackTrace);
780 } 826 }
781 } 827
782 catch (Exception e) 828 // m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString());
783 { 829
784 m_log.ErrorFormat( 830 try
785 "[ASYNC REQUEST]: Request {0} {1} failed with exception {2}{3}", 831 {
786 verb, requestUrl, e.Message, e.StackTrace); 832 action(deserial);
787 } 833 }
834 catch (Exception e)
835 {
836 m_log.ErrorFormat(
837 "[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}{3}",
838 verb, requestUrl, e.Message, e.StackTrace);
839 }
840
841 }, null);
842 }
788 843
789 // m_log.DebugFormat("[ASYNC REQUEST]: Received {0}", deserial.ToString()); 844 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
845 if (tickdiff > WebUtil.LongCallTime)
846 {
847 string originalRequest = null;
790 848
791 try 849 if (buffer != null)
792 {
793 action(deserial);
794 }
795 catch (Exception e)
796 { 850 {
797 m_log.ErrorFormat( 851 originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
798 "[ASYNC REQUEST]: Request {0} {1} callback failed with exception {2}{3}", 852
799 verb, requestUrl, e.Message, e.StackTrace); 853 if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
854 originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
800 } 855 }
801 856
802 }, null); 857 m_log.InfoFormat(
858 "[ASYNC REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
859 reqnum,
860 verb,
861 requestUrl,
862 tickdiff,
863 tickdata,
864 originalRequest);
865 }
803 } 866 }
804 } 867 }
805 868
806 public static class SynchronousRestFormsRequester 869 public static class SynchronousRestFormsRequester
807 { 870 {
808 private static readonly ILog m_log = 871 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
809 LogManager.GetLogger(
810 MethodBase.GetCurrentMethod().DeclaringType);
811 872
812 /// <summary> 873 /// <summary>
813 /// Perform a synchronous REST request. 874 /// Perform a synchronous REST request.
@@ -821,6 +882,12 @@ namespace OpenSim.Framework
821 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception> 882 /// the request. You'll want to make sure you deal with this as they're not uncommon</exception>
822 public static string MakeRequest(string verb, string requestUrl, string obj) 883 public static string MakeRequest(string verb, string requestUrl, string obj)
823 { 884 {
885 int reqnum = WebUtil.RequestNumber++;
886 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
887
888 int tickstart = Util.EnvironmentTickCount();
889 int tickdata = 0;
890
824 WebRequest request = WebRequest.Create(requestUrl); 891 WebRequest request = WebRequest.Create(requestUrl);
825 request.Method = verb; 892 request.Method = verb;
826 string respstring = String.Empty; 893 string respstring = String.Empty;
@@ -856,6 +923,9 @@ namespace OpenSim.Framework
856 { 923 {
857 if (requestStream != null) 924 if (requestStream != null)
858 requestStream.Close(); 925 requestStream.Close();
926
927 // capture how much time was spent writing
928 tickdata = Util.EnvironmentTickCountSubtract(tickstart);
859 } 929 }
860 } 930 }
861 931
@@ -894,6 +964,18 @@ namespace OpenSim.Framework
894 m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving {0} {1}", verb, requestUrl); 964 m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving {0} {1}", verb, requestUrl);
895 } 965 }
896 } 966 }
967
968 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
969 if (tickdiff > WebUtil.LongCallTime)
970 m_log.InfoFormat(
971 "[FORMS]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
972 reqnum,
973 verb,
974 requestUrl,
975 tickdiff,
976 tickdata,
977 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
978
897 return respstring; 979 return respstring;
898 } 980 }
899 } 981 }
@@ -921,6 +1003,12 @@ namespace OpenSim.Framework
921 1003
922 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout) 1004 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout)
923 { 1005 {
1006 int reqnum = WebUtil.RequestNumber++;
1007 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
1008
1009 int tickstart = Util.EnvironmentTickCount();
1010 int tickdata = 0;
1011
924 Type type = typeof(TRequest); 1012 Type type = typeof(TRequest);
925 TResponse deserial = default(TResponse); 1013 TResponse deserial = default(TResponse);
926 1014
@@ -928,12 +1016,13 @@ namespace OpenSim.Framework
928 request.Method = verb; 1016 request.Method = verb;
929 if (pTimeout != 0) 1017 if (pTimeout != 0)
930 request.Timeout = pTimeout * 1000; 1018 request.Timeout = pTimeout * 1000;
1019 MemoryStream buffer = null;
931 1020
932 if ((verb == "POST") || (verb == "PUT")) 1021 if ((verb == "POST") || (verb == "PUT"))
933 { 1022 {
934 request.ContentType = "text/xml"; 1023 request.ContentType = "text/xml";
935 1024
936 MemoryStream buffer = new MemoryStream(); 1025 buffer = new MemoryStream();
937 1026
938 XmlWriterSettings settings = new XmlWriterSettings(); 1027 XmlWriterSettings settings = new XmlWriterSettings();
939 settings.Encoding = Encoding.UTF8; 1028 settings.Encoding = Encoding.UTF8;
@@ -966,6 +1055,9 @@ namespace OpenSim.Framework
966 { 1055 {
967 if (requestStream != null) 1056 if (requestStream != null)
968 requestStream.Close(); 1057 requestStream.Close();
1058
1059 // capture how much time was spent writing
1060 tickdata = Util.EnvironmentTickCountSubtract(tickstart);
969 } 1061 }
970 } 1062 }
971 1063
@@ -1013,7 +1105,30 @@ namespace OpenSim.Framework
1013 verb, requestUrl, e.Message, e.StackTrace); 1105 verb, requestUrl, e.Message, e.StackTrace);
1014 } 1106 }
1015 1107
1108 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
1109 if (tickdiff > WebUtil.LongCallTime)
1110 {
1111 string originalRequest = null;
1112
1113 if (buffer != null)
1114 {
1115 originalRequest = Encoding.UTF8.GetString(buffer.ToArray());
1116
1117 if (originalRequest.Length > WebUtil.MaxRequestDiagLength)
1118 originalRequest = originalRequest.Remove(WebUtil.MaxRequestDiagLength);
1119 }
1120
1121 m_log.InfoFormat(
1122 "[SynchronousRestObjectRequester]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
1123 reqnum,
1124 verb,
1125 requestUrl,
1126 tickdiff,
1127 tickdata,
1128 originalRequest);
1129 }
1130
1016 return deserial; 1131 return deserial;
1017 } 1132 }
1018 } 1133 }
1019} \ No newline at end of file 1134}