NuGet dependency visualizer with F# and Graphviz

Script for this article is available as public Gist.

For a long time I was interested in what is going on on NuGet. I think that NuGet UI does not provide one important piece of information – which packages depend on current packages. This information is very useful for package authors and also can help a user to find packages that provide more sophisticated implementation.

Other interesting thing is to see the big picture and answer some global questions:

  • What is inside the technology I use? What is the dependency of packages that I use? What are dependencies of dependencies and so on.
  • What is built on top of packages that I maintain? What beautiful applications of my ideas other can find? What is the cost of releasing a broken package? Who can be harmed?

I believe that there are a lot of other answers we can find from the high view.

Some time ago I have found that NuGet team provides NuGet.Core package that has all  API required to communicate with NuGet. The API is not really fast if you are going to download information about all versions of all NuGet packages 😉 But NuGet team is working on a new v3 API that is going to be much faster than current v2. For current research I have downloaded info about all packages and all their versions to my FSI session to be able to run different types of analysis and create visualizations without further communication with NuGet. This operation is slow enough: it took about 1 hour last time when I run it, but it really depends on NuGet workload and your internet connection.

The second thing is visualization of the result, here I want to say thank you to Scott Wlaschin for his great script type-dependency-graph.fsx (that was built for ‘Cycles and modularity in the wild‘ analysis). I took his GraphViz module and slightly modified it to allow colorful graphs printing. To use it you need to download GraphViz from the official site.

That is all tooling that we need. So we are ready to describe a structure of an analysis – script extracts 3 subsets of NuGet packages and visualizes them in different colors with all dependencies.

  1. Packages that are in scope of analysis (green on the graphs)
  2. Packages that we depend on (grey on the graph) – Package is in the set 2 if exists a dependency path from any package from Set 1 to this package.
  3. Packages that depend on us (blue on the graph) – Package is in the set 3 if exists a dependency path from this package to any package from Set 1.

NOTE: In this analysis I ignored package version and considered only latest package version and dependencies of latest version. If you need more accurate analysis you should adjust script a bit.

Running this script I did some interesting observations:

FsPickler is already highly used by other packages!
FsPickler is already highly used by other packages!
FSharp.Compiler.Service is already deeply incorporated in tooling!
FSharp.Compiler.Service is already deeply incorporated in tooling!
Too many different Fsharp.Core packages of NuGet adopted by different tools.
Too many different Fsharp.Core packages on NuGet adopted by different tools.
FSharpx is still alive! ;)
FSharpx is still alive! 😉
Roslyn.dot
Roslyn ohhhh Roslyn

 

F# Ecosystem is HUGE! (see full svg version here, surry bug without FunScipt ;))
F# Ecosystem is HUGE! (see full svg version here, sorry but without FunScipt ;))

I hope that you’ll also find this script useful and discover something interesting on NuGet.

 

9 thoughts on “NuGet dependency visualizer with F# and Graphviz

      1. I’ve written it as a small exercise of F# so I’ve never expected such popularity. I will try to provide more info and examples in the free time (I hope it will be soon).

  1. Hi Sergey Tihon,

    Thanks for your blog and hoping to see nice graphviz applications but.
    As a result of reading an incorrect formatted source from Nuget repository the code gives an exception, can you please help with it by perhaps a filter

    The code is:

    let latestVersionOfNuGetPackages =
    allNuGetPackages // |> Stream.filter (fun p -> p :> Uri) ??
    |> Stream.groupBy (fun p -> p.Id)


    “codedocs”
    > System.InvalidOperationException: The current value ‘String’ type is not compatible with the expected ‘System.Uri’ type. —> System.UriFormatException: Invalid URI: The hostname could not be parsed.
    at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
    at System.Uri..ctor(String uriString, UriKind uriKind)
    at System.Data.Services.Client.ClientConvert.ChangeType(String propertyValue, Type propertyType)
    — End of inner exception stack trace —
    at System.Data.Services.Client.ClientConvert.ChangeType(String propertyValue, Type propertyType)
    at System.Data.Services.Client.AtomMaterializer.MaterializeDataValue(Type type, AtomContentProperty atomProperty, DataServiceContext context)
    at System.Data.Services.Client.AtomMaterializer.MaterializeDataValues(ClientType actualType, List`1 values, Boolean ignoreMissingProperties, DataServiceContext context)
    at System.Data.Services.Client.AtomMaterializer.MaterializeResolvedEntry(AtomEntry entry, Boolean includeLinks)
    at System.Data.Services.Client.AtomMaterializerInvoker.DirectMaterializePlan(Object materializer, Object entry, Type expectedEntryType)
    at System.Data.Services.Client.ProjectionPlan.Run(AtomMaterializer materializer, AtomEntry entry, Type expectedType)
    at System.Data.Services.Client.AtomMaterializer.Read()
    at System.Data.Services.Client.MaterializeAtom.MoveNextInternal()
    at System.Data.Services.Client.MaterializeAtom.MoveNext()
    at NuGet.DataServiceQueryWrapper`1.d__7.MoveNext()
    at FSI_0015.allNuGetPackages@117-1.Invoke(Unit unitVar0) in C:\Users\Musa\Documents\f\fsdot-master\src\nuget-dependency-visualizer.fsx:line 117
    at .$FSI_0016.main@() in src\nuget-dependency-visualizer.fsx:line 127
    Stopped due to error

    1. The error occurs in `Nuget.Core.dll`, that is uses `v2` version of `Nuget` Api.
      1) I am not sure that this package is still supported
      2) You probably cannot fix it on the script side

  2. Any fix or work around for tutorial purpose will be helpful. If the issue is with Nuget.Core.dll v2 then what is a relevant pull request point of where to be placed? It crashes when loading “coder” from repository. I have also tried older and newer dll’s.

    //#I @”packages\Nuget.Core.2.8.3\lib\net40-Client”
    #I @”packages\Nuget.Core.2.14.0\lib\net40-Client”
    //#I @”packages\Nuget.Core.1.8.0\lib\net40-Client”
    #r “NuGet.Core.dll”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s