PageSourceSearch

https://nbomber.com/assets/js/92206179.151f5e6b.js

js nbomber.com collected 2026-10-02 06:25:24 UTC 8,260 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunknbomber_docs=globalThis.webpackChunknbomber_docs||[]).push([[7563],{2517(e,t,n){n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>l,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>h});const s=JSON.parse('{"id":"nbomber/custom-metrics","title":"Custom Metrics","description":"Overview","source":"@site/docs/nbomber/custom-metrics.md","sourceDirName":"nbomber","slug":"/nbomber/custom-metrics","permalink":"/docs/nbomber/custom-metrics","draft":false,"unlisted":false,"editUrl":"https://github.com/PragmaticFlow/NBomber.Docs/blob/dev/docs/nbomber/custom-metrics.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"id":"custom-metrics","title":"Custom Metrics","sidebar_position":8},"sidebar":"tutorialSidebar","previous":{"title":"Logger","permalink":"/docs/nbomber/logger"},"next":{"title":"Dynamic Workloads","permalink":"/docs/nbomber/dynamic-workloads"}}');var r=n(4848),i=n(8453);const o=n.p+"assets/images/custom_metrics-88b43ab290731fdbc5391e82910c8172.jpg",c=n.p+"assets/images/custom_metrics_tab-c04a2725519691756378f296937b0d82.jpg",a={id:"custom-metrics",title:"Custom Metrics",sidebar_position:8},l=void 0,u={},h=[{value:"Overview",id:"overview",level:2},{value:"Setting up Custom Metrics",id:"setting-up-custom-metrics",level:2},{value:"Viewing Custom Metrics in the HTML report",id:"viewing-custom-metrics-in-the-html-report",level:2},{value:"Using Thresholds",id:"using-thresholds",level:2},{value:"Using Thresholds via JSON Config",id:"using-thresholds-via-json-config",level:2}];function m(e){const t={a:"a",code:"code",em:"em",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)("center",{children:(0,r.jsx)("img",{src:o,width:"75%",height:"75%"})}),"\n",(0,r.jsx)(t.h2,{id:"overview",children:"Overview"}),"\n",(0,r.jsx)(t.p,{children:"Metrics are numerical measurements reported over time. By default, NBomber automatically collects built-in metrics: CPU, RAM (usage), Data (sent/receive), and more. Besides built-ins, you can also define custom metrics."}),"\n",(0,r.jsx)(t.p,{children:"NBomber provides different types of custom metrics that you can use, depending on what you want to measure. These include:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"Counter"}),": a cumulative count of events, such as the number of successful or failed requests."]}),"\n"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-csharp",children:'var counter = Metric.CreateCounter("my-counter", unitOfMeasure: "MB");\ncounter.Add(2); // tracks a value that may increase or decrease over time\ncounter.Add(-1);\n'})}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:[(0,r.jsx)(t.strong,{children:"Gauge"}),": measures the last value recorded, such as memory usage or the number of active users at a given time."]}),"\n"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-csharp",children:'var gauge = Metric.CreateGauge("my-gauge", unitOfMeasure: "KB");\ngauge.Set(6.5);\ngauge.Set(7.3); // set the current value of the metric\n'})}),"\n",(0,r.jsx)(t.h2,{id:"setting-up-custom-metrics",children:"Setting up Custom Metrics"}),"\n",(0,r.jsx)(t.p,{children:"Let's take a look at how you can define custom metrics in your code. In the following sections, you'll also learn how to add thresholds on top of them."}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-csharp",children:'// define custom metrics\nvar counter = Metric.CreateCounter("my-counter", unitOfMeasure: "MB");\nvar gauge = Metric.CreateGauge("my-gauge", unitOfMeasure: "KB");\n\nvar scenario = Scenario.Create("scenario", async context =>\n{\n    await Task.Delay(500);\n\n    // highlight-start\n    counter.Add(1); // tracks a value that may increase or decrease over time\n    gauge.Set(6.5); // set the current value of the metric\n    // highlight-end\n\n    return Response.Ok();\n})\n.WithInit(ctx =>\n{\n    // register custom metrics\n    // highlight-start\n    ctx.RegisterMetric(counter);\n    ctx.RegisterMetric(gauge);\n    // highlight-end\n\n    return Task.CompletedTask;\n});
1\n\nvar stats = NBomberRunner\n    .RegisterScenarios(scenario)\n    .Run();\n\n// we can retrieve the final metric values for further assertions\n// highlight-start\nvar counterValue = stats.Metrics.Counters.Find("my-counter").Value;\nvar gaugeValue = stats.Metrics.Gauges.Find("my-gauge").Value;\n// highlight-end\n'})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsxs)(t.em,{children:["You can find the complete example by this ",(0,r.jsx)(t.a,{href:"https://github.com/PragmaticFlow/NBomber/blob/dev/examples/Demo/Features/CustomMetrics/CustomMetricsExample.cs",children:"link"}),"."]})}),"\n",(0,r.jsx)(t.h2,{id:"viewing-custom-metrics-in-the-html-report",children:"Viewing Custom Metrics in the HTML report"}),"\n",(0,r.jsx)(t.p,{children:"After running a load test, you will be able to view and check custom metric values in the HTML report."}),"\n",(0,r.jsx)("center",{children:(0,r.jsx)("img",{src:c,width:"80%",height:"80%"})}),"\n",(0,r.jsx)(t.h2,{id:"using-thresholds",children:"Using Thresholds"}),"\n",(0,r.jsxs)(t.p,{children:["While custom metrics give you quantitative insights, ",(0,r.jsx)(t.a,{href:"/docs/nbomber/asserts_and_thresholds",children:"Thresholds"})," in NBomber allow you to validate specific conditions. Using thresholds helps ensure that the system\u2019s behavior meets predefined performance standards."]}
1),"\n",(0,r.jsx)(t.p,{children:"Here\u2019s how you can define thresholds for custom metrics:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-csharp",children:'// define custom metrics\nvar counter = Metric.CreateCounter("my-counter", unitOfMeasure: "MB");\nvar gauge = Metric.CreateGauge("my-gauge", unitOfMeasure: "KB");\n\nvar scenario = Scenario.Create("scenario", async context =>\n{\n    ...\n})\n.WithInit(ctx =>\n{\n    // register custom metrics\n    ctx.RegisterMetric(counter);\n    ctx.RegisterMetric(gauge);\n\n    return Task.CompletedTask;\n})\n.WithThresholds(\n    // highlight-start\n    Threshold.Create(metric => metric.Counters.Get("my-counter").Value < 1000),\n    Threshold.Create(metric => metric.Gauges.Get("my-gauge").Value >= 6.5)\n    // highlight-end\n);\n'})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsxs)(t.em,{children:["You can find the complete example by this ",(0,r.jsx)(t.a,{href:"https://github.com/PragmaticFlow/NBomber/blob/dev/examples/Demo/Features/CustomMetrics/CustomMetricsExample.cs",children:"link"}),"."]})}),"\n",(0,r.jsx)(t.h2,{id:"using-thresholds-via-json-config",children:"Using Thresholds via JSON Config"}),"\n",(0,r.jsxs)(t.p,{children:["Additionaly, you can define ",(0,r.jsx)(t.a,{href:"asserts_and_thresholds#runtime-thresholds-in-json-config",children:"Thresholds"})," in ",(0,r.jsx)(t.a,{href:"/docs/nbomber/json-config",children:"JSON Config"})," file."]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-json",metastring:'title="nbomber-config.json"',children:'{\n    "GlobalSettings": {\n\n        "ScenariosSettings": [\n            {\n                "ScenarioName": "scenario",\n\n                "ThresholdSettings": [\n\n                    { "Metric": ["my-counter", "value < 1000"] },\n                    { "Metric": ["my-gauge", "value >= 6.5"] }\n\n                ]\n            }\n        ]\n    }\n}\n'})}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsxs)(t.em,{children:["You can find the complete example by this ",(0,r.jsx)(t.a,{href:"https://github.com/PragmaticFlow/NBomber/blob/dev/examples/Demo/Features/CustomMetrics/nbomber-config.json",children:"link"}),"."]})})]})}function d(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(m,{...e})}):m(e)}},8453(e,t,n){n.d(t,{R:()=>o,x:()=>c});var s=n(6540);const r={},i=s.createContext(r);function o(e){const t=s.useContext(i);return s.useMemo(function(){return"function"==typeof e?e(t):{...t,...e}},[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.