{"id":18148745,"url":"https://github.com/xiaomi7732/flamegraphnet","last_synced_at":"2025-10-28T04:30:51.649Z","repository":{"id":92448022,"uuid":"287449713","full_name":"xiaomi7732/FlameGraphNet","owner":"xiaomi7732","description":"Build FlameGraph using C#","archived":false,"fork":false,"pushed_at":"2024-12-30T06:00:45.000Z","size":201,"stargazers_count":4,"open_issues_count":4,"forks_count":1,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2024-12-30T06:44:26.366Z","etag":null,"topics":["flame-graph","stacks","svg"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xiaomi7732.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-08-14T05:16:12.000Z","updated_at":"2024-12-30T06:00:48.000Z","dependencies_parsed_at":"2023-06-01T03:15:08.126Z","dependency_job_id":null,"html_url":"https://github.com/xiaomi7732/FlameGraphNet","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiaomi7732%2FFlameGraphNet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiaomi7732%2FFlameGraphNet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiaomi7732%2FFlameGraphNet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiaomi7732%2FFlameGraphNet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xiaomi7732","download_url":"https://codeload.github.com/xiaomi7732/FlameGraphNet/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238590638,"owners_count":19497356,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flame-graph","stacks","svg"],"created_at":"2024-11-01T23:09:53.719Z","updated_at":"2025-10-28T04:30:51.632Z","avatar_url":"https://github.com/xiaomi7732.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flame Graph .NET\n\n## Description\n\nA .NET library that makes creating flame graph, output svg content easily.\n\n## Get started\n\n* Generate a flame graph like this:\n\n![Generated FlameGraph](./Demo.gif)\n\n* Add reference to the package:\n\n```shell\ndotnet add package FlameGraph.Net\n```\n\n* Crate a class that implements the IFlameGraphNode interface:\n\n```csharp\nclass SimpleNode : IFlameGraphNode\n{\n    public string Content { get; set; }\n\n    public double Metric { get; set; }\n\n    public List\u003cIFlameGraphNode\u003e Children { get; } = new List\u003cIFlameGraphNode\u003e();\n}\n```\n\n* Create tree structure using the the node class above:\n\n```csharp\nprivate static void SimpleNodeExample()\n{\n    // Get the tree\n    const int nodeCount = 20;\n    SimpleNode root = new SimpleNode()\n    {\n        Content = $\"Node {nodeCount.ToString(\"0\")}\",\n        Metric = nodeCount,\n    };\n    root = AppendChildren(root, nodeCount);\n\n    // Create a graph factory with options.\n    FlameGraph newGraph = new FlameGraph(new FlameGraphOptions()\n    {\n        Title = \"Hello Flame Graph\",\n        Width = 800,\n        Height = 600,\n    });\n\n    // Output the svg\n    string fileName = nameof(SimpleNodeExample) + \".svg\";\n    DeleteFileWhenExists(fileName);\n    newGraph.BuildTo(root, fileName);\n}\n\n// Generate a simple tree.\nprivate static SimpleNode AppendChildren(SimpleNode current, double metricValue)\n{\n    metricValue--;\n    if (metricValue \u003e 0)\n    {\n        SimpleNode newChild = new SimpleNode()\n        {\n            Content = $\"Node {metricValue.ToString(\"0\")}\",\n            Metric = metricValue,\n        };\n\n        current.Children.Add(AppendChildren(newChild, metricValue));\n    }\n    return current;\n}\n\nprivate static void DeleteFileWhenExists(string resultFilePath)\n{\n    if (File.Exists(resultFilePath))\n    {\n        File.Delete(resultFilePath);\n    }\n}\n```\n\n## Advanced Topics\n\n### Use different background colors for frames\n\nColorize frames with different colors could help quickly identify interesting targets. `FrameBackgroundProvider` in `FlameGraphOptions` can be used to reach the goal:\n\n```csharp\nFlameGraph newGraph = new FlameGraph(new FlameGraphOptions()\n{\n    Title = \"Hello Flame Graph\",\n    ... // The following delegate returns 2 colors depends on the value of the metrics.\n    FrameBackgroundProvider = node =\u003e\n    {\n        if (node.Metric \u003e 10)\n        {\n            return Color.OrangeRed;\n        }\n        return Color.DarkOrange;\n    },\n});\n```\n\nThe options above will highlight (OrangeRed) any frames that has a value greater than 10 and those frames will easily catch the eyes:\n\n![Flame Graph with various color](./images/flameGraphWithColor.png)\n\n_Tips: combine the node.Content with regular expression to return various colors._\n\n### Manual height vs Auto height\n\nBy default, there's option to control the generated svg height. For example, the following option is going to make an svg of heights of 1000.\nIn this mode, the frames on the graph might be truncated, only limited levels could fit into the height.\n\n```csharp\nFlameGraph graph = new FlameGraph(new FlameGraphOptions()\n{\n    Title = \"Hello Flame Graph\",\n    Width = 800,\n    Height = 1000\n});\n```\n\nSometimes, it will be convenient to just generate an svg that fits shows all stacks - no matter the height. An option of `AutoHeight` is provided:\n\n```csharp\nFlameGraph graph = new FlameGraph(new FlameGraphOptions()\n{\n    Title = \"Hello Flame Graph\",\n    Width = 800,\n    AutoHeight = true, // Set auto height to true\n    Height = 1000  // This setting will be overwritten and takes no effect.\n});\n```\n\nIn this case, the graph height will be calculated automatically to fit the whole stack. The deeper the tree passed in, the taller the height becomes.\n\n### Using any existing tree node as flame graph node\n\nThe key is to provide 3 delegates to extract the following items from a existing object:\n\n* Content\n* Metric\n* Children\n\nHere's an example:\n\n```csharp\nprivate static void NodeAdapterExample()\n{\n    // Create delegates for adaption\n    Func\u003cTreeNode, string\u003e getContent = n =\u003e n.Text;\n    Func\u003cTreeNode, double\u003e getMetric = n =\u003e n.Value;\n    Func\u003cTreeNode, IEnumerable\u003cTreeNode\u003e\u003e getChildren = n =\u003e n.Children;\n\n    // Generate an example tree\n    const int levels = 20;\n    TreeNode root = new TreeNode(\"Root\", levels);\n    root = AppendChildren(root, levels);\n\n    // Adapter the tree\n    var wrappedRoot = new FlameGraphNode\u003cTreeNode\u003e(root, getContent, getMetric, getChildren);\n\n    // Output the svg stream to file.\n    FlameGraph graph = new FlameGraph(new FlameGraphOptions()\n    {\n        Title = \"Hello Flame Graph\",\n        Width = 800,\n        Height = 600,\n    });\n\n    using Stream svgStream = graph.Build(wrappedRoot);\n    using FileStream fileStream = new FileStream($\"{nameof(NodeAdapterExample)}.svg\", FileMode.Create, FileAccess.Write);\n    svgStream.CopyTo(fileStream);\n}\n\nprivate static TreeNode AppendChildren(TreeNode current, double metricValue)\n{\n    metricValue--;\n    if (metricValue \u003e 0)\n    {\n        TreeNode newChild = new TreeNode($\"Node {metricValue.ToString(\"0\")}\", metricValue);\n        current.Children.Add(AppendChildren(newChild, metricValue));\n    }\n    return current;\n}\n```\n\nTreeNode is a class that doesn't implement IFlameGraphNode. 3 delegates are crated to extract enough information from it:\n\n```csharp\n    // Create delegates for adaption\n    Func\u003cTreeNode, string\u003e getContent = n =\u003e n.Text;\n    Func\u003cTreeNode, double\u003e getMetric = n =\u003e n.Value;\n    Func\u003cTreeNode, IEnumerable\u003cTreeNode\u003e\u003e getChildren = n =\u003e n.Children;\n```\n\nAnd then a wrappedRoot is created based on the info:\n\n```csharp\nvar wrappedRoot = new FlameGraphNode\u003cTreeNode\u003e(root, getContent, getMetric, getChildren);\n```\n\nThe rest of it shows to write the stream output to a file directly.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxiaomi7732%2Fflamegraphnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxiaomi7732%2Fflamegraphnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxiaomi7732%2Fflamegraphnet/lists"}