Search in sources :

Example 1 with Twin

use of io.datarouter.util.tuple.Twin in project datarouter by hotpads.

the class DatarouterSnapshotEntryHandler method buildTable.

private ContainerTag<?> buildTable(SnapshotKey snapshotKey, long id) {
    SnapshotGroup group = groups.getGroup(snapshotKey.groupId);
    var reader = new SnapshotIdReader(snapshotKey, groups);
    SnapshotRecord record = reader.getRecord(id);
    SnapshotRecordStringDecoder decoder = ReflectionTool.create(group.getSnapshotEntryDecoderClass());
    SnapshotRecordStrings decoded = decoder.decode(record);
    List<Twin<String>> rows = new ArrayList<>();
    rows.add(new Twin<>("id", Long.toString(record.id)));
    rows.add(new Twin<>(decoder.keyName(), decoded.key));
    rows.add(new Twin<>(decoder.valueName(), decoded.value));
    IntStream.range(0, decoded.columnValues.size()).mapToObj(column -> new Twin<>(decoder.columnValueName(column), decoded.columnValues.get(column))).forEach(rows::add);
    var table = new J2HtmlTable<Twin<String>>().withClasses("sortable table table-sm table-striped my-4 border").withColumn("field", twin -> twin.getLeft()).withColumn("value", twin -> twin.getRight()).build(rows);
    return table;
}
Also used : IntStream(java.util.stream.IntStream) SnapshotRecord(io.datarouter.filesystem.snapshot.reader.record.SnapshotRecord) Twin(io.datarouter.util.tuple.Twin) Mav(io.datarouter.web.handler.mav.Mav) SnapshotGroup(io.datarouter.filesystem.snapshot.group.SnapshotGroup) ReflectionTool(io.datarouter.util.lang.ReflectionTool) ArrayList(java.util.ArrayList) ContainerTag(j2html.tags.ContainerTag) Inject(javax.inject.Inject) List(java.util.List) DatarouterWebRequireJsV2(io.datarouter.web.requirejs.DatarouterWebRequireJsV2) SnapshotGroups(io.datarouter.filesystem.snapshot.group.SnapshotGroups) BaseHandler(io.datarouter.web.handler.BaseHandler) Bootstrap4PageFactory(io.datarouter.web.html.j2html.bootstrap4.Bootstrap4PageFactory) SnapshotKey(io.datarouter.filesystem.snapshot.key.SnapshotKey) Param(io.datarouter.web.handler.types.Param) J2HtmlTable(io.datarouter.web.html.j2html.J2HtmlTable) SnapshotIdReader(io.datarouter.filesystem.snapshot.reader.SnapshotIdReader) J2HtmlTable(io.datarouter.web.html.j2html.J2HtmlTable) ArrayList(java.util.ArrayList) SnapshotRecord(io.datarouter.filesystem.snapshot.reader.record.SnapshotRecord) SnapshotIdReader(io.datarouter.filesystem.snapshot.reader.SnapshotIdReader) SnapshotGroup(io.datarouter.filesystem.snapshot.group.SnapshotGroup) Twin(io.datarouter.util.tuple.Twin)

Example 2 with Twin

use of io.datarouter.util.tuple.Twin in project datarouter by hotpads.

the class TableSizeMonitoringService method getAboveThresholdLists.

public Twin<List<CountStat>> getAboveThresholdLists() {
    List<CountStat> aboveThresholdList = new ArrayList<>();
    List<CountStat> abovePercentageList = new ArrayList<>();
    for (PhysicalNode<?, ?, ?> node : datarouterNodes.getWritableNodes(clients.getClientIds())) {
        ClientTableEntityPrefixNameWrapper nodeNames = new ClientTableEntityPrefixNameWrapper(node);
        String tableName = nodeNames.getTableName();
        String clientName = nodeNames.getClientName();
        NodewatchConfiguration nodeConfig = null;
        Long threshold = null;
        boolean enablePercentChangeAlert = true;
        boolean enableThresholdAlert = true;
        nodeConfig = tableConfigurationService.getTableConfigMap().get(nodeNames);
        if (nodeConfig != null) {
            threshold = nodeConfig.maxThreshold;
            enablePercentChangeAlert = nodeConfig.enablePercentageAlert;
            enableThresholdAlert = nodeConfig.enableThresholdAlert;
        }
        // continue if the nodeConfig isCountable is set to false
        if (nodeConfig != null && !nodeConfig.isCountable) {
            continue;
        }
        List<TableCount> tableCountRecords = tableCountDao.getForTable(clientName, tableName);
        if (tableCountRecords.size() < 2) {
            continue;
        }
        Collections.sort(tableCountRecords, new TableCount.TableCountLatestEntryComparator());
        TableCount latest = tableCountRecords.get(0);
        TableCount previous = tableCountRecords.get(1);
        if (previous.getNumRows() == 0) {
            continue;
        }
        // skip if the table has records less than the count_threshold
        if (smallEnoughToIgnore(latest.getNumRows()) && smallEnoughToIgnore(previous.getNumRows())) {
            continue;
        }
        if (enableThresholdAlert) {
            Optional<TableSizeAlertThreshold> thresholdEntry = tableSizeAlertThresholdDao.find(new TableSizeAlertThresholdKey(clientName, tableName));
            // override manual thresholdEntry if exists
            if (thresholdEntry.isPresent() && thresholdEntry.get().getMaxRows() > 0) {
                threshold = thresholdEntry.get().getMaxRows();
            }
            // check if node numRows exceeds threshold
            if (threshold != null && latest.getNumRows() >= threshold) {
                aboveThresholdList.add(calculateStats(latest, threshold));
            }
        }
        if (enablePercentChangeAlert) {
            // check % growth if no absolute threshold set & !enablePercentChangeAlert
            CountStat growthIncrease = calculateStats(latest, previous.getNumRows());
            if (growthIncrease == null) {
                continue;
            }
            if (Math.abs(growthIncrease.percentageIncrease) > PERCENTAGE_THRESHOLD) {
                abovePercentageList.add(growthIncrease);
            }
        }
    }
    return new Twin<>(aboveThresholdList, abovePercentageList);
}
Also used : NodewatchConfiguration(io.datarouter.storage.node.tableconfig.NodewatchConfiguration) ArrayList(java.util.ArrayList) Twin(io.datarouter.util.tuple.Twin) TableSizeAlertThreshold(io.datarouter.nodewatch.storage.alertthreshold.TableSizeAlertThreshold) LatestTableCount(io.datarouter.nodewatch.storage.latesttablecount.LatestTableCount) TableCount(io.datarouter.nodewatch.storage.tablecount.TableCount) TableSizeAlertThresholdKey(io.datarouter.nodewatch.storage.alertthreshold.TableSizeAlertThresholdKey) ClientTableEntityPrefixNameWrapper(io.datarouter.storage.node.tableconfig.ClientTableEntityPrefixNameWrapper)

Example 3 with Twin

use of io.datarouter.util.tuple.Twin in project datarouter by hotpads.

the class WebappInstanceAlertJob method makeContent.

private ContainerTag<?> makeContent(WebappInstance webappInstance, DatarouterDuration buildAge) {
    ZoneId zoneId = defaultDistributionListZoneId.get();
    var rows = List.of(new Twin<>("webapp", webappInstance.getKey().getWebappName()), new Twin<>("build date", ZonedDateFormatterTool.formatInstantWithZone(webappInstance.getBuildInstant(), zoneId)), new Twin<>("build age", buildAge.toString()), new Twin<>("startup date", ZonedDateFormatterTool.formatInstantWithZone(webappInstance.getStartupInstant(), zoneId)), new Twin<>("commitId", webappInstance.getCommitId()));
    return new J2HtmlEmailTable<Twin<String>>().withColumn(new J2HtmlEmailTableColumn<>(null, row -> makeDivBoldRight(row.getLeft()))).withColumn(new J2HtmlEmailTableColumn<>(null, row -> text(row.getRight()))).build(rows);
}
Also used : Twin(io.datarouter.util.tuple.Twin) TagCreator.text(j2html.TagCreator.text) TagCreator.body(j2html.TagCreator.body) DatarouterHtmlEmailService(io.datarouter.web.email.DatarouterHtmlEmailService) DatarouterWebappInstanceSettingRoot(io.datarouter.webappinstance.config.DatarouterWebappInstanceSettingRoot) J2HtmlEmailTableColumn(io.datarouter.email.html.J2HtmlEmailTable.J2HtmlEmailTableColumn) DatarouterWebappInstancePaths(io.datarouter.webappinstance.config.DatarouterWebappInstancePaths) Inject(javax.inject.Inject) WebappInstanceService(io.datarouter.webappinstance.service.WebappInstanceService) ServerTypeDetector(io.datarouter.storage.servertype.ServerTypeDetector) J2HtmlEmailTable(io.datarouter.email.html.J2HtmlEmailTable) BaseJob(io.datarouter.job.BaseJob) StandardDatarouterEmailHeaderService(io.datarouter.web.email.StandardDatarouterEmailHeaderService) TaskTracker(io.datarouter.instrumentation.task.TaskTracker) WebappInstance(io.datarouter.webappinstance.storage.webappinstance.WebappInstance) Instant(java.time.Instant) DatarouterDuration(io.datarouter.util.duration.DatarouterDuration) ZoneId(java.time.ZoneId) ContainerTag(j2html.tags.ContainerTag) ZonedDateFormatterTool(io.datarouter.util.time.ZonedDateFormatterTool) DefaultEmailDistributionListZoneId(io.datarouter.web.config.properties.DefaultEmailDistributionListZoneId) WebappInstanceAlertEmailType(io.datarouter.email.type.DatarouterEmailTypes.WebappInstanceAlertEmailType) DomContent(j2html.tags.DomContent) List(java.util.List) TagCreator.div(j2html.TagCreator.div) ZoneId(java.time.ZoneId) DefaultEmailDistributionListZoneId(io.datarouter.web.config.properties.DefaultEmailDistributionListZoneId) J2HtmlEmailTableColumn(io.datarouter.email.html.J2HtmlEmailTable.J2HtmlEmailTableColumn) Twin(io.datarouter.util.tuple.Twin)

Example 4 with Twin

use of io.datarouter.util.tuple.Twin in project datarouter by hotpads.

the class ViewNodeDataHandler method countKeys.

@Handler
public <PK extends PrimaryKey<PK>, D extends Databean<PK, D>> Mav countKeys(OptionalInteger batchSize, OptionalInteger logBatchSize, OptionalInteger limit, OptionalBoolean useOffsetting, OptionalInteger stride) {
    showForm();
    if (!(node instanceof SortedStorageWriter<?, ?>)) {
        return pageFactory.message(request, "Cannot browse unsorted node");
    }
    PhysicalNode<?, ?, ?> physicalNode = NodeTool.extractSinglePhysicalNode(node);
    // TODO replace strings with more formal client detection
    boolean actualUseOffsetting = useOffsetting.orElse(physicalNode.getClientType().supportsOffsetSampling());
    @SuppressWarnings("unchecked") SortedStorageReader<PK, D> sortedNode = (SortedStorageReader<PK, D>) node;
    long count = 0;
    long startMs = System.currentTimeMillis() - 1;
    PK last = null;
    if (actualUseOffsetting) {
        var countingToolBuilder = new StrideScannerBuilder<>(sortedNode).withLog(true);
        stride.ifPresent(countingToolBuilder::withStride);
        batchSize.ifPresent(countingToolBuilder::withBatchSize);
        count = countingToolBuilder.build().findLast().map(sample -> sample.totalCount).orElse(0L);
    } else {
        Config config = new Config().setResponseBatchSize(batchSize.orElse(1000)).setScannerCaching(// disabled due to BigTable bug?
        false).setTimeout(Duration.ofMinutes(1)).anyDelay().setNumAttempts(1);
        limit.ifPresent(config::setLimit);
        int printBatchSize = logBatchSize.orElse(100_000);
        long batchStartMs = System.currentTimeMillis() - 1;
        for (PK pk : sortedNode.scanKeys(config).iterable()) {
            if (ComparableTool.lt(pk, last)) {
                // shouldn't happen, but seems to once in 10mm times
                logger.warn("{} was < {}", pk, last);
            }
            ++count;
            if (count % printBatchSize == 0) {
                long batchMs = System.currentTimeMillis() - batchStartMs;
                double batchAvgRps = printBatchSize * 1000 / Math.max(1, batchMs);
                logger.warn("{} {} {} @{}rps", NumberFormatter.addCommas(count), node.getName(), pk.toString(), NumberFormatter.addCommas(batchAvgRps));
                batchStartMs = System.currentTimeMillis();
            }
            last = pk;
        }
    }
    if (count < 1) {
        return pageFactory.message(request, "no rows found");
    }
    long endMs = System.currentTimeMillis();
    long durationMs = endMs - startMs;
    DatarouterDuration duration = new DatarouterDuration(durationMs, TimeUnit.MILLISECONDS);
    double avgRps = count * 1_000 / durationMs;
    String message = String.format("finished counting %s at %s %s @%srps totalDuration=%s", node.getName(), NumberFormatter.addCommas(count), last == null ? "?" : last.toString(), NumberFormatter.addCommas(avgRps), duration);
    logger.warn(message);
    List<Twin<String>> emailKvs = List.of(Twin.of("node", node.getName()), Twin.of("useOffsetting", actualUseOffsetting + ""), Twin.of("stride", stride.map(Object::toString).orElse("default")), Twin.of("totalCount", NumberFormatter.addCommas(count)), Twin.of("lastKey", last == null ? "?" : last.toString()), Twin.of("averageRps", NumberFormatter.addCommas(avgRps)), Twin.of("start", ZonedDateFormatterTool.formatLongMsWithZone(startMs, ZoneId.systemDefault())), Twin.of("end", ZonedDateFormatterTool.formatLongMsWithZone(endMs, ZoneId.systemDefault())), Twin.of("duration", duration + ""), Twin.of("triggeredBy", getSessionInfo().getRequiredSession().getUsername()));
    sendEmail(node.getName(), emailKvs);
    var dto = new DatarouterChangelogDtoBuilder("Inspect Node Data", node.getName(), "countKeys", getSessionInfo().getRequiredSession().getUsername()).build();
    changelogRecorder.record(dto);
    return pageFactory.message(request, message);
}
Also used : SortedStorageWriter(io.datarouter.storage.node.op.raw.write.SortedStorageWriter) Config(io.datarouter.storage.config.Config) DatarouterDuration(io.datarouter.util.duration.DatarouterDuration) SortedStorageReader(io.datarouter.storage.node.op.raw.read.SortedStorageReader) Twin(io.datarouter.util.tuple.Twin) DatarouterChangelogDtoBuilder(io.datarouter.instrumentation.changelog.ChangelogRecorder.DatarouterChangelogDtoBuilder)

Example 5 with Twin

use of io.datarouter.util.tuple.Twin in project datarouter by hotpads.

the class SqsQueueRegistryService method getSqsQueuesForClient.

public Pair<List<Twin<String>>, List<String>> getSqsQueuesForClient(ClientId clientId) {
    Set<String> knownQueuesUrls = new HashSet<>();
    AmazonSQS sqs = sqsClientManager.getAmazonSqs(clientId);
    List<? extends BaseSqsNode<?, ?, ?>> sqsNodes = Scanner.of(nodes.getPhysicalNodesForClient(clientId.getName())).map(NodeTool::extractSinglePhysicalNode).map(physicalNode -> (BaseSqsNode<?, ?, ?>) physicalNode).list();
    List<Twin<String>> knownQueueUrlByName = Scanner.of(sqsNodes).map(BaseSqsNode::getQueueUrlAndName).map(Supplier::get).each(twin -> knownQueuesUrls.add(twin.getLeft())).list();
    List<String> unreferencedQueues = Scanner.of(sqsNodes).map(BaseSqsNode::buildNamespace).distinct().map(sqs::listQueues).concatIter(ListQueuesResult::getQueueUrls).exclude(knownQueuesUrls::contains).map(queueUrl -> StringTool.getStringAfterLastOccurrence("/", queueUrl)).include(queueName -> sqsQueueExists(sqs, queueName)).list();
    return new Pair<>(knownQueueUrlByName, unreferencedQueues);
}
Also used : Twin(io.datarouter.util.tuple.Twin) Scanner(io.datarouter.scanner.Scanner) NodeTool(io.datarouter.storage.node.NodeTool) Set(java.util.Set) ListQueuesResult(com.amazonaws.services.sqs.model.ListQueuesResult) Singleton(javax.inject.Singleton) StringTool(io.datarouter.util.string.StringTool) Supplier(java.util.function.Supplier) HashSet(java.util.HashSet) Inject(javax.inject.Inject) SqsClientManager(io.datarouter.aws.sqs.SqsClientManager) List(java.util.List) QueueDoesNotExistException(com.amazonaws.services.sqs.model.QueueDoesNotExistException) ClientId(io.datarouter.storage.client.ClientId) AmazonSQS(com.amazonaws.services.sqs.AmazonSQS) BaseSqsNode(io.datarouter.aws.sqs.BaseSqsNode) DatarouterNodes(io.datarouter.storage.node.DatarouterNodes) Pair(io.datarouter.util.tuple.Pair) ListQueuesResult(com.amazonaws.services.sqs.model.ListQueuesResult) AmazonSQS(com.amazonaws.services.sqs.AmazonSQS) Twin(io.datarouter.util.tuple.Twin) NodeTool(io.datarouter.storage.node.NodeTool) BaseSqsNode(io.datarouter.aws.sqs.BaseSqsNode) Supplier(java.util.function.Supplier) HashSet(java.util.HashSet) Pair(io.datarouter.util.tuple.Pair)

Aggregations

Twin (io.datarouter.util.tuple.Twin)5 List (java.util.List)3 Inject (javax.inject.Inject)3 DatarouterDuration (io.datarouter.util.duration.DatarouterDuration)2 ContainerTag (j2html.tags.ContainerTag)2 ArrayList (java.util.ArrayList)2 AmazonSQS (com.amazonaws.services.sqs.AmazonSQS)1 ListQueuesResult (com.amazonaws.services.sqs.model.ListQueuesResult)1 QueueDoesNotExistException (com.amazonaws.services.sqs.model.QueueDoesNotExistException)1 BaseSqsNode (io.datarouter.aws.sqs.BaseSqsNode)1 SqsClientManager (io.datarouter.aws.sqs.SqsClientManager)1 J2HtmlEmailTable (io.datarouter.email.html.J2HtmlEmailTable)1 J2HtmlEmailTableColumn (io.datarouter.email.html.J2HtmlEmailTable.J2HtmlEmailTableColumn)1 WebappInstanceAlertEmailType (io.datarouter.email.type.DatarouterEmailTypes.WebappInstanceAlertEmailType)1 SnapshotGroup (io.datarouter.filesystem.snapshot.group.SnapshotGroup)1 SnapshotGroups (io.datarouter.filesystem.snapshot.group.SnapshotGroups)1 SnapshotKey (io.datarouter.filesystem.snapshot.key.SnapshotKey)1 SnapshotIdReader (io.datarouter.filesystem.snapshot.reader.SnapshotIdReader)1 SnapshotRecord (io.datarouter.filesystem.snapshot.reader.record.SnapshotRecord)1 DatarouterChangelogDtoBuilder (io.datarouter.instrumentation.changelog.ChangelogRecorder.DatarouterChangelogDtoBuilder)1