Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ public RawMetricSamplesHandler(MeasurementAccessor accessor, ExecutionMetricSamp
}

@Override
public void processMeasurements(List<Measurement> measurements) {
public void processMeasurements(ExecutionContext executionContext, List<Measurement> measurements) {
List<?> castedMeasurements = measurements;
if (measurements.size() > 0) {
accessor.saveManyMeasurements((List<Object>) castedMeasurements);
}
}

@Override
public void processMetrics(List<ExecutionMetricSample> metrics) {
public void processMetrics(ExecutionContext executionContext, List<ExecutionMetricSample> metrics) {
if (metrics != null && !metrics.isEmpty()) {
executionMetricSampleAccessor.save(metrics);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.slf4j.LoggerFactory;
import step.controller.services.async.AsyncTaskManager;
import step.controller.services.async.AsyncTaskManagerPlugin;
import step.core.Constants;
import step.core.GlobalContext;
import step.core.collections.Collection;
import step.core.collections.CollectionFactory;
Expand All @@ -13,6 +14,9 @@
import step.core.deployment.WebApplicationConfigurationManager;
import step.core.entities.Entity;
import step.core.entities.EntityConstants;
import step.core.execution.model.ExecutionNoticeSeverity;
import step.core.execution.notices.ExecutionNoticeManager;
import step.core.execution.notices.ExecutionNoticeType;
import step.core.metrics.MetricsConstants;
import step.core.plugins.AbstractControllerPlugin;
import step.core.plugins.Plugin;
Expand Down Expand Up @@ -126,7 +130,32 @@ public void serverStart(GlobalContext context) {
TimeSeriesIngestionPipeline mainIngestionPipeline = timeSeries.getIngestionPipeline();

TimeSeriesAggregationPipeline aggregationPipeline = timeSeries.getAggregationPipeline();
TimeSeriesMetricSamplesHandler handler = new TimeSeriesMetricSamplesHandler(timeSeries, includedAttributes, excludedAttributes);
// Safeguard against high cardinality on user-defined metric/measurement labels during executions.
// Two axes are bounded: the number of unique values per label, and the number of distinct label names per metric.
// For both properties: a negative value disables the safeguard; 0 is the strictest setting (mask every custom
// value / drop every custom label respectively, allowing an admin to fully strip custom labels from time-series).
int maxUniqueLabelValues = configuration.getPropertyAsInteger("timeseries.attributes.max-unique-label-values", 20);
int maxLabelsPerMetric = configuration.getPropertyAsInteger("timeseries.attributes.max-labels-per-metric", 20);
ExecutionNoticeManager executionNoticeManager = context.require(ExecutionNoticeManager.class);
// The documentation URL is keyed on the Step "doc" version (the minor component, e.g. "30" for 3.30.0),
// derived from the version constant so it tracks version upgrades automatically.
String docUrl = "https://step.dev/knowledgebase/" + Constants.STEP_VERSION.getMinor()
+ "/userdocs/analytics/measurements-and-metrics/#label-cardinality-safeguard";
executionNoticeManager.register(new ExecutionNoticeType(
TimeSeriesMetricSamplesHandler.CARDINALITY_NOTICE_TYPE_ID,
"Time-series",
ExecutionNoticeSeverity.WARNING,
"High cardinality detected on the custom metric label <b>{labelName}</b> of metric <b>{metricName}</b>. " +
"Unique values exceeding the quota of {quota} were dismissed and are reported under a single placeholder value. " +
"<a href=\"" + docUrl + "\" target=\"_blank\">Learn more</a>"));
executionNoticeManager.register(new ExecutionNoticeType(
TimeSeriesMetricSamplesHandler.CARDINALITY_LABEL_COUNT_NOTICE_TYPE_ID,
"Time-series",
ExecutionNoticeSeverity.WARNING,
"High cardinality detected on metric <b>{metricName}</b>: the number of distinct custom labels exceeded " +
"the quota of {quota}. Additional labels were dropped from the ingested data. " +
"<a href=\"" + docUrl + "\" target=\"_blank\">Learn more</a>"));
TimeSeriesMetricSamplesHandler handler = new TimeSeriesMetricSamplesHandler(timeSeries, includedAttributes, excludedAttributes, maxUniqueLabelValues, maxLabelsPerMetric, executionNoticeManager);

context.put(TimeSeries.class, timeSeries);
context.put(TimeSeriesIngestionPipeline.class, mainIngestionPipeline);
Expand Down
Loading