/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim:set expandtab ts=4 sw=2 sts=2 cin: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "NetworkMarker.h" #include "HttpBaseChannel.h" #include "nsIChannelEventSink.h" namespace mozilla { namespace net { static constexpr net::TimingStruct scEmptyNetTimingStruct; void profiler_add_network_marker( nsIURI* aURI, const nsACString& aRequestMethod, int32_t aPriority, uint64_t aChannelId, NetworkLoadType aType, mozilla::TimeStamp aStart, mozilla::TimeStamp aEnd, int64_t aCount, mozilla::net::CacheDisposition aCacheDisposition, uint64_t aInnerWindowID, bool aIsPrivateBrowsing, const mozilla::net::TimingStruct* aTimings, UniquePtr aSource, const Maybe& aContentType, nsIURI* aRedirectURI, uint32_t aRedirectFlags, uint64_t aRedirectChannelId) { if (!profiler_thread_is_being_profiled_for_markers()) { return; } nsAutoCStringN<2048> name; name.AppendASCII("Load "); // top 32 bits are process id of the load name.AppendInt(aChannelId & 0xFFFFFFFFu); // These can do allocations/frees/etc; avoid if not active nsAutoCStringN<2048> spec; if (aURI) { aURI->GetAsciiSpec(spec); name.AppendASCII(": "); name.Append(spec); } nsAutoCString redirect_spec; if (aRedirectURI) { aRedirectURI->GetAsciiSpec(redirect_spec); } struct NetworkMarker { static constexpr Span MarkerTypeName() { return MakeStringSpan("Network"); } static void StreamJSONMarkerData( baseprofiler::SpliceableJSONWriter& aWriter, mozilla::TimeStamp aStart, mozilla::TimeStamp aEnd, int64_t aID, const ProfilerString8View& aURI, const ProfilerString8View& aRequestMethod, NetworkLoadType aType, int32_t aPri, int64_t aCount, net::CacheDisposition aCacheDisposition, bool aIsPrivateBrowsing, const net::TimingStruct& aTimings, const ProfilerString8View& aRedirectURI, const ProfilerString8View& aContentType, uint32_t aRedirectFlags, int64_t aRedirectChannelId) { // This payload still streams a startTime and endTime property because it // made the migration to MarkerTiming on the front-end easier. aWriter.TimeProperty("startTime", aStart); aWriter.TimeProperty("endTime", aEnd); aWriter.IntProperty("id", aID); aWriter.StringProperty("status", GetNetworkState(aType)); if (Span cacheString = GetCacheState(aCacheDisposition); !cacheString.IsEmpty()) { aWriter.StringProperty("cache", cacheString); } aWriter.IntProperty("pri", aPri); if (aCount > 0) { aWriter.IntProperty("count", aCount); } if (aURI.Length() != 0) { aWriter.StringProperty("URI", aURI); } if (aRedirectURI.Length() != 0) { aWriter.StringProperty("RedirectURI", aRedirectURI); aWriter.StringProperty("redirectType", getRedirectType(aRedirectFlags)); aWriter.BoolProperty( "isHttpToHttpsRedirect", aRedirectFlags & nsIChannelEventSink::REDIRECT_STS_UPGRADE); if (aRedirectChannelId != 0) { aWriter.IntProperty("redirectId", aRedirectChannelId); } } aWriter.StringProperty("requestMethod", aRequestMethod); if (aContentType.Length() != 0) { aWriter.StringProperty("contentType", aContentType); } else { aWriter.NullProperty("contentType"); } if (aIsPrivateBrowsing) { aWriter.BoolProperty("isPrivateBrowsing", aIsPrivateBrowsing); } if (aType != NetworkLoadType::LOAD_START) { aWriter.TimeProperty("domainLookupStart", aTimings.domainLookupStart); aWriter.TimeProperty("domainLookupEnd", aTimings.domainLookupEnd); aWriter.TimeProperty("connectStart", aTimings.connectStart); aWriter.TimeProperty("tcpConnectEnd", aTimings.tcpConnectEnd); aWriter.TimeProperty("secureConnectionStart", aTimings.secureConnectionStart); aWriter.TimeProperty("connectEnd", aTimings.connectEnd); aWriter.TimeProperty("requestStart", aTimings.requestStart); aWriter.TimeProperty("responseStart", aTimings.responseStart); aWriter.TimeProperty("responseEnd", aTimings.responseEnd); } } static MarkerSchema MarkerTypeDisplay() { return MarkerSchema::SpecialFrontendLocation{}; } private: static Span GetNetworkState(NetworkLoadType aType) { switch (aType) { case NetworkLoadType::LOAD_START: return MakeStringSpan("STATUS_START"); case NetworkLoadType::LOAD_STOP: return MakeStringSpan("STATUS_STOP"); case NetworkLoadType::LOAD_REDIRECT: return MakeStringSpan("STATUS_REDIRECT"); case NetworkLoadType::LOAD_CANCEL: return MakeStringSpan("STATUS_CANCEL"); default: MOZ_ASSERT(false, "Unexpected NetworkLoadType enum value."); return MakeStringSpan(""); } } static Span GetCacheState( net::CacheDisposition aCacheDisposition) { switch (aCacheDisposition) { case net::kCacheUnresolved: return MakeStringSpan("Unresolved"); case net::kCacheHit: return MakeStringSpan("Hit"); case net::kCacheHitViaReval: return MakeStringSpan("HitViaReval"); case net::kCacheMissedViaReval: return MakeStringSpan("MissedViaReval"); case net::kCacheMissed: return MakeStringSpan("Missed"); case net::kCacheUnknown: return MakeStringSpan(""); default: MOZ_ASSERT(false, "Unexpected CacheDisposition enum value."); return MakeStringSpan(""); } } static Span getRedirectType(uint32_t aRedirectFlags) { MOZ_ASSERT(aRedirectFlags != 0, "aRedirectFlags should be non-zero"); if (aRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) { return MakeStringSpan("Temporary"); } if (aRedirectFlags & nsIChannelEventSink::REDIRECT_PERMANENT) { return MakeStringSpan("Permanent"); } if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) { return MakeStringSpan("Internal"); } MOZ_ASSERT(false, "Couldn't find a redirect type from aRedirectFlags"); return MakeStringSpan(""); } }; profiler_add_marker( name, geckoprofiler::category::NETWORK, {MarkerTiming::Interval(aStart, aEnd), MarkerStack::TakeBacktrace(std::move(aSource)), MarkerInnerWindowId(aInnerWindowID)}, NetworkMarker{}, aStart, aEnd, static_cast(aChannelId), spec, aRequestMethod, aType, aPriority, aCount, aCacheDisposition, aIsPrivateBrowsing, aTimings ? *aTimings : scEmptyNetTimingStruct, redirect_spec, aContentType ? ProfilerString8View(*aContentType) : ProfilerString8View(), aRedirectFlags, aRedirectChannelId); } } // namespace net } // namespace mozilla