{"id":17162,"library":"artillery-plugin-metrics-by-endpoint","title":"Artillery Metrics by Endpoint Plugin","description":"The `artillery-plugin-metrics-by-endpoint` package extends Artillery, a powerful load testing tool, by providing granular, per-endpoint breakdown of latency and HTTP response codes. Unlike Artillery's default behavior, which aggregates performance metrics across all endpoints, this plugin enables users to view statistics (e.g., p50, p95, p99 response times, min/max latency, and status code counts) for each unique URL or named request within their HTTP tests. The current stable version is 1.24.0, with releases typically aligning with updates to the main Artillery monorepo, where the plugin's code now resides. Its key differentiator is the ability to offer deep insights into individual endpoint performance, crucial for identifying bottlenecks in complex microservice architectures or APIs with many routes. It offers configuration options to intelligently group metrics for dynamic URLs, providing clearer reports.","status":"active","version":"1.24.0","language":"javascript","source_language":"en","source_url":null,"tags":["javascript"],"install":[{"cmd":"npm install artillery-plugin-metrics-by-endpoint","lang":"bash","label":"npm"},{"cmd":"yarn add artillery-plugin-metrics-by-endpoint","lang":"bash","label":"yarn"},{"cmd":"pnpm add artillery-plugin-metrics-by-endpoint","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"This is an Artillery plugin and requires Artillery to run. It typically expects a compatible Artillery core version.","package":"artillery","optional":false}],"imports":[{"note":"Artillery plugins are activated via YAML configuration in the test script, not through direct JavaScript imports. The `metrics-by-endpoint` key corresponds to the npm package name.","wrong":"import { MetricsByEndpointPlugin } from 'artillery-plugin-metrics-by-endpoint';","symbol":"Plugin Activation","correct":"config:\n  plugins:\n    metrics-by-endpoint: {}"},{"note":"Plugin-specific options like `useOnlyRequestNames` or `stripQueryString` are configured directly under the plugin's entry in the `config.plugins` section of the Artillery YAML test script. There is no public JavaScript API for end-user configuration.","wrong":"// No direct JS import for configuration is typically used by end-users.","symbol":"Configuration Options","correct":"config:\n  plugins:\n    metrics-by-endpoint:\n      useOnlyRequestNames: true\n      stripQueryString: true"},{"note":"To leverage `useOnlyRequestNames`, define a `name` property on your HTTP requests within the scenario flow. This explicitly tells the plugin how to group metrics, especially for dynamic URLs, providing more stable reporting.","wrong":"// No direct JS import pattern for this concept.","symbol":"Defining Request Names","correct":"- get:\n    url: '/users/{{ userId }}'\n    name: 'Get User Profile'"}],"quickstart":{"code":"config:\n  target: 'https://api.example.com'\n  phases:\n    - duration: 60\n      arrivalRate: 10\n      name: 'Warm up traffic'\n\n  plugins:\n    metrics-by-endpoint:\n      useOnlyRequestNames: true # Aggregate metrics by 'name' property of requests\n      stripQueryString: true    # Ignore query parameters when determining endpoint identity\n\n  scenarios:\n    - name: 'User Scenario with Endpoint Metrics'\n      flow:\n        - get:\n            url: '/status'\n            name: 'Check API Status'\n        - post:\n            url: '/users'\n            name: 'Create New User'\n            json:\n              username: 'user_{{ $uuid }}'\n              email: 'user_{{ $uuid }}@example.com'\n            capture:\n              json: '$.id'\n              as: 'userId'\n        - get:\n            url: '/users/{{ userId }}'\n            name: 'Retrieve User Profile'\n        - put:\n            url: '/users/{{ userId }}'\n            name: 'Update User Profile'\n            json:\n              status: 'active'","lang":"yaml","description":"This Artillery YAML script demonstrates how to enable the `metrics-by-endpoint` plugin and configure it to report metrics based on explicit request names, while stripping query strings for better aggregation. It includes a multi-step scenario with named HTTP requests, ensuring granular performance data for each defined endpoint."},"warnings":[{"fix":"Upgrade Artillery to a recent stable version (e.g., `npm install -g artillery@latest`) and ensure `artillery-plugin-metrics-by-endpoint` is also at its latest version (`npm install artillery-plugin-metrics-by-endpoint`). If Artillery is installed locally, install the plugin locally too.","message":"As of Artillery v2 (2.0.0-beta.x and later), there were significant internal changes. While this plugin is now integrated into the main Artillery monorepo, ensure your `artillery` and `artillery-plugin-metrics-by-endpoint` versions are compatible, especially if you are using older Artillery versions.","severity":"breaking","affected_versions":">=2.0.0-beta"},{"fix":"Configure `stripQueryString: true` to ignore query parameters, and/or `useOnlyRequestNames: true` (recommended) to group metrics based on the `name` property defined for requests in your scenario. Set `groupDynamicURLs: false` to ensure dynamic parts of the URL are still considered unique if `useOnlyRequestNames` isn't fully comprehensive.","message":"By default, the plugin treats each unique URL, including query parameters, as a separate endpoint. This can lead to an explosion of metrics for dynamic URLs (e.g., `/item?id=1`, `/item?id=2`), making reports unmanageable.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Explicitly add a `name` property to *all* requests for which you desire per-endpoint metrics when `useOnlyRequestNames: true`. Consider setting `reportNoNameRequests: false` if you strictly only want metrics for explicitly named requests.","message":"If `useOnlyRequestNames: true` is set, but some requests in your scenario do not have a `name` property defined, the plugin might still fall back to using the full request path as the metric name, contrary to the expectation that only named requests would be reported or that unnamed requests would be skipped.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"If Artillery is installed globally (`npm install -g artillery`), install the plugin globally (`npm install -g artillery-plugin-metrics-by-endpoint`). If Artillery is a local project dependency, install the plugin as a local dev dependency (`npm install --save-dev artillery-plugin-metrics-by-endpoint`).","message":"Artillery plugins must be installed in the same scope (global or local) as Artillery itself. Mismatched installations can lead to the plugin not being found or loaded correctly.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure `artillery-plugin-metrics-by-endpoint` is installed in the same manner as your Artillery installation. If Artillery is global, install the plugin globally (`npm install -g artillery-plugin-metrics-by-endpoint`). If Artillery is a local project dependency, install the plugin locally (`npm install --save-dev artillery-plugin-metrics-by-endpoint`).","cause":"Artillery cannot find the plugin package. This usually means the plugin was installed in a different npm scope (global vs. local) than Artillery, or it was not installed at all.","error":"WARNING: Plugin metrics-by-endpoint specified but module artillery-plugin-metrics-by-endpoint could not be found (MODULE_NOT_FOUND)"},{"fix":"Add `useOnlyRequestNames: true` and define `name` properties for your requests in the Artillery scenario. For dynamic path segments, ensure your `name` is consistent across those requests. If query parameters are causing the issue, add `stripQueryString: true`.","cause":"The plugin's default behavior treats each unique URL string as a separate endpoint. Without specific configuration, dynamic path segments or query parameters result in separate metric entries.","error":"Metrics for dynamic URLs are not grouping correctly; I see many distinct endpoints for what should be one logical endpoint (e.g., /users/1, /users/2, etc.)"},{"fix":"Ensure *all* requests you want metrics for have an explicit `name` property. Additionally, you can set `reportNoNameRequests: false` in the plugin configuration to explicitly prevent metrics from being reported for requests that do not have a `name` field.","cause":"Even with `useOnlyRequestNames: true`, if a request lacks a `name`, the plugin may still fall back to using the full URL path, which can be unexpected.","error":"I expected the plugin to only show metrics for requests with an explicit 'name' property when `useOnlyRequestNames` is true, but it's still showing metrics for unnamed requests."}],"ecosystem":"npm","meta_description":null}