diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index e6407ecf220b0df466bb3542a745df6c1ab415d8..9c49f7eff4dc6fb73c503b988cda57d4cff58b70 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -572,7 +572,7 @@ namespace LLError
 		mFunctionString += std::string(mFunction) + ":";
 		for (size_t i = 0; i < mTagCount; i++)
 		{
-			mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : ",");
+			mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? " " : ",");
 		}
 	}
 
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index 7bf886ef262ddf4086122127276c412358e946cd..ab6fc694138539a1e7c2225f5f2027c3acecf1d1 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -195,7 +195,8 @@ LLAssetRequest::LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType type
         mInfoCallback( NULL ),
         mIsLocal(FALSE),
         mIsUserWaiting(FALSE),
-        mTimeout(LL_ASSET_STORAGE_TIMEOUT)
+        mTimeout(LL_ASSET_STORAGE_TIMEOUT),
+        mBytesFetched(0)
 {
 }
 
@@ -641,6 +642,20 @@ void LLAssetStorage::downloadCompleteCallback(
             result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE;
             vfile.remove();
         }
+        else
+        {
+#if 1
+            for (request_list_t::iterator iter = gAssetStorage->mPendingDownloads.begin();
+                 iter != gAssetStorage->mPendingDownloads.end(); ++iter  )
+            {
+                LLAssetRequest* dlreq = *iter;
+                if ((dlreq->getUUID() == file_id) && (dlreq->getType()== file_type))
+                {
+                    dlreq->mBytesFetched = vfile.getSize();
+                }
+            }
+#endif
+        }
     }
 
     removeAndCallbackPendingDownloads(file_id, file_type, callback_id, callback_type, ext_status, result);
diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h
index 2ec8ac31b487aff30136bd69bd380081c745581b..d6b4fa0c7b949059478797dc4c0e367e0927dc3c 100644
--- a/indra/llmessage/llassetstorage.h
+++ b/indra/llmessage/llassetstorage.h
@@ -138,6 +138,7 @@ class LLAssetRequest : public LLBaseDownloadRequest
 	BOOL	mIsUserWaiting;		// We don't want to try forever if a user is waiting for a result.
 	F64Seconds		mTimeout;			// Amount of time before timing out.
 	LLUUID	mRequestingAgentID;	// Only valid for uploads from an agent
+    F64	mBytesFetched;
 
 	virtual LLSD getTerseDetails() const;
 	virtual LLSD getFullDetails() const;
diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp
index d47f73ccce1ec0a5f82bc49668fa93a1ac23b7a5..a9e0ba7b5d5d1d7eed273b95081e405507f85fbc 100644
--- a/indra/newview/llviewerassetstats.cpp
+++ b/indra/newview/llviewerassetstats.cpp
@@ -168,6 +168,7 @@ namespace LLViewerAssetStatsFF
 
 	static LLTrace::DCCountStatHandle<> sEnqueued[EVACCount];
 	static LLTrace::DCCountStatHandle<> sDequeued[EVACCount];
+	static LLTrace::DCEventStatHandle<> sBytesFetched[EVACCount];
 	static LLTrace::DCEventStatHandle<F64Seconds > sResponse[EVACCount];
 }
 
@@ -277,7 +278,8 @@ void LLViewerAssetStats::getStat(LLTrace::Recording& rec, T& req, LLViewerAssetS
             .resp_count(rec.getSampleCount(sResponse[cat]))
             .resp_min(rec.getMin(sResponse[cat]).value())
             .resp_max(rec.getMax(sResponse[cat]).value())
-            .resp_mean(rec.getMean(sResponse[cat]).value());
+            .resp_mean(rec.getMean(sResponse[cat]).value())
+            .resp_mean_bytes(rec.getMean(sBytesFetched[cat]));
     }
 }
 
@@ -370,11 +372,12 @@ void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp)
 	add(sDequeued[int(eac)], 1);
 }
 
-void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration)
+void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration, F64 bytes)
 {
 	const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp));
 
 	record(sResponse[int(eac)], F64Microseconds(duration));
+	record(sBytesFetched[int(eac)], bytes);
 }
 
 void init()
@@ -403,7 +406,8 @@ LLViewerAssetStats::AssetRequestType::AssetRequestType()
 	resp_count("resp_count"),
 	resp_min("resp_min"),
 	resp_max("resp_max"),
-	resp_mean("resp_mean")
+	resp_mean("resp_mean"),
+    resp_mean_bytes("resp_mean_bytes")
 {}
 	
 LLViewerAssetStats::FPSStats::FPSStats() 
diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h
index a2545c0bad555438f854054cc0c94c0656fa53ce..718c2842247551431d1e99966926c00d6cfb1710 100644
--- a/indra/newview/llviewerassetstats.h
+++ b/indra/newview/llviewerassetstats.h
@@ -118,11 +118,12 @@ class LLViewerAssetStats : public LLStopWatchControlsMixin<LLViewerAssetStats>
 	struct AssetRequestType : public LLInitParam::Block<AssetRequestType>
 	{
 		Mandatory<S32>	enqueued,
-			dequeued,
-			resp_count;
+						dequeued,
+						resp_count;
 		Mandatory<F64>	resp_min,
 						resp_max,
-						resp_mean;
+						resp_mean,
+						resp_mean_bytes;
 	
 		AssetRequestType();
 	};
@@ -272,7 +273,7 @@ void record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp);
 void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp);
 
 void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp,
-						  LLViewerAssetStats::duration_t duration);
+                     LLViewerAssetStats::duration_t duration, F64 bytes=0);
 
 void record_avatar_stats();
 
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index 85150bf7fa07eddddf0479190dfed5bae68991fd..fa3567620c2faf9ffd8392fe212af2bdd9e31c3a 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -82,7 +82,8 @@ class LLViewerAssetRequest : public LLAssetRequest
             LLViewerAssetStatsFF::record_dequeue(mType, mWithHTTP, false);
             LLViewerAssetStatsFF::record_response(mType, mWithHTTP, false,
                                                   (LLViewerAssetStatsFF::get_timestamp()
-                                                   - mMetricsStartTime));
+                                                   - mMetricsStartTime),
+                                                  mBytesFetched);
             mMetricsStartTime = (U32Seconds)0;
         }
     }
@@ -458,12 +459,13 @@ void LLViewerAssetStorage::queueRequestHttp(
             LLViewerAssetStatsFF::record_enqueue(atype, with_http, is_temp);
 
             LLCoros::instance().launch("LLViewerAssetStorage::assetRequestCoro",
-                                       boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, uuid, atype, callback, user_data));
+                                       boost::bind(&LLViewerAssetStorage::assetRequestCoro, this, req, uuid, atype, callback, user_data));
         }
     }
 }
 
 void LLViewerAssetStorage::assetRequestCoro(
+    LLViewerAssetRequest *req,
     const LLUUID& uuid,
     LLAssetType::EType atype,
     LLGetAssetCallback callback,
@@ -506,6 +508,7 @@ void LLViewerAssetStorage::assetRequestCoro(
             temp_id.generate();
             LLVFile vf(gAssetStorage->mVFS, temp_id, atype, LLVFile::WRITE);
             vf.setMaxSize(size);
+            req->mBytesFetched = size;
             if (!vf.write(raw.data(),size))
             {
                 // TODO asset-http: handle error
diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h
index d28a8a276ff03bdb150686258143ad8074a2751f..3ca81126018ea259d73094b630ab3f41a84ed7fd 100644
--- a/indra/newview/llviewerassetstorage.h
+++ b/indra/newview/llviewerassetstorage.h
@@ -31,6 +31,8 @@
 
 class LLVFile;
 
+class LLViewerAssetRequest;
+
 class LLViewerAssetStorage : public LLAssetStorage
 {
 public:
@@ -85,7 +87,8 @@ class LLViewerAssetStorage : public LLAssetStorage
                           BOOL duplicate,
                           BOOL is_priority);
 
-    void assetRequestCoro(const LLUUID& uuid,
+    void assetRequestCoro(LLViewerAssetRequest *req,
+                          const LLUUID& uuid,
                           LLAssetType::EType atype,
                           void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
                           void *user_data);
diff --git a/scripts/metrics/viewer_asset_logs.py b/scripts/metrics/viewer_asset_logs.py
index 47f06581384ba22030e58fe0e7e5e00cefdc1b4e..8e46ca470724081b729db3b0f3233eb8943b4279 100644
--- a/scripts/metrics/viewer_asset_logs.py
+++ b/scripts/metrics/viewer_asset_logs.py
@@ -72,6 +72,7 @@ def update_stats(stats,rec):
                 #print "field",field,"count",type_stats["count"]
                 if (newcount>0):
                     type_stats["sum"] = type_stats.get("sum",0) + val["resp_count"] * val["resp_mean"]
+                    type_stats["sum_bytes"] = type_stats.get("sum_bytes",0) + val["resp_count"] * val.get("resp_mean_bytes",0)
                 type_stats["enqueued"] = type_stats.get("enqueued",0) + val["enqueued"]
                 type_stats["dequeued"] = type_stats.get("dequeued",0) + val["dequeued"]
                 
@@ -92,7 +93,10 @@ def update_stats(stats,rec):
 
         update_stats(stats,rec)
 
-    for key, val in stats.iteritems():
+    for key in sorted(stats.keys()):
+        val = stats[key]
         if val["count"] > 0:
-            print "key",key,"count",val["count"],"mean",val["sum"]/val["count"],"enqueued",val["enqueued"],"dequeued",val["dequeued"]
+            print key,"count",val["count"],"mean_time",val["sum"]/val["count"],"mean_bytes",val["sum_bytes"]/val["count"],"enqueued",val["enqueued"],"dequeued",val["dequeued"]
+        else:
+            print key,"count",val["count"],"enqueued",val["enqueued"],"dequeued",val["dequeued"]