Add a column split on a boolean valued field.
Add a column split on a boolean valued field.
Name | Type | Description |
---|---|---|
fieldName | String | The name of field to split on. |
trueDisplayValue | String | A string to display in the true valued column label. |
falseDisplayValue | String | A string to display in the false valued column label. |
The updated pivot specification.
addBooleanColumnSplit: function(fieldName, trueDisplayValue, falseDisplayValue) {
if (!this.dataModelObject.fieldByName(fieldName)) {
throw new Error("Did not find field " + fieldName);
}
var f = this.dataModelObject.fieldByName(fieldName);
if ("boolean" !== f.type) {
throw new Error("Field was of type " + f.type + ", expected boolean.");
}
this.columns.push({
fieldName: fieldName,
owner: f.owner,
type: f.type,
trueLabel: trueDisplayValue,
falseLabel: falseDisplayValue
});
return this;
},
Add a row split on a boolean valued field.
Name | Type | Description |
---|---|---|
fieldName | String | The name of field to split on. |
label | String | A human readable name for this set of rows. |
trueDisplayValue | String | A string to display in the true valued row label. |
falseDisplayValue | String | A string to display in the false valued row label. |
The updated pivot specification.
addBooleanRowSplit: function(field, label, trueDisplayValue, falseDisplayValue) {
if (!this.dataModelObject.fieldByName(field)) {
throw new Error("Did not find field " + field);
}
var f = this.dataModelObject.fieldByName(field);
if ("boolean" !== f.type) {
throw new Error("Field was of type " + f.type + ", expected boolean.");
}
this.rows.push({
fieldName: field,
owner: f.owner,
type: f.type,
label: label,
trueLabel: trueDisplayValue,
falseLabel: falseDisplayValue
});
return this;
},
Add an aggregate to each cell of the pivot.
Name | Type | Description |
---|---|---|
fieldName | String | The name of field to aggregate. |
label | String | a human readable name for this aggregate. |
statsFunction | String | The function to use for aggregation, see class docs for valid stats functions. |
The updated pivot specification.
addCellValue: function(fieldName, label, statsFunction) {
if (!this.dataModelObject.hasField(fieldName)) {
throw new Error("Did not find field " + fieldName);
}
var f = this.dataModelObject.fieldByName(fieldName);
if (utils.contains(["string", "ipv4"], f.type) &&
!utils.contains([
"list",
"values",
"first",
"last",
"count",
"dc"], statsFunction)
) {
throw new Error("Stats function on string and IPv4 fields must be one of:" +
" list, distinct_values, first, last, count, or distinct_count; found " +
statsFunction);
}
else if ("number" === f.type &&
!utils.contains([
"sum",
"count",
"average",
"min",
"max",
"stdev",
"list",
"values"
], statsFunction)
) {
throw new Error("Stats function on number field must be must be one of:" +
" sum, count, average, max, min, stdev, list, or distinct_values; found " +
statsFunction
);
}
else if ("timestamp" === f.type &&
!utils.contains([
"duration",
"earliest",
"latest",
"list",
"values"
], statsFunction)
) {
throw new Error("Stats function on timestamp field must be one of:" +
" duration, earliest, latest, list, or distinct values; found " +
statsFunction
);
}
else if (utils.contains(["objectCount", "childCount"], f.type) &&
"count" !== statsFunction
) {
throw new Error("Stats function on childcount and objectcount fields must be count; " +
"found " + statsFunction);
}
else if ("boolean" === f.type) {
throw new Error("Cannot use boolean valued fields as cell values.");
}
this.cells.push({
fieldName: fieldName,
owner: f.lineage.join("."),
type: f.type,
label: label,
sparkline: false, // Not properly implemented in core yet.
value: statsFunction
});
return this;
},
Add a column split on a string or number valued field, producing a column for each distinct value of the field.
Name | Type | Description |
---|---|---|
fieldName | String | The name of field to split on. |
The updated pivot specification.
addColumnSplit: function(fieldName) {
if (!this.dataModelObject.hasField(fieldName)) {
throw new Error("Did not find field " + fieldName);
}
var f = this.dataModelObject.fieldByName(fieldName);
if (!utils.contains(["number", "string"], f.type)) {
throw new Error("Field was of type " + f.type + ", expected number or string.");
}
var col = {
fieldName: fieldName,
owner: f.owner,
type: f.type
};
if ("number" === f.type) {
col.display = "all";
}
this.columns.push(col);
return this;
},
Add a filter on a boolean valued field. The filter will be a constraint of the form field
comparisoncompareTo
, for example: is_remote = false
.
Name | Type | Description |
---|---|---|
fieldName | String | The name of field to filter on |
comparisonType | String | The type of comparison, see class docs for valid types. |
comparisonOp | String | The comparison, see class docs for valid comparisons, based on type. |
compareTo | String | The value to compare the field to. |
The updated pivot specification.
addFilter: function(fieldName, comparisonType, comparisonOp, compareTo) {
if (!this.dataModelObject.hasField(fieldName)) {
throw new Error("Cannot add filter on a nonexistent field.");
}
if (comparisonType !== this.dataModelObject.fieldByName(fieldName).type) {
throw new Error(
"Cannot add " + comparisonType +
" filter on " + fieldName +
" because it is of type " +
this.dataModelObject.fieldByName(fieldName).type);
}
if (!utils.contains(this._comparisons[comparisonType], comparisonOp)) {
throw new Error(
"Cannot add " + comparisonType +
" filter because " + comparisonOp +
" is not a valid comparison operator");
}
var ret = {
fieldName: fieldName,
owner: this.dataModelObject.fieldByName(fieldName).lineage.join("."),
type: comparisonType
};
// These fields are type dependent
if (utils.contains(["boolean", "string", "ipv4", "number"], ret.type)) {
ret.rule = {
comparator: comparisonOp,
compareTo: compareTo
};
}
this.filters.push(ret);
return this;
},
Add a limit on the events shown in a pivot by sorting them according to some field, then taking the specified number from the beginning or end of the list.
Name | Type | Description |
---|---|---|
fieldName | String | The name of field to filter on. |
sortAttribute | String | The name of the field to use for sorting. |
sortDirection | String | The direction to sort events, see class docs for valid types. |
limit | String | The number of values from the sorted list to allow through this filter. |
statsFunction | String | The stats function to use for aggregation before sorting, see class docs for valid types. |
The updated pivot specification.
addLimitFilter: function(fieldName, sortAttribute, sortDirection, limit, statsFunction) {
if (!this.dataModelObject.hasField(fieldName)) {
throw new Error("Cannot add limit filter on a nonexistent field.");
}
var f = this.dataModelObject.fieldByName(fieldName);
if (!utils.contains(["string", "number", "objectCount"], f.type)) {
throw new Error("Cannot add limit filter on " + fieldName + " because it is of type " + f.type);
}
if ("string" === f.type && !utils.contains(["count", "dc"], statsFunction)) {
throw new Error("Stats function for fields of type string must be COUNT or DISTINCT_COUNT; found " +
statsFunction);
}
if ("number" === f.type && !utils.contains(["count", "dc", "average", "sum"], statsFunction)) {
throw new Error("Stats function for fields of type number must be one of COUNT, DISTINCT_COUNT, SUM, or AVERAGE; found " +
statsFunction);
}
if ("objectCount" === f.type && !utils.contains(["count"], statsFunction)) {
throw new Error("Stats function for fields of type object count must be COUNT; found " + statsFunction);
}
var filter = {
fieldName: fieldName,
owner: f.lineage.join("."),
type: f.type,
attributeName: sortAttribute,
attributeOwner: this.dataModelObject.fieldByName(sortAttribute).lineage.join("."),
sortDirection: sortDirection,
limitAmount: limit,
statsFn: statsFunction
};
// Assumed "highest" is preferred for when sortDirection is "DEFAULT"
filter.limitType = "ASCENDING" === sortDirection ? "lowest" : "highest";
this.filters.push(filter);
return this;
},
Add a column split on a numeric field, splitting the values into ranges.
Name | Type | Description |
---|---|---|
fieldName | String | The field to split on. |
options | Object | An optional dictionary of collection filtering and pagination options: |
The updated pivot specification.
addRangeColumnSplit: function(fieldName, ranges) {
if (!this.dataModelObject.hasField(fieldName)) {
throw new Error("Did not find field " + fieldName);
}
var f = this.dataModelObject.fieldByName(fieldName);
if ("number" !== f.type) {
throw new Error("Field was of type " + f.type + ", expected number.");
}
// In Splunk 6.0.1.1, data models incorrectly expect strings for these fields
// instead of numbers. In 6.1, this is fixed and both are accepted.
var updatedRanges = {};
if (!utils.isUndefined(ranges.start) && ranges.start !== null) {
updatedRanges.start = ranges.start;
}
if (!utils.isUndefined(ranges.end) && ranges.end !== null) {
updatedRanges.end = ranges.end;
}
if (!utils.isUndefined(ranges.step) && ranges.step !== null) {
updatedRanges.size = ranges.step;
}
if (!utils.isUndefined(ranges.limit) && ranges.limit !== null) {
updatedRanges.maxNumberOf = ranges.limit;
}
this.columns.push({
fieldName: fieldName,
owner: f.owner,
type: f.type,
display: "ranges",
ranges: updatedRanges
});
return this;
},
Add a row split on a numeric field, splitting into numeric ranges.
This split generates bins with edges equivalent to the classic loop 'for i in
Name | Type | Description |
---|---|---|
fieldName | String | The field to split on. |
label | String | A human readable name for this set of rows. |
options | Object | An optional dictionary of collection filtering and pagination options: |
The updated pivot specification.
addRangeRowSplit: function(field, label, ranges) {
if (!this.dataModelObject.hasField(field)) {
throw new Error("Did not find field " + field);
}
var f = this.dataModelObject.fieldByName(field);
if ("number" !== f.type) {
throw new Error("Field was of type " + f.type + ", expected number.");
}
var updateRanges = {};
if (!utils.isUndefined(ranges.start) && ranges.start !== null) {
updateRanges.start = ranges.start;
}
if (!utils.isUndefined(ranges.end) && ranges.end !== null) {
updateRanges.end = ranges.end;
}
if (!utils.isUndefined(ranges.step) && ranges.step !== null) {
updateRanges.size = ranges.step;
}
if (!utils.isUndefined(ranges.limit) && ranges.limit !== null) {
updateRanges.maxNumberOf = ranges.limit;
}
this.rows.push({
fieldName: field,
owner: f.owner,
type: f.type,
label: label,
display: "ranges",
ranges: updateRanges
});
return this;
},
Add a row split on a numeric or string valued field, splitting on each distinct value of the field.
Name | Type | Description |
---|---|---|
fieldName | String | The name of field to split on. |
label | String | A human readable name for this set of rows. |
The updated pivot specification.
addRowSplit: function(fieldName, label) {
if (!this.dataModelObject.hasField(fieldName)) {
throw new Error("Did not find field " + fieldName);
}
var f = this.dataModelObject.fieldByName(fieldName);
if (!utils.contains(["number", "string"], f.type)) {
throw new Error("Field was of type " + f.type + ", expected number or string.");
}
var row = {
fieldName: fieldName,
owner: f.owner,
type: f.type,
label: label
};
if ("number" === f.type) {
row.display = "all";
}
this.rows.push(row);
return this;
},
Add a column split on a timestamp valued field, binned by the specified bucket size.
Name | Type | Description |
---|---|---|
fieldName | String | The name of field to split on. |
binning | String | The size of bins to use, see class docs for valid types. |
The updated pivot specification.
addTimestampColumnSplit: function(field, binning) {
if (!this.dataModelObject.hasField(field)) {
throw new Error("Did not find field " + field);
}
var f = this.dataModelObject.fieldByName(field);
if ("timestamp" !== f.type) {
throw new Error("Field was of type " + f.type + ", expected timestamp.");
}
if (!utils.contains(this._binning, binning)) {
throw new Error("Invalid binning " + binning + " found. Valid values are: " + this._binning.join(", "));
}
this.columns.push({
fieldName: field,
owner: f.owner,
type: f.type,
period: binning
});
return this;
},
Add a row split on a timestamp valued field, binned by the specified bucket size.
Name | Type | Description |
---|---|---|
fieldName | String | The name of field to split on. |
label | String | A human readable name for this set of rows. |
binning | String | The size of bins to use, see class docs for valid types. |
The updated pivot specification.
addTimestampRowSplit: function(field, label, binning) {
if (!this.dataModelObject.hasField(field)) {
throw new Error("Did not find field " + field);
}
var f = this.dataModelObject.fieldByName(field);
if ("timestamp" !== f.type) {
throw new Error("Field was of type " + f.type + ", expected timestamp.");
}
if (!utils.contains(this._binning, binning)) {
throw new Error("Invalid binning " + binning + " found. Valid values are: " + this._binning.join(", "));
}
this.rows.push({
fieldName: field,
owner: f.owner,
type: f.type,
label: label,
period: binning
});
return this;
},
Constructor for a pivot specification.
Name | Type | Description |
---|---|---|
parentDataModel | splunkjs.Service.DataModel | The |
init: function(dataModelObject) {
this.dataModelObject = dataModelObject;
this.columns = [];
this.rows = [];
this.filters = [];
this.cells = [];
this.accelerationNamespace = dataModelObject.dataModel.isAccelerated() ?
dataModelObject.dataModel.name : null;
this.run = utils.bind(this, this.run);
this.pivot = utils.bind(this, this.pivot);
},
Query Splunk for SPL queries corresponding to a pivot report for this data model, defined by this PivotSpecification
.
Name | Type | Description |
---|---|---|
callback | Function | A function to call when done getting the pivot: |
service.dataModels().fetch(function(err, dataModels) {
var searches = dataModels.item("internal_audit_logs").objectByName("searches");
var pivotSpec = searches.createPivotSpecification();
// Use of the fluent API
pivotSpec.addRowSplit("user", "Executing user")
.addRangeColumnSplit("exec_time", {start: 0, end: 12, step: 5, limit: 4})
.addCellValue("search", "Search Query", "values")
.pivot(function(pivotErr, pivot) {
console.log("Pivot search is:", pivot.search);
});
});
pivot: function(callback) {
var svc = this.dataModelObject.dataModel.service;
var args = {
pivot_json: JSON.stringify(this.toJsonObject())
};
if (!utils.isUndefined(this.accelerationNamespace)) {
args.namespace = this.accelerationNamespace;
}
return svc.get(Paths.pivot + "/" + encodeURIComponent(this.dataModelObject.dataModel.name), args, function(err, response) {
if (err) {
callback(new Error(err.data.messages[0].text), response);
return;
}
if (response.data.entry && response.data.entry[0]) {
callback(null, new root.Pivot(svc, response.data.entry[0].content));
}
else {
callback(new Error("Didn't get a Pivot report back from Splunk"), response);
}
});
},
Convenience method to wrap up the PivotSpecification.pivot()
and Pivot.run()
function calls.
Query Splunk for SPL queries corresponding to a pivot report for this data model, defined by this PivotSpecification
; then, starts a search job running this pivot, accelerated if possible.
service.dataModels().fetch(function(fetchErr, dataModels) {
var searches = dataModels.item("internal_audit_logs").objectByName("searches");
var pivotSpec = searches.createPivotSpecification();
// Use of the fluent API
pivotSpec.addRowSplit("user", "Executing user")
.addRangeColumnSplit("exec_time", {start: 0, end: 12, step: 5, limit: 4})
.addCellValue("search", "Search Query", "values")
.run(function(err, job, pivot) {
console.log("Job SID is:", job.sid);
console.log("Pivot search is:", pivot.search);
});
});
Name | Type | Description |
---|---|---|
args | Object | A dictionary of properties for the search job (optional). For a list of available parameters, see Search job parameters on Splunk Developer Portal. |
callback | Function | A function to call when done getting the pivot: |
run: function(args, callback) {
if (!callback) {
callback = args;
args = {};
}
args = args || {};
this.pivot(function(err, pivot) {
if (err) {
callback(err, null, null);
}
else {
pivot.run(args, Async.augment(callback, pivot));
}
});
}
});
Set the acceleration cache for this pivot specification to a job, usually generated by createLocalAccelerationJob on a DataModelObject instance, as the acceleration cache for this pivot specification.
Name | Type | Description |
---|---|---|
sid | String,splunkjs.Service.Job | The sid of an acceleration job, |
The updated pivot specification.
setAccelerationJob: function(sid) {
// If a search object is passed in, get its sid
if (sid && sid instanceof Service.Job) {
sid = sid.sid;
}
if (!sid) {
throw new Error("Sid to use for acceleration must not be null.");
}
this.accelerationNamespace = "sid=" + sid;
return this;
},
Returns a JSON ready object representation of this pivot specification.
The JSON ready object representation of this pivot specification.
toJsonObject: function() {
return {
dataModel: this.dataModelObject.dataModel.name,
baseClass: this.dataModelObject.name,
rows: this.rows,
columns: this.columns,
cells: this.cells,
filters: this.filters
};
},