blob: 6e0e40968ed50f4ee57fc94dcca54afaf5fcbf05 [file] [log] [blame]
"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[6167],{15680:(e,t,a)=>{a.d(t,{xA:()=>p,yg:()=>c});var n=a(96540);function r(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function i(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function o(e){for(var t=1;t<arguments.length;t++){var a=null!=arguments[t]?arguments[t]:{};t%2?i(Object(a),!0).forEach((function(t){r(e,t,a[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):i(Object(a)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(a,t))}))}return e}function l(e,t){if(null==e)return{};var a,n,r=function(e,t){if(null==e)return{};var a,n,r={},i=Object.keys(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||(r[a]=e[a]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n<i.length;n++)a=i[n],t.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var s=n.createContext({}),g=function(e){var t=n.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},p=function(e){var t=g(e.components);return n.createElement(s.Provider,{value:t},e.children)},u="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},d=n.forwardRef((function(e,t){var a=e.components,r=e.mdxType,i=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),u=g(a),d=r,c=u["".concat(s,".").concat(d)]||u[d]||m[d]||i;return a?n.createElement(c,o(o({ref:t},p),{},{components:a})):n.createElement(c,o({ref:t},p))}));function c(e,t){var a=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=a.length,o=new Array(i);o[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:r,o[1]=l;for(var g=2;g<i;g++)o[g]=a[g];return n.createElement.apply(null,o)}return n.createElement.apply(null,a)}d.displayName="MDXCreateElement"},19405:(e,t,a)=>{a.r(t),a.d(t,{assets:()=>p,contentTitle:()=>s,default:()=>c,frontMatter:()=>l,metadata:()=>g,toc:()=>u});var n=a(58168),r=a(98587),i=(a(96540),a(15680)),o=["components"],l={id:"spectator-histogram",title:"Spectator Histogram module"},s=void 0,g={unversionedId:"development/extensions-contrib/spectator-histogram",id:"development/extensions-contrib/spectator-histogram",title:"Spectator Histogram module",description:"\x3c!--",source:"@site/docs/29.0.0/development/extensions-contrib/spectator-histogram.md",sourceDirName:"development/extensions-contrib",slug:"/development/extensions-contrib/spectator-histogram",permalink:"/docs/29.0.0/development/extensions-contrib/spectator-histogram",draft:!1,tags:[],version:"current",frontMatter:{id:"spectator-histogram",title:"Spectator Histogram module"}},p={},u=[{value:"Summary",id:"summary",level:2},{value:"Background",id:"background",level:2},{value:"Limitations",id:"limitations",level:2},{value:"Functionality",id:"functionality",level:2},{value:"Loading the extension",id:"loading-the-extension",level:2},{value:"Aggregators",id:"aggregators",level:2},{value:"<code>spectatorHistogram</code> aggregator",id:"spectatorhistogram-aggregator",level:3},{value:"<code>longSum</code>, <code>doubleSum</code> and <code>floatSum</code> aggregators",id:"longsum-doublesum-and-floatsum-aggregators",level:3},{value:"Post Aggregators",id:"post-aggregators",level:2},{value:"Percentile (singular)",id:"percentile-singular",level:3},{value:"Percentiles (multiple)",id:"percentiles-multiple",level:3},{value:"Examples",id:"examples",level:2},{value:"Example Ingestion Spec",id:"example-ingestion-spec",level:3},{value:"Example Query",id:"example-query",level:3},{value:"Histogram bucket boundaries",id:"histogram-bucket-boundaries",level:2}],m={toc:u},d="wrapper";function c(e){var t=e.components,l=(0,r.A)(e,o);return(0,i.yg)(d,(0,n.A)({},m,l,{components:t,mdxType:"MDXLayout"}),(0,i.yg)("h2",{id:"summary"},"Summary"),(0,i.yg)("p",null,"This module provides Apache Druid approximate histogram aggregators and percentile\npost-aggregators based on Spectator fixed-bucket histograms."),(0,i.yg)("p",null,"Consider SpectatorHistogram to compute percentile approximations. This extension has a reduced storage footprint compared to the ",(0,i.yg)("a",{parentName:"p",href:"/docs/29.0.0/development/extensions-core/datasketches-extension"},"DataSketches extension"),", which results in smaller segment sizes, faster loading from deep storage, and lower memory usage. This extension provides fast and accurate queries on large datasets at low storage cost."),(0,i.yg)("p",null,"This aggregator only applies when your raw data contains positive long integer values. Do not use this aggregator if you have negative values in your data."),(0,i.yg)("p",null,"In the Druid instance shown below, the example Wikipedia dataset is loaded 3 times."),(0,i.yg)("ul",null,(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("inlineCode",{parentName:"li"},"wikipedia")," contains the dataset ingested as is, without rollup"),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("inlineCode",{parentName:"li"},"wikipedia_spectator")," contains the dataset with a single extra metric column of type ",(0,i.yg)("inlineCode",{parentName:"li"},"spectatorHistogram")," for the ",(0,i.yg)("inlineCode",{parentName:"li"},"added")," column"),(0,i.yg)("li",{parentName:"ul"},(0,i.yg)("inlineCode",{parentName:"li"},"wikipedia_datasketch")," contains the dataset with a single extra metric column of type ",(0,i.yg)("inlineCode",{parentName:"li"},"quantilesDoublesSketch")," for the ",(0,i.yg)("inlineCode",{parentName:"li"},"added")," column")),(0,i.yg)("p",null,"Spectator histograms average just 6 extra bytes per row, while the ",(0,i.yg)("inlineCode",{parentName:"p"},"quantilesDoublesSketch"),"\nadds 48 bytes per row. This represents an eightfold reduction in additional storage size for spectator histograms."),(0,i.yg)("p",null,(0,i.yg)("img",{alt:"Comparison of datasource sizes in web console",src:a(97257).A,width:"689",height:"225"})),(0,i.yg)("p",null,"As rollup improves, so does the size savings. For example, when you ingest the Wikipedia dataset\nwith day-grain query granularity and remove all dimensions except ",(0,i.yg)("inlineCode",{parentName:"p"},"countryName"),",\nthis results in a segment that has just 106 rows. The base segment has 87 bytes per row.\nCompare the following bytes per row for SpectatorHistogram versus DataSketches:"),(0,i.yg)("ul",null,(0,i.yg)("li",{parentName:"ul"},"An additional ",(0,i.yg)("inlineCode",{parentName:"li"},"spectatorHistogram")," column adds 27 bytes per row on average."),(0,i.yg)("li",{parentName:"ul"},"An additional ",(0,i.yg)("inlineCode",{parentName:"li"},"quantilesDoublesSketch")," column adds 255 bytes per row.")),(0,i.yg)("p",null,"SpectatorHistogram reduces the additional storage size by 9.4 times in this example.\nStorage gains will differ per dataset depending on the variance and rollup of the data."),(0,i.yg)("h2",{id:"background"},"Background"),(0,i.yg)("p",null,(0,i.yg)("a",{parentName:"p",href:"https://netflix.github.io/atlas-docs/spectator/"},"Spectator")," is a simple library\nfor instrumenting code to record dimensional time series data.\nIt was built, primarily, to work with ",(0,i.yg)("a",{parentName:"p",href:"https://netflix.github.io/atlas-docs/"},"Atlas"),".\nAtlas was developed by Netflix to manage dimensional time series data for near\nreal-time operational insight."),(0,i.yg)("p",null,"With the ",(0,i.yg)("a",{parentName:"p",href:"https://github.com/Netflix-Skunkworks/iep-apps/tree/main/atlas-druid"},"Atlas-Druid"),"\nservice, it's possible to use the power of Atlas queries, backed by Druid as a\ndata store to benefit from high-dimensionality and high-cardinality data."),(0,i.yg)("p",null,"SpectatorHistogram is designed for efficient parallel aggregations while still\nallowing for filtering and grouping by dimensions.\nIt provides similar functionality to the built-in DataSketches ",(0,i.yg)("inlineCode",{parentName:"p"},"quantilesDoublesSketch")," aggregator, but is\nopinionated to maintain higher absolute accuracy at smaller values.\nLarger values have lower absolute accuracy; however, relative accuracy is maintained across the range.\nSee ",(0,i.yg)("a",{parentName:"p",href:"#histogram-bucket-boundaries"},"Bucket boundaries")," for more information.\nThe SpectatorHistogram is optimized for typical measurements from cloud services and web apps,\nsuch as page load time, transferred bytes, response time, and request latency."),(0,i.yg)("p",null,"Through some trade-offs SpectatorHistogram provides a significantly more compact\nrepresentation with the same aggregation performance and accuracy as\nDataSketches Quantiles Sketch. Note that results depend on the dataset.\nAlso see the ","[limitations]","(#limitations] of this extension."),(0,i.yg)("h2",{id:"limitations"},"Limitations"),(0,i.yg)("ul",null,(0,i.yg)("li",{parentName:"ul"},"Supports positive long integer values within the range of [0, 2^53). Negatives are\ncoerced to 0."),(0,i.yg)("li",{parentName:"ul"},"Does not support decimals."),(0,i.yg)("li",{parentName:"ul"},"Does not support Druid SQL queries, only native queries."),(0,i.yg)("li",{parentName:"ul"},"Does not support vectorized queries."),(0,i.yg)("li",{parentName:"ul"},"Generates 276 fixed buckets with increasing bucket widths. In practice, the observed error of computed percentiles ranges from 0.1% to 3%, exclusive. See ",(0,i.yg)("a",{parentName:"li",href:"#histogram-bucket-boundaries"},"Bucket boundaries")," for the full list of bucket boundaries.")),(0,i.yg)("admonition",{type:"tip"},(0,i.yg)("p",{parentName:"admonition"},"If these limitations don't work for your use case, then use ",(0,i.yg)("a",{parentName:"p",href:"/docs/29.0.0/development/extensions-core/datasketches-extension"},"DataSketches")," instead.")),(0,i.yg)("h2",{id:"functionality"},"Functionality"),(0,i.yg)("p",null,"The SpectatorHistogram aggregator can generate histograms from raw numeric\nvalues as well as aggregating or combining pre-aggregated histograms generated using\nthe SpectatorHistogram aggregator itself.\nWhile you can generate histograms on the fly at query time, it is generally more\nperformant to generate histograms during ingestion and then combine them at\nquery time. This is especially true where rollup is enabled. It may be misleading or\nincorrect to generate histograms from already rolled-up summed data."),(0,i.yg)("p",null,"The module provides postAggregators, ",(0,i.yg)("inlineCode",{parentName:"p"},"percentileSpectatorHistogram")," (singular) and\n",(0,i.yg)("inlineCode",{parentName:"p"},"percentilesSpectatorHistogram")," (plural), to compute approximate\npercentiles from histograms generated by the SpectatorHistogram aggregator.\nAgain, these postAggregators can be used to compute percentiles from raw numeric\nvalues via the SpectatorHistogram aggregator or from pre-aggregated histograms."),(0,i.yg)("blockquote",null,(0,i.yg)("p",{parentName:"blockquote"},"If you're only using the aggregator to compute percentiles from raw numeric values,\nthen you can use the built-in quantilesDoublesSketch aggregator instead. The performance\nand accuracy are comparable. However, the DataSketches aggregator supports negative values,\nand you don't need to download an additional extension.")),(0,i.yg)("p",null,"An aggregated SpectatorHistogram can also be queried using a ",(0,i.yg)("inlineCode",{parentName:"p"},"longSum")," or ",(0,i.yg)("inlineCode",{parentName:"p"},"doubleSum"),"\naggregator to retrieve the population of the histogram. This is effectively the count\nof the number of values that were aggregated into the histogram. This flexibility can\navoid the need to maintain a separate metric for the count of values."),(0,i.yg)("p",null,"For high-frequency measurements, you may need to pre-aggregate data at the client prior\nto sending into Druid. For example, if you're measuring individual image render times\non an image-heavy website, you may want to aggregate the render times for a page-view\ninto a single histogram prior to sending to Druid in real-time. This can reduce the\namount of data that's needed to send from the client across the wire."),(0,i.yg)("p",null,"SpectatorHistogram supports ingesting pre-aggregated histograms in real-time and batch.\nThey can be sent as a JSON map, keyed by the spectator bucket ID and the value is the\ncount of values. This is the same format as the serialized JSON representation of the\nhistogram. The keys need not be ordered or contiguous. For example:"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-json"},'{ "4": 8, "5": 15, "6": 37, "7": 9, "8": 3, "10": 1, "13": 1 }\n')),(0,i.yg)("h2",{id:"loading-the-extension"},"Loading the extension"),(0,i.yg)("p",null,"To use SpectatorHistogram, make sure you ",(0,i.yg)("a",{parentName:"p",href:"/docs/29.0.0/configuration/extensions#loading-extensions"},"include")," the extension in your config file:"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre"},'druid.extensions.loadList=["druid-spectator-histogram"]\n')),(0,i.yg)("h2",{id:"aggregators"},"Aggregators"),(0,i.yg)("p",null,"The result of the aggregation is a histogram that is built by ingesting numeric values from\nthe raw data, or from combining pre-aggregated histograms. The result is represented in\nJSON format where the keys are the bucket index and the values are the count of entries\nin that bucket."),(0,i.yg)("p",null,"The buckets are defined as per the Spectator ",(0,i.yg)("a",{parentName:"p",href:"https://github.com/Netflix/spectator/blob/main/spectator-api/src/main/java/com/netflix/spectator/api/histogram/PercentileBuckets.java"},"PercentileBuckets")," specification.\nSee ",(0,i.yg)("a",{parentName:"p",href:"#histogram-bucket-boundaries"},"Histogram bucket boundaries")," for the full list of bucket boundaries."),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-js"}," // The set of buckets is generated by using powers of 4 and incrementing by one-third of the\n // previous power of 4 in between as long as the value is less than the next power of 4 minus\n // the delta.\n //\n // Base: 1, 2, 3\n //\n // 4 (4^1), delta = 1 (~1/3 of 4)\n // 5, 6, 7, ..., 14,\n //\n // 16 (4^2), delta = 5 (~1/3 of 16)\n // 21, 26, 31, ..., 56,\n //\n // 64 (4^3), delta = 21 (~1/3 of 64)\n // ...\n")),(0,i.yg)("p",null,"There are multiple aggregator types included, all of which are based on the same\nunderlying implementation. If you use the Atlas-Druid service, the different types\nsignal the service on how to handle the resulting data from a query."),(0,i.yg)("ul",null,(0,i.yg)("li",{parentName:"ul"},"spectatorHistogramTimer signals that the histogram is representing\na collection of timer values. It is recommended to normalize timer values to nanoseconds\nat, or prior to, ingestion. If queried via the Atlas-Druid service, it will\nnormalize timers to second resolution at query time as a more natural unit of time\nfor human consumption."),(0,i.yg)("li",{parentName:"ul"},"spectatorHistogram and spectatorHistogramDistribution are generic histograms that\ncan be used to represent any measured value without units. No normalization is\nrequired or performed.")),(0,i.yg)("h3",{id:"spectatorhistogram-aggregator"},(0,i.yg)("inlineCode",{parentName:"h3"},"spectatorHistogram")," aggregator"),(0,i.yg)("p",null,"Alias: ",(0,i.yg)("inlineCode",{parentName:"p"},"spectatorHistogramDistribution"),", ",(0,i.yg)("inlineCode",{parentName:"p"},"spectatorHistogramTimer")),(0,i.yg)("p",null,"To aggregate at query time:"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre"},'{\n "type" : "spectatorHistogram",\n "name" : <output_name>,\n "fieldName" : <column_name>\n }\n')),(0,i.yg)("table",null,(0,i.yg)("thead",{parentName:"table"},(0,i.yg)("tr",{parentName:"thead"},(0,i.yg)("th",{parentName:"tr",align:null},"Property"),(0,i.yg)("th",{parentName:"tr",align:null},"Description"),(0,i.yg)("th",{parentName:"tr",align:null},"Required?"))),(0,i.yg)("tbody",{parentName:"table"},(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"type"),(0,i.yg)("td",{parentName:"tr",align:null},'This String must be one of "spectatorHistogram", "spectatorHistogramTimer", "spectatorHistogramDistribution"'),(0,i.yg)("td",{parentName:"tr",align:null},"yes")),(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"name"),(0,i.yg)("td",{parentName:"tr",align:null},"A String for the output (result) name of the aggregation."),(0,i.yg)("td",{parentName:"tr",align:null},"yes")),(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"fieldName"),(0,i.yg)("td",{parentName:"tr",align:null},"A String for the name of the input field containing raw numeric values or pre-aggregated histograms."),(0,i.yg)("td",{parentName:"tr",align:null},"yes")))),(0,i.yg)("h3",{id:"longsum-doublesum-and-floatsum-aggregators"},(0,i.yg)("inlineCode",{parentName:"h3"},"longSum"),", ",(0,i.yg)("inlineCode",{parentName:"h3"},"doubleSum")," and ",(0,i.yg)("inlineCode",{parentName:"h3"},"floatSum")," aggregators"),(0,i.yg)("p",null,"To get the population size (count of events contributing to the histogram):"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre"},'{\n "type" : "longSum",\n "name" : <output_name>,\n "fieldName" : <column_name_of_aggregated_histogram>\n }\n')),(0,i.yg)("table",null,(0,i.yg)("thead",{parentName:"table"},(0,i.yg)("tr",{parentName:"thead"},(0,i.yg)("th",{parentName:"tr",align:null},"Property"),(0,i.yg)("th",{parentName:"tr",align:null},"Description"),(0,i.yg)("th",{parentName:"tr",align:null},"Required?"))),(0,i.yg)("tbody",{parentName:"table"},(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"type"),(0,i.yg)("td",{parentName:"tr",align:null},'Must be "longSum", "doubleSum", or "floatSum".'),(0,i.yg)("td",{parentName:"tr",align:null},"yes")),(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"name"),(0,i.yg)("td",{parentName:"tr",align:null},"A String for the output (result) name of the aggregation."),(0,i.yg)("td",{parentName:"tr",align:null},"yes")),(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"fieldName"),(0,i.yg)("td",{parentName:"tr",align:null},"A String for the name of the input field containing pre-aggregated histograms."),(0,i.yg)("td",{parentName:"tr",align:null},"yes")))),(0,i.yg)("h2",{id:"post-aggregators"},"Post Aggregators"),(0,i.yg)("h3",{id:"percentile-singular"},"Percentile (singular)"),(0,i.yg)("p",null,"This returns a single percentile calculation based on the distribution of the values in the aggregated histogram."),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre"},'{\n "type": "percentileSpectatorHistogram",\n "name": <output name>,\n "field": {\n "type": "fieldAccess",\n "fieldName": <name of aggregated SpectatorHistogram>\n },\n "percentile": <decimal percentile, e.g. 50.0 for median>\n}\n')),(0,i.yg)("table",null,(0,i.yg)("thead",{parentName:"table"},(0,i.yg)("tr",{parentName:"thead"},(0,i.yg)("th",{parentName:"tr",align:null},"Property"),(0,i.yg)("th",{parentName:"tr",align:null},"Description"),(0,i.yg)("th",{parentName:"tr",align:null},"Required?"))),(0,i.yg)("tbody",{parentName:"table"},(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"type"),(0,i.yg)("td",{parentName:"tr",align:null},'This String should always be "percentileSpectatorHistogram"'),(0,i.yg)("td",{parentName:"tr",align:null},"yes")),(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"name"),(0,i.yg)("td",{parentName:"tr",align:null},"A String for the output (result) name of the calculation."),(0,i.yg)("td",{parentName:"tr",align:null},"yes")),(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"field"),(0,i.yg)("td",{parentName:"tr",align:null},"A field reference pointing to the aggregated histogram."),(0,i.yg)("td",{parentName:"tr",align:null},"yes")),(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"percentile"),(0,i.yg)("td",{parentName:"tr",align:null},"A single decimal percentile between 0.0 and 100.0"),(0,i.yg)("td",{parentName:"tr",align:null},"yes")))),(0,i.yg)("h3",{id:"percentiles-multiple"},"Percentiles (multiple)"),(0,i.yg)("p",null,"This returns an array of percentiles corresponding to those requested."),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre"},'{\n "type": "percentilesSpectatorHistogram",\n "name": <output name>,\n "field": {\n "type": "fieldAccess",\n "fieldName": <name of aggregated SpectatorHistogram>\n },\n "percentiles": [25, 50, 75, 99.5]\n}\n')),(0,i.yg)("blockquote",null,(0,i.yg)("p",{parentName:"blockquote"},"It's more efficient to request multiple percentiles in a single query\nthan to request individual percentiles in separate queries. This array-based\nhelper is provided for convenience and has a marginal performance benefit over\nusing the singular percentile post-aggregator multiple times within a query.\nThe more expensive part of the query is the aggregation of the histogram.\nThe post-aggregation calculations all happen on the same aggregated histogram.")),(0,i.yg)("p",null,"The results contain arrays matching the length and order of the requested\narray of percentiles."),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre"},'"percentilesAdded": [\n 0.5504911679884643, // 25th percentile\n 4.013975155279504, // 50th percentile \n 78.89518317503394, // 75th percentile\n 8580.024999999994 // 99.5th percentile\n]\n')),(0,i.yg)("table",null,(0,i.yg)("thead",{parentName:"table"},(0,i.yg)("tr",{parentName:"thead"},(0,i.yg)("th",{parentName:"tr",align:null},"Property"),(0,i.yg)("th",{parentName:"tr",align:null},"Description"),(0,i.yg)("th",{parentName:"tr",align:null},"Required?"))),(0,i.yg)("tbody",{parentName:"table"},(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"type"),(0,i.yg)("td",{parentName:"tr",align:null},'This String should always be "percentilesSpectatorHistogram"'),(0,i.yg)("td",{parentName:"tr",align:null},"yes")),(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"name"),(0,i.yg)("td",{parentName:"tr",align:null},"A String for the output (result) name of the calculation."),(0,i.yg)("td",{parentName:"tr",align:null},"yes")),(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"field"),(0,i.yg)("td",{parentName:"tr",align:null},"A field reference pointing to the aggregated histogram."),(0,i.yg)("td",{parentName:"tr",align:null},"yes")),(0,i.yg)("tr",{parentName:"tbody"},(0,i.yg)("td",{parentName:"tr",align:null},"percentiles"),(0,i.yg)("td",{parentName:"tr",align:null},"Non-empty array of decimal percentiles between 0.0 and 100.0"),(0,i.yg)("td",{parentName:"tr",align:null},"yes")))),(0,i.yg)("h2",{id:"examples"},"Examples"),(0,i.yg)("h3",{id:"example-ingestion-spec"},"Example Ingestion Spec"),(0,i.yg)("p",null,"Example of ingesting the sample Wikipedia dataset with a histogram metric column:"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-json"},'{\n "type": "index_parallel",\n "spec": {\n "ioConfig": {\n "type": "index_parallel",\n "inputSource": {\n "type": "http",\n "uris": ["https://druid.apache.org/data/wikipedia.json.gz"]\n },\n "inputFormat": { "type": "json" }\n },\n "dataSchema": {\n "granularitySpec": {\n "segmentGranularity": "day",\n "queryGranularity": "minute",\n "rollup": true\n },\n "dataSource": "wikipedia",\n "timestampSpec": { "column": "timestamp", "format": "iso" },\n "dimensionsSpec": {\n "dimensions": [\n "isRobot",\n "channel",\n "flags",\n "isUnpatrolled",\n "page",\n "diffUrl",\n "comment",\n "isNew",\n "isMinor",\n "isAnonymous",\n "user",\n "namespace",\n "cityName",\n "countryName",\n "regionIsoCode",\n "metroCode",\n "countryIsoCode",\n "regionName"\n ]\n },\n "metricsSpec": [\n { "name": "count", "type": "count" },\n { "name": "sum_added", "type": "longSum", "fieldName": "added" },\n {\n "name": "hist_added",\n "type": "spectatorHistogram",\n "fieldName": "added"\n }\n ]\n },\n "tuningConfig": {\n "type": "index_parallel",\n "partitionsSpec": { "type": "hashed" },\n "forceGuaranteedRollup": true\n }\n }\n}\n')),(0,i.yg)("h3",{id:"example-query"},"Example Query"),(0,i.yg)("p",null,"Example query using the sample Wikipedia dataset:"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-json"},'{\n "queryType": "timeseries",\n "dataSource": {\n "type": "table",\n "name": "wikipedia"\n },\n "intervals": {\n "type": "intervals",\n "intervals": [\n "0000-01-01/9999-12-31"\n ]\n },\n "granularity": {\n "type": "all"\n },\n "aggregations": [\n {\n "type": "spectatorHistogram",\n "name": "histogram_added",\n "fieldName": "added"\n }\n ],\n "postAggregations": [\n {\n "type": "percentileSpectatorHistogram",\n "name": "medianAdded",\n "field": {\n "type": "fieldAccess",\n "fieldName": "histogram_added"\n },\n "percentile": "50.0"\n }\n ]\n}\n')),(0,i.yg)("p",null,"Results in"),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-json"},'[\n {\n "result": {\n "histogram_added": {\n "0": 11096, "1": 632, "2": 297, "3": 187, "4": 322, "5": 161,\n "6": 174, "7": 127, "8": 125, "9": 162, "10": 123, "11": 106,\n "12": 95, "13": 104, "14": 95, "15": 588, "16": 540, "17": 690,\n "18": 719, "19": 478, "20": 288, "21": 250, "22": 219, "23": 224,\n "24": 737, "25": 424, "26": 343, "27": 266, "28": 232, "29": 217,\n "30": 171, "31": 164, "32": 161, "33": 530, "34": 339, "35": 236,\n "36": 181, "37": 152, "38": 113, "39": 128, "40": 80, "41": 75,\n "42": 289, "43": 145, "44": 138, "45": 83, "46": 45, "47": 46,\n "48": 64, "49": 65, "50": 71, "51": 421, "52": 525, "53": 59,\n "54": 31, "55": 35, "56": 8, "57": 10, "58": 5, "59": 4, "60": 11,\n "61": 10, "62": 5, "63": 2, "64": 2, "65": 1, "67": 1, "68": 1,\n "69": 1, "70": 1, "71": 1, "78": 2\n },\n "medianAdded": 4.013975155279504\n },\n "timestamp": "2016-06-27T00:00:00.000Z"\n }\n]\n')),(0,i.yg)("h2",{id:"histogram-bucket-boundaries"},"Histogram bucket boundaries"),(0,i.yg)("p",null,"The following array lists the upper bounds of each bucket index. There are 276 buckets in total.\nThe first bucket index is 0 and the last bucket index is 275.\nThe bucket widths increase as the bucket index increases. This leads to a greater absolute error for larger values, but maintains a relative error of rough percentage across the number range.\nFor example, the maximum error at value 10 is zero since the bucket width is 1 (the difference of ",(0,i.yg)("inlineCode",{parentName:"p"},"11-10"),"). For a value of 16,000,000,000, the bucket width is 1,431,655,768 (from ",(0,i.yg)("inlineCode",{parentName:"p"},"17179869184-15748213416"),"). This gives an error of up to ~8.9%, from ",(0,i.yg)("inlineCode",{parentName:"p"},"1,431,655,768/16,000,000,000*100"),". In practice, the observed error of computed percentiles is in the range of (0.1%, 3%)."),(0,i.yg)("pre",null,(0,i.yg)("code",{parentName:"pre",className:"language-json"},"[\n 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 21, 26, 31, 36, 41, 46,\n 51, 56, 64, 85, 106, 127, 148, 169, 190, 211, 232, 256, 341, 426, 511, 596,\n 681, 766, 851, 936, 1024, 1365, 1706, 2047, 2388, 2729, 3070, 3411, 3752,\n 4096, 5461, 6826, 8191, 9556, 10921, 12286, 13651, 15016, 16384, 21845,\n 27306, 32767, 38228, 43689, 49150, 54611, 60072, 65536, 87381, 109226,\n 131071, 152916, 174761, 196606, 218451, 240296, 262144, 349525, 436906,\n 524287, 611668, 699049, 786430, 873811, 961192, 1048576, 1398101, 1747626,\n 2097151, 2446676, 2796201, 3145726, 3495251, 3844776, 4194304, 5592405,\n 6990506, 8388607, 9786708, 11184809, 12582910, 13981011, 15379112, 16777216,\n 22369621, 27962026, 33554431, 39146836, 44739241, 50331646, 55924051,\n 61516456, 67108864, 89478485, 111848106, 134217727, 156587348, 178956969,\n 201326590, 223696211, 246065832, 268435456, 357913941, 447392426, 536870911,\n 626349396, 715827881, 805306366, 894784851, 984263336, 1073741824, 1431655765,\n 1789569706, 2147483647, 2505397588, 2863311529, 3221225470, 3579139411,\n 3937053352, 4294967296, 5726623061, 7158278826, 8589934591, 10021590356,\n 11453246121, 12884901886, 14316557651, 15748213416, 17179869184, 22906492245,\n 28633115306, 34359738367, 40086361428, 45812984489, 51539607550, 57266230611,\n 62992853672, 68719476736, 91625968981, 114532461226, 137438953471,\n 160345445716, 183251937961, 206158430206, 229064922451, 251971414696,\n 274877906944, 366503875925, 458129844906, 549755813887, 641381782868,\n 733007751849, 824633720830, 916259689811, 1007885658792, 1099511627776,\n 1466015503701, 1832519379626, 2199023255551, 2565527131476, 2932031007401,\n 3298534883326, 3665038759251, 4031542635176, 4398046511104, 5864062014805,\n 7330077518506, 8796093022207, 10262108525908, 11728124029609, 13194139533310,\n 14660155037011, 16126170540712, 17592186044416, 23456248059221,\n 29320310074026, 35184372088831, 41048434103636, 46912496118441,\n 52776558133246, 58640620148051, 64504682162856, 70368744177664,\n 93824992236885, 117281240296106, 140737488355327, 164193736414548,\n 187649984473769, 211106232532990, 234562480592211, 258018728651432,\n 281474976710656, 375299968947541, 469124961184426, 562949953421311,\n 656774945658196, 750599937895081, 844424930131966, 938249922368851,\n 1032074914605736, 1125899906842624, 1501199875790165, 1876499844737706,\n 2251799813685247, 2627099782632788, 3002399751580329, 3377699720527870,\n 3752999689475411, 4128299658422952, 4503599627370496, 6004799503160661,\n 7505999378950826, 9007199254740991, 10508399130531156, 12009599006321321,\n 13510798882111486, 15011998757901651, 16513198633691816, 18014398509481984,\n 24019198012642645, 30023997515803306, 36028797018963967, 42033596522124628,\n 48038396025285289, 54043195528445950, 60047995031606611, 66052794534767272,\n 72057594037927936, 96076792050570581, 120095990063213226, 144115188075855871,\n 168134386088498516, 192153584101141161, 216172782113783806, 240191980126426451,\n 264211178139069096, 288230376151711744, 384307168202282325, 480383960252852906,\n 576460752303423487, 672537544353994068, 768614336404564649, 864691128455135230,\n 960767920505705811, 1056844712556276392, 1152921504606846976, 1537228672809129301,\n 1921535841011411626, 2305843009213693951, 2690150177415976276, 3074457345618258601,\n 3458764513820540926, 3843071682022823251, 4227378850225105576, 9223372036854775807\n]\n")))}c.isMDXComponent=!0},97257:(e,t,a)=>{a.d(t,{A:()=>n});const n=a.p+"assets/images/spectator-histogram-size-comparison-665af4720d1b302515a31f758b824f26.png"}}]);