Set the project.json so that you can compile either for the desktop framework or for .NET Core.

This commit is contained in:
Vance Morrison
2016-06-24 17:23:52 -07:00
parent 1e5229ad70
commit 8b3134e05f
2 changed files with 18 additions and 294 deletions
+18 -6
View File
@@ -1,9 +1,5 @@
{
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0-rc2-3002702",
"type": "platform"
},
"Microsoft.ApplicationInsights.AspNetCore": "1.0.0-rc2-final",
"Microsoft.AspNetCore.Mvc": "1.0.0-rc2-final",
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0-rc2-final",
@@ -15,8 +11,7 @@
"Microsoft.Extensions.Logging.Console": "1.0.0-rc2-final",
"Microsoft.Extensions.Logging.Debug": "1.0.0-rc2-final",
"Newtonsoft.Json": "8.0.3",
"Microsoft.AspNetCore.StaticFiles": "1.0.0-rc2-final",
"TraceEventCore": "1.0.41"
"Microsoft.AspNetCore.StaticFiles": "1.0.0-rc2-final"
},
"tools": {
@@ -27,13 +22,30 @@
},
"frameworks": {
/** comment out the net46 framework if you want to run on .NET Core */
"net46": {
"dependencies": {
"Microsoft.Diagnostics.Tracing.TraceEvent": "1.0.41",
"System.IO.Compression": "4.1.0",
"System.IO.Compression.ZipFile": "4.0.1"
}
}
/** comment out the netcorapp1.0 if you want to run on the Desktop framework.
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"version": "1.0.0-rc2-3002702",
"type": "platform"
},
"TraceEventCore": "1.0.41"
},
"imports": [
"dotnet5.6",
"dnxcore50",
"portable-net45+win8"
]
}
**/
},
"buildOptions": {
@@ -1,288 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved
// This file is best viewed using outline mode (Ctrl-M Ctrl-O)
//
// This program uses code hyperlinks available as part of the HyperAddin Visual Studio plug-in.
// It is available from http://www.codeplex.com/hyperAddin
// using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Symbols;
using Microsoft.Diagnostics.Tracing.Etlx;
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Parsers.Clr;
using Microsoft.Diagnostics.Tracing.Parsers.ClrPrivate;
using Microsoft.Diagnostics.Tracing.Parsers.FrameworkEventSource;
using Microsoft.Diagnostics.Tracing.Parsers.Kernel;
using Microsoft.Diagnostics.Tracing.Parsers.Symbol;
using Microsoft.Diagnostics.Tracing.Parsers.Tpl;
using Microsoft.Diagnostics.Tracing.Stacks;
using Microsoft.Diagnostics.Utilities;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using Address = System.UInt64;
namespace Microsoft.Diagnostics.Tracing.Analysis
{
/// <summary>
/// Extension methods to enable TraceManagedProcess
/// </summary>
public static class TraceManagedSamplesExtensions
{
public static void NeedManagedSamples(this TraceEventDispatcher source, Microsoft.Diagnostics.Tracing.Etlx.TraceLog tracelog)
{
// ensure there are base processes
source.NeedProcesses();
source.NeedManagedProcesses();
if (!source.UserData.ContainsKey("Computers/ManagedSamples"))
{
TraceProcesses processes = source.Processes();
SetupCallbacks(source, tracelog);
source.UserData["Computers/ManagedSamples"] = processes;
}
}
#region private
private static void SetupCallbacks(TraceEventDispatcher source, Microsoft.Diagnostics.Tracing.Etlx.TraceLog tracelog)
{
source.Kernel.PerfInfoSample += delegate (SampledProfileTraceData data)
{
var stats = data.Process();
var mang = stats.AsManagedProcess();
if (mang != null)
{
mang.JIT.Stats.TotalCpuTimeMSec += 1;
Tuple<string/*module*/,string/*method*/> name = GetSampledMethodName(tracelog, mang.JIT, data);
if (name == null) return;
MethodInformation meth = null;
var methods = mang.JIT.Methods.Where(m => m.ModuleILPath.Contains(name.Item1) && m.MethodName.Equals(name.Item2));
if (methods.Count() > 0)
{
Debug.Assert(methods.Count() == 1);
meth = methods.First();
}
else
{
meth = new MethodInformation( stats.ProcessIndex);
meth.ModuleILPath = name.Item1;
meth.MethodName = name.Item2;
meth.ILSize = meth.NativeSize = -1;
meth.CompileCpuTimeMSec = -1;
meth.StartTimeMSec = -1;
mang.JIT.Methods.Add(meth);
}
meth.RunCpuTimeMSec++;
}
};
}
private static Tuple<string/*module*/,string/*method*/> GetSampledMethodName(Microsoft.Diagnostics.Tracing.Etlx.TraceLog tracelog, JITDetails details, SampledProfileTraceData data)
{
TraceCodeAddress ca = details.Stats.GetManagedMethodOnStack(data, tracelog);
if (ca == null)
{
return null;
}
if (String.IsNullOrEmpty(ca.ModuleName))
{
return null;
}
// Lookup symbols, if not already looked up.
if (!details.Stats.SymbolsLookedUp.Contains(ca.ModuleName))
{
try
{
LookupSymbolsForModule(tracelog, data, ca.ModuleName);
}
catch (Exception)
{
return null;
}
details.Stats.SymbolsLookedUp.Add(ca.ModuleName);
}
if (ca.Method == null)
{
details.Stats.SymbolsMissing.Add(ca.ModuleName);
return null;
}
return new Tuple<string,string>(ca.ModuleName, ca.Method.FullMethodName);
}
public static void LookupSymbolsForModule(Microsoft.Diagnostics.Tracing.Etlx.TraceLog tracelog, SampledProfileTraceData data, string simpleModuleName)
{
var symbolReader = GetSymbolReader(tracelog.FilePath);
var filterProcess = tracelog.Processes.LastProcessWithID(data.ProcessID);
// Remove any extensions.
simpleModuleName = Path.GetFileNameWithoutExtension(simpleModuleName);
// If we have a process, look the DLL up just there
var moduleFiles = new Dictionary<int, TraceModuleFile>();
if (filterProcess != null)
{
foreach (var loadedModule in filterProcess.LoadedModules)
{
var baseName = Path.GetFileNameWithoutExtension(loadedModule.Name);
if (string.Compare(baseName, simpleModuleName, StringComparison.OrdinalIgnoreCase) == 0)
moduleFiles[(int)loadedModule.ModuleFile.ModuleFileIndex] = loadedModule.ModuleFile;
}
}
// We did not find it, try system-wide
if (moduleFiles.Count == 0)
{
foreach (var moduleFile in tracelog.ModuleFiles)
{
var baseName = Path.GetFileNameWithoutExtension(moduleFile.Name);
if (string.Compare(baseName, simpleModuleName, StringComparison.OrdinalIgnoreCase) == 0)
moduleFiles[(int)moduleFile.ModuleFileIndex] = moduleFile;
}
}
if (moduleFiles.Count == 0)
throw new ApplicationException("Could not find module " + simpleModuleName + " in trace.");
foreach (var moduleFile in moduleFiles.Values)
{
try
{
tracelog.CodeAddresses.LookupSymbolsForModule(symbolReader, moduleFile);
}
catch (ApplicationException)
{
}
}
}
public static SymbolReader GetSymbolReader(string etlFilePath = null, SymbolReaderOptions symbolFlags = SymbolReaderOptions.None)
{
SymbolPath symPath = new SymbolPath(SymbolPath);
if ((symbolFlags & SymbolReaderOptions.CacheOnly) != 0)
symPath = new SymbolPath("SRV*" + symPath.DefaultSymbolCache());
var sourcePath = SourcePath; // ???
bool hasLocalSymDir = false;
if (etlFilePath != null)
{
// Add the directory where the file resides and a 'symbols' subdirectory
var filePathDir = Path.GetDirectoryName(etlFilePath);
if (filePathDir.Length != 0)
{
// Then the directory where the .ETL file lives.
symPath.Insert(filePathDir);
// The symbols directory has even higher priority (less likely to have a false positive)
var localSymDir = Path.Combine(filePathDir, "symbols");
if (Directory.Exists(localSymDir))
{
hasLocalSymDir = true;
symPath.Insert(localSymDir);
symPath.Insert("SRV*" + localSymDir);
}
// WPR conventions add any .etl.ngenPDB directory to the path too. has higher priority still.
var wprSymDir = etlFilePath + ".NGENPDB";
if (Directory.Exists(wprSymDir))
symPath.Insert("SRV*" + wprSymDir);
else
{
// I have now seen both conventions .etl.ngenpdb and .ngenpdb, so look for both.
wprSymDir = Path.ChangeExtension(etlFilePath, ".NGENPDB");
if (Directory.Exists(wprSymDir))
symPath.Insert("SRV*" + wprSymDir);
}
// VS uses .NGENPDBS as a convention.
wprSymDir = etlFilePath + ".NGENPDBS";
if (Directory.Exists(wprSymDir))
symPath.Insert("SRV*" + wprSymDir);
if (!string.IsNullOrWhiteSpace(sourcePath))
sourcePath += ";";
sourcePath += filePathDir;
var srcDir = Path.Combine(filePathDir, "src");
if (Directory.Exists(srcDir))
sourcePath += ";" + srcDir;
}
}
// Can we use the cached symbol reader?
if (s_symbolReader != null)
{
s_symbolReader.SourcePath = sourcePath;
if (symbolFlags == SymbolReaderOptions.None && s_symbolReader.SymbolPath == symPath.ToString())
return s_symbolReader;
s_symbolReader.Dispose();
s_symbolReader = null;
}
SymbolReader ret = new SymbolReader(TextWriter.Null, symPath.ToString());
ret.SourcePath = sourcePath;
ret.Options = symbolFlags;
ret.SecurityCheck = (pdbFile => true);
ret.CacheUnsafeSymbols = hasLocalSymDir;
if (symbolFlags == SymbolReaderOptions.None)
s_symbolReader = ret;
return ret;
}
public static string SymbolPath
{
get
{
if (m_SymbolPath == null)
{
// Start with _NT_SYMBOL_PATH
var symPath = new SymbolPath(Microsoft.Diagnostics.Symbols.SymbolPath.SymbolPathFromEnvironment);
// If we still don't have anything, add a default one
// Since the default goes off machine, if we are outside of Microsoft, we have to ask
// the user for permission.
symPath.Add(Microsoft.Diagnostics.Symbols.SymbolPath.MicrosoftSymbolServerPath);
// Remember it.
SymbolPath = symPath.InsureHasCache(symPath.DefaultSymbolCache()).CacheFirst().ToString();
}
return m_SymbolPath;
}
set
{
m_SymbolPath = value;
}
}
public static string SourcePath
{
get
{
if (m_SourcePath == null)
{
var symPath = new SymbolPath(Environment.GetEnvironmentVariable("_NT_SOURCE_PATH"));
// Remember it.
SourcePath = symPath.ToString();
}
return m_SourcePath;
}
set
{
m_SourcePath = value;
}
}
private static string m_SymbolPath;
private static string m_SourcePath;
private static SymbolReader s_symbolReader;
#endregion
}
}