Search in sources :

Example 1 with ModelProfileOnNode

use of org.opensearch.ad.model.ModelProfileOnNode in project anomaly-detection by opensearch-project.

the class ProfileResponse method writeTo.

@Override
public void writeTo(StreamOutput out) throws IOException {
    super.writeTo(out);
    out.writeVInt(modelProfile.length);
    if (Bwc.supportMultiCategoryFields(out.getVersion())) {
        for (ModelProfileOnNode profile : modelProfile) {
            profile.writeTo(out);
        }
    } else {
        for (ModelProfileOnNode profile : modelProfile) {
            ModelProfile oldFormatModelProfile = profile.getModelProfile();
            oldFormatModelProfile.writeTo(out);
        }
    }
    out.writeInt(shingleSize);
    out.writeString(coordinatingNode);
    out.writeVLong(totalSizeInBytes);
    out.writeVLong(activeEntities);
    out.writeVLong(totalUpdates);
    if (Bwc.supportMultiCategoryFields(out.getVersion())) {
        out.writeVLong(modelCount);
    }
}
Also used : ModelProfileOnNode(org.opensearch.ad.model.ModelProfileOnNode) ModelProfile(org.opensearch.ad.model.ModelProfile)

Example 2 with ModelProfileOnNode

use of org.opensearch.ad.model.ModelProfileOnNode in project anomaly-detection by opensearch-project.

the class EntityProfileTransportAction method doExecute.

@Override
protected void doExecute(Task task, EntityProfileRequest request, ActionListener<EntityProfileResponse> listener) {
    String adID = request.getAdID();
    Entity entityValue = request.getEntityValue();
    Optional<String> modelIdOptional = entityValue.getModelId(adID);
    if (false == modelIdOptional.isPresent()) {
        listener.onFailure(new AnomalyDetectionException(adID, NO_MODEL_ID_FOUND_MSG));
        return;
    }
    // we use entity's toString (e.g., app_0) to find its node
    // This should be consistent with how we land a model node in AnomalyResultTransportAction
    Optional<DiscoveryNode> node = hashRing.getOwningNodeWithSameLocalAdVersionForRealtimeAD(entityValue.toString());
    if (false == node.isPresent()) {
        listener.onFailure(new AnomalyDetectionException(adID, NO_NODE_FOUND_MSG));
        return;
    }
    String nodeId = node.get().getId();
    String modelId = modelIdOptional.get();
    DiscoveryNode localNode = clusterService.localNode();
    if (localNode.getId().equals(nodeId)) {
        EntityCache cache = cacheProvider.get();
        Set<EntityProfileName> profilesToCollect = request.getProfilesToCollect();
        EntityProfileResponse.Builder builder = new EntityProfileResponse.Builder();
        if (profilesToCollect.contains(EntityProfileName.ENTITY_INFO)) {
            builder.setActive(cache.isActive(adID, modelId));
            builder.setLastActiveMs(cache.getLastActiveMs(adID, modelId));
        }
        if (profilesToCollect.contains(EntityProfileName.INIT_PROGRESS) || profilesToCollect.contains(EntityProfileName.STATE)) {
            builder.setTotalUpdates(cache.getTotalUpdates(adID, modelId));
        }
        if (profilesToCollect.contains(EntityProfileName.MODELS)) {
            Optional<ModelProfile> modleProfile = cache.getModelProfile(adID, modelId);
            if (modleProfile.isPresent()) {
                builder.setModelProfile(new ModelProfileOnNode(nodeId, modleProfile.get()));
            }
        }
        listener.onResponse(builder.build());
    } else if (request.remoteAddress() == null) {
        // redirect if request comes from local host.
        // If a request comes from remote machine, it is already redirected.
        // One redirection should be enough.
        // We don't want a potential infinite loop due to any bug and thus give up.
        LOG.info("Sending entity profile request to {} for detector {}, entity {}", nodeId, adID, entityValue);
        try {
            transportService.sendRequest(node.get(), EntityProfileAction.NAME, request, option, new TransportResponseHandler<EntityProfileResponse>() {

                @Override
                public EntityProfileResponse read(StreamInput in) throws IOException {
                    return new EntityProfileResponse(in);
                }

                @Override
                public void handleResponse(EntityProfileResponse response) {
                    listener.onResponse(response);
                }

                @Override
                public void handleException(TransportException exp) {
                    listener.onFailure(exp);
                }

                @Override
                public String executor() {
                    return ThreadPool.Names.SAME;
                }
            });
        } catch (Exception e) {
            LOG.error(String.format(Locale.ROOT, "Fail to get entity profile for detector {}, entity {}", adID, entityValue), e);
            listener.onFailure(new AnomalyDetectionException(adID, FAIL_TO_GET_ENTITY_PROFILE_MSG, e));
        }
    } else {
        // Prior to Opensearch 1.1, we map a node using model id in the profile API.
        // This is not consistent how we map node in AnomalyResultTransportAction, where
        // we use entity values. We fixed that bug in Opensearch 1.1. But this can cause
        // issue when a request involving an old node according to model id.
        // The new node finds the entity value does not map to itself, so it redirects to another node.
        // The redirection can cause an infinite loop. This branch breaks the loop and gives up.
        LOG.error("Fail to get entity profile for detector {}, entity {}. Maybe because old and new node" + " are using different keys for the hash ring.", adID, entityValue);
        listener.onFailure(new AnomalyDetectionException(adID, FAIL_TO_GET_ENTITY_PROFILE_MSG));
    }
}
Also used : AnomalyDetectionException(org.opensearch.ad.common.exception.AnomalyDetectionException) Entity(org.opensearch.ad.model.Entity) DiscoveryNode(org.opensearch.cluster.node.DiscoveryNode) EntityCache(org.opensearch.ad.caching.EntityCache) ModelProfileOnNode(org.opensearch.ad.model.ModelProfileOnNode) TransportResponseHandler(org.opensearch.transport.TransportResponseHandler) TransportException(org.opensearch.transport.TransportException) ModelProfile(org.opensearch.ad.model.ModelProfile) AnomalyDetectionException(org.opensearch.ad.common.exception.AnomalyDetectionException) IOException(java.io.IOException) TransportException(org.opensearch.transport.TransportException) StreamInput(org.opensearch.common.io.stream.StreamInput) EntityProfileName(org.opensearch.ad.model.EntityProfileName)

Example 3 with ModelProfileOnNode

use of org.opensearch.ad.model.ModelProfileOnNode in project anomaly-detection by opensearch-project.

the class EntityProfileRunnerTests method testModel.

public void testModel() throws InterruptedException {
    setUpExecuteEntityProfileAction(InittedEverResultStatus.INITTED);
    EntityProfile.Builder expectedProfile = new EntityProfile.Builder();
    ModelProfileOnNode modelProfile = new ModelProfileOnNode(nodeId, new ModelProfile(modelId, entity, modelSize));
    expectedProfile.modelProfile(modelProfile);
    final CountDownLatch inProgressLatch = new CountDownLatch(1);
    runner.profile(detectorId, entity, model, ActionListener.wrap(response -> {
        assertEquals(expectedProfile.build(), response);
        inProgressLatch.countDown();
    }, exception -> {
        assertTrue("Should not reach here", false);
        inProgressLatch.countDown();
    }));
    assertTrue(inProgressLatch.await(100, TimeUnit.SECONDS));
}
Also used : ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) Arrays(java.util.Arrays) ModelProfile(org.opensearch.ad.model.ModelProfile) DocValueFormat(org.opensearch.search.DocValueFormat) SearchHits(org.opensearch.search.SearchHits) EntityProfileName(org.opensearch.ad.model.EntityProfileName) ModelProfileOnNode(org.opensearch.ad.model.ModelProfileOnNode) HashSet(java.util.HashSet) InternalMax(org.opensearch.search.aggregations.metrics.InternalMax) ANOMALY_DETECTOR_JOB_INDEX(org.opensearch.ad.model.AnomalyDetectorJob.ANOMALY_DETECTOR_JOB_INDEX) EntityProfileResponse(org.opensearch.ad.transport.EntityProfileResponse) Mockito.doAnswer(org.mockito.Mockito.doAnswer) AnomalyDetector(org.opensearch.ad.model.AnomalyDetector) InternalAggregations(org.opensearch.search.aggregations.InternalAggregations) SearchRequest(org.opensearch.action.search.SearchRequest) ActionListener(org.opensearch.action.ActionListener) SearchResponse(org.opensearch.action.search.SearchResponse) GetResponse(org.opensearch.action.get.GetResponse) EntityProfile(org.opensearch.ad.model.EntityProfile) Collections.emptyMap(java.util.Collections.emptyMap) Client(org.opensearch.client.Client) CommonName(org.opensearch.ad.constant.CommonName) InitProgressProfile(org.opensearch.ad.model.InitProgressProfile) SearchHit(org.opensearch.search.SearchHit) IndexNotFoundException(org.opensearch.index.IndexNotFoundException) ANOMALY_DETECTORS_INDEX(org.opensearch.ad.model.AnomalyDetector.ANOMALY_DETECTORS_INDEX) GetRequest(org.opensearch.action.get.GetRequest) Set(java.util.Set) IOException(java.io.IOException) InternalSearchResponse(org.opensearch.search.internal.InternalSearchResponse) TimeUnit(java.util.concurrent.TimeUnit) TotalHits(org.apache.lucene.search.TotalHits) CountDownLatch(java.util.concurrent.CountDownLatch) CommonErrorMessages(org.opensearch.ad.constant.CommonErrorMessages) ChronoUnit(java.time.temporal.ChronoUnit) Entity(org.opensearch.ad.model.Entity) SearchResponseSections(org.opensearch.action.search.SearchResponseSections) EntityState(org.opensearch.ad.model.EntityState) ShardSearchFailure(org.opensearch.action.search.ShardSearchFailure) AnomalyDetectorJob(org.opensearch.ad.model.AnomalyDetectorJob) IntervalTimeConfiguration(org.opensearch.ad.model.IntervalTimeConfiguration) Collections(java.util.Collections) EntityProfileAction(org.opensearch.ad.transport.EntityProfileAction) Text(org.opensearch.common.text.Text) Mockito.mock(org.mockito.Mockito.mock) ModelProfileOnNode(org.opensearch.ad.model.ModelProfileOnNode) EntityProfile(org.opensearch.ad.model.EntityProfile) CountDownLatch(java.util.concurrent.CountDownLatch) ModelProfile(org.opensearch.ad.model.ModelProfile)

Example 4 with ModelProfileOnNode

use of org.opensearch.ad.model.ModelProfileOnNode in project anomaly-detection by opensearch-project.

the class EntityProfileRunnerTests method setUpExecuteEntityProfileAction.

@SuppressWarnings("unchecked")
private void setUpExecuteEntityProfileAction(InittedEverResultStatus initted) {
    smallUpdates = 1;
    latestActiveTimestamp = 1603999189758L;
    isActive = Boolean.TRUE;
    modelId = "T4c3dXUBj-2IZN7itix__entity_" + entityValue;
    modelSize = 712480L;
    nodeId = "g6pmr547QR-CfpEvO67M4g";
    doAnswer(invocation -> {
        Object[] args = invocation.getArguments();
        ActionListener<EntityProfileResponse> listener = (ActionListener<EntityProfileResponse>) args[2];
        EntityProfileResponse.Builder profileResponseBuilder = new EntityProfileResponse.Builder();
        if (InittedEverResultStatus.UNKNOWN == initted) {
            profileResponseBuilder.setTotalUpdates(0L);
        } else if (InittedEverResultStatus.NOT_INITTED == initted) {
            profileResponseBuilder.setTotalUpdates(smallUpdates);
            profileResponseBuilder.setLastActiveMs(latestActiveTimestamp);
            profileResponseBuilder.setActive(isActive);
        } else {
            profileResponseBuilder.setTotalUpdates(requiredSamples + 1);
            ModelProfileOnNode model = new ModelProfileOnNode(nodeId, new ModelProfile(modelId, entity, modelSize));
            profileResponseBuilder.setModelProfile(model);
        }
        listener.onResponse(profileResponseBuilder.build());
        return null;
    }).when(client).execute(any(EntityProfileAction.class), any(), any());
    doAnswer(invocation -> {
        Object[] args = invocation.getArguments();
        SearchRequest request = (SearchRequest) args[0];
        String indexName = request.indices()[0];
        ActionListener<SearchResponse> listener = (ActionListener<SearchResponse>) args[1];
        SearchResponse searchResponse = null;
        if (indexName.equals(CommonName.ANOMALY_RESULT_INDEX_ALIAS)) {
            InternalMax maxAgg = new InternalMax(CommonName.AGG_NAME_MAX_TIME, latestSampleTimestamp, DocValueFormat.RAW, emptyMap());
            InternalAggregations internalAggregations = InternalAggregations.from(Collections.singletonList(maxAgg));
            SearchHits hits = new SearchHits(new SearchHit[] {}, null, Float.NaN);
            SearchResponseSections searchSections = new SearchResponseSections(hits, internalAggregations, null, false, false, null, 1);
            searchResponse = new SearchResponse(searchSections, null, 1, 1, 0, 30, ShardSearchFailure.EMPTY_ARRAY, SearchResponse.Clusters.EMPTY);
        } else {
            SearchHits collapsedHits = new SearchHits(new SearchHit[] { new SearchHit(2, "ID", new Text("type"), Collections.emptyMap(), Collections.emptyMap()), new SearchHit(3, "ID", new Text("type"), Collections.emptyMap(), Collections.emptyMap()) }, new TotalHits(1, TotalHits.Relation.EQUAL_TO), 1.0F);
            InternalSearchResponse internalSearchResponse = new InternalSearchResponse(collapsedHits, null, null, null, false, null, 1);
            searchResponse = new SearchResponse(internalSearchResponse, null, 1, 1, 0, 0, ShardSearchFailure.EMPTY_ARRAY, SearchResponse.Clusters.EMPTY);
        }
        listener.onResponse(searchResponse);
        return null;
    }).when(client).search(any(), any());
}
Also used : TotalHits(org.apache.lucene.search.TotalHits) EntityProfileAction(org.opensearch.ad.transport.EntityProfileAction) SearchRequest(org.opensearch.action.search.SearchRequest) SearchResponseSections(org.opensearch.action.search.SearchResponseSections) InternalMax(org.opensearch.search.aggregations.metrics.InternalMax) SearchHit(org.opensearch.search.SearchHit) ModelProfileOnNode(org.opensearch.ad.model.ModelProfileOnNode) Text(org.opensearch.common.text.Text) ModelProfile(org.opensearch.ad.model.ModelProfile) SearchResponse(org.opensearch.action.search.SearchResponse) InternalSearchResponse(org.opensearch.search.internal.InternalSearchResponse) InternalAggregations(org.opensearch.search.aggregations.InternalAggregations) ActionListener(org.opensearch.action.ActionListener) EntityProfileResponse(org.opensearch.ad.transport.EntityProfileResponse) SearchHits(org.opensearch.search.SearchHits) InternalSearchResponse(org.opensearch.search.internal.InternalSearchResponse)

Example 5 with ModelProfileOnNode

use of org.opensearch.ad.model.ModelProfileOnNode in project anomaly-detection by opensearch-project.

the class BwcTests method setUpEntityProfileResponse.

private void setUpEntityProfileResponse() {
    long lastActiveTimestamp = 10L;
    EntityProfileResponse.Builder builder = new EntityProfileResponse.Builder();
    builder.setLastActiveMs(lastActiveTimestamp).build();
    ModelProfile modelProfile = new ModelProfile(modelId, entity, modelSize);
    ModelProfileOnNode model = new ModelProfileOnNode(nodeId, modelProfile);
    builder.setModelProfile(model);
    entityProfileResponse1_1 = builder.build();
    EntityProfileResponse1_0.Builder builder1_0 = new EntityProfileResponse1_0.Builder();
    builder1_0.setLastActiveMs(lastActiveTimestamp).build();
    ModelProfile1_0 modelProfile1_0 = new ModelProfile1_0(modelId, modelSize, nodeId);
    builder1_0.setModelProfile(modelProfile1_0);
    entityProfileResponse1_0 = builder1_0.build();
    ModelProfile convertedModelProfile = new ModelProfile(modelId, null, modelSize);
    convertedModelProfileOnNode = new ModelProfileOnNode(CommonName.EMPTY_FIELD, convertedModelProfile);
}
Also used : ModelProfileOnNode(org.opensearch.ad.model.ModelProfileOnNode) EntityProfileResponse(org.opensearch.ad.transport.EntityProfileResponse) ModelProfile(org.opensearch.ad.model.ModelProfile)

Aggregations

ModelProfileOnNode (org.opensearch.ad.model.ModelProfileOnNode)12 ModelProfile (org.opensearch.ad.model.ModelProfile)8 EntityProfileResponse (org.opensearch.ad.transport.EntityProfileResponse)5 IOException (java.io.IOException)3 ActionListener (org.opensearch.action.ActionListener)3 FailedNodeException (org.opensearch.action.FailedNodeException)3 ProfileResponse (org.opensearch.ad.transport.ProfileResponse)3 ClusterName (org.opensearch.cluster.ClusterName)3 ChronoUnit (java.time.temporal.ChronoUnit)2 Arrays (java.util.Arrays)2 Collections (java.util.Collections)2 Collections.emptyMap (java.util.Collections.emptyMap)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 Set (java.util.Set)2 CountDownLatch (java.util.concurrent.CountDownLatch)2 TimeUnit (java.util.concurrent.TimeUnit)2 TotalHits (org.apache.lucene.search.TotalHits)2 ArgumentMatchers.any (org.mockito.ArgumentMatchers.any)2 Mockito.doAnswer (org.mockito.Mockito.doAnswer)2