Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Exporters and Readers #210

Merged
merged 7 commits into from
Jan 27, 2025

Conversation

ansjcy
Copy link
Member

@ansjcy ansjcy commented Jan 24, 2025

Description

There are multiple issues with the current exporter.

  1. Currently, we have different exporters config for different metrics.
    https://opensearch.org/docs/latest/observing-your-data/query-insights/top-n-queries/#configuring-a-local-index-exporter
    This is not a good pattern since we don't have specific use cases when users enabled multiple top n metrics, but they only want to exporter certain of them. We need to move the exporter from top queries service level to query insights service level.
  2. The safeguard to decide if an index is created by query insights service is not strong. We only check the index name. We should add certain metadata in the index to indicate "this is our index". [FEATURE] Enhance the safegard when deleting top queries records #213
  3. There's no index mapping and index level sorting defined for the index, and we only allow default size (10?) when searching on the index. This will become a problem when the frontend wants lots of data (basically, everything exceed 10 will go wrong) [FEATURE] Exporters should have index mappings defined #212
  4. There are a lot of duplicate records in index when multiple metrics are enabled. We need to do deduplication.
  5. when LocalIndexReader uses generateLocalIndexDateHash() to get historical data, since generateLocalIndexDateHash only consider current time, it's not generating correct hash for older date.
  6. We are overusing static methods, and not complying with the ExporterFactory Model. Need to refactor the node.

Issues Resolved

TODO

tests

TODO

  • enable top n queries for all metrics and local index exporter with
 curl -X PUT 'localhost:9200/_cluster/settings' -H 'Content-Type: application/json' -d'
{
    "persistent" : {
        "search.insights.top_queries.latency.enabled" : "true",
        "search.insights.top_queries.cpu.enabled" : "true",
        "search.insights.top_queries.memory.enabled" : "true",
        "search.insights.top_queries.exporter.type" : "local_index"
    }
}'
{"acknowledged":true,"persistent":{"search":{"insights":{"top_queries":{"cpu":{"enabled":"true"},"exporter":{"type":"local_index"},"memory":{"enabled":"true"},"latency":{"enabled":"true"}}}}},"transient":{}}
  • do search
  • check local index, data are exported without errors
➜  OpenSearch git:(main) ✗ curl -X POST "localhost:9200/top_queries-*/_search?pretty"
{
  "took" : 15,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 6,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "top_queries-2025.01.24-62114",
        "_id" : "l1L7lZQBbSnBp-lpBZtY",
        "_score" : 1.0,
        "_source" : {
          "timestamp" : 1737683015018,
          "id" : "ba5087e8-47f6-4882-b4e0-94b0c455df83",
          "task_resource_usages" : [
            {
              "action" : "indices:data/read/search[phase/query]",
              "taskId" : 117,
              "parentTaskId" : 116,
              "nodeId" : "aBdathzfR_O-o7ct8LqHrA",
              "taskResourceUsage" : {
                "cpu_time_in_nanos" : 577000,
                "memory_in_bytes" : 33160
              }
            },
            {
              "action" : "indices:data/read/search",
              "taskId" : 116,
              "parentTaskId" : -1,
              "nodeId" : "aBdathzfR_O-o7ct8LqHrA",
              "taskResourceUsage" : {
                "cpu_time_in_nanos" : 85000,
                "memory_in_bytes" : 3672
              }
            }
          ],
          "search_type" : "query_then_fetch",
          "total_shards" : 1,
          "indices" : [
            "my-index-0"
          ],
          "group_by" : "NONE",
          "labels" : { },
          "phase_latency_map" : {
            "expand" : 0,
            "query" : 1,
            "fetch" : 0
          },
          "source" : {
            "size" : 20,
            "query" : {
              "term" : {
                "user.id" : {
                  "value" : "cyji",
                  "boost" : 1.0
                }
              }
            }
          },
          "measurements" : {
            "memory" : {
              "number" : 36832,
              "count" : 1,
              "aggregationType" : "NONE"
            },
            "latency" : {
              "number" : 1,
              "count" : 1,
              "aggregationType" : "NONE"
            },
            "cpu" : {
              "number" : 662000,
              "count" : 1,
              "aggregationType" : "NONE"
            }
          }
        }
      },
    ...

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@ansjcy ansjcy force-pushed the refactor-exporter-and-reader branch 10 times, most recently from 7f3d20d to 851d174 Compare January 24, 2025 07:07
Copy link
Collaborator

@deshsidd deshsidd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a few comments and went over this - looks good at a high level. Might need to give one more pass soon.

String currentDate = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.ROOT)
.format(Instant.now().atOffset(ZoneOffset.UTC).toLocalDate());
private boolean checkIndexExists(String indexName) {
ClusterState clusterState = clusterService.state();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can there be a corner scenario where the cluster state does not have up to date information? Are we handling this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, In theory the cluster state should be most up to date but there are scenarios when 2 threads are trying to create / delete the same index for the same time. If you look into the code I already handled with something like

Throwable cause = ExceptionsHelper.unwrapCause(e);
                        if (cause instanceof ResourceAlreadyExistsException) {

@@ -104,7 +116,7 @@ public List<SearchQueryRecord> read(final String from, final String to, String i
while (curr.isBefore(end.plusDays(1).toLocalDate().atStartOfDay(end.getZone()))) {
String indexName = buildLocalIndexName(curr);
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().size(1000);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to add a constant so this does not get lost in the code in case we want to change this in the future

// This method is invoked when sink type is changed
// Clear local indices if exporter is of type LocalIndexExporter
if (topQueriesExporter != null && topQueriesExporter.getClass() == LocalIndexExporter.class) {
deleteAllTopNIndices(client, indexMetadataMap, (LocalIndexExporter) topQueriesExporter);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we toggle between exports and back to local index exporter do we want to lose all the older data in this scenario?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's the expectation for now. Disabling local index exporter will delete all historical data. It was originally implemented in #172

.execute(() -> ((LocalIndexExporter) exporter).deleteExpiredTopNIndices(indexMetadataMap));
}
}
public static boolean isTopQueriesIndex(String indexName, IndexMetadata indexMetadata) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Do we want to add this to a helper/util?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should belongs to TopQueriesService though since we are checking if an index belongs to top n queries.

* Prefix for top n queries by memory exporters
*/
private static final String TOP_N_MEMORY_QUERIES_EXPORTER_PREFIX = TOP_N_MEMORY_QUERIES_PREFIX + ".exporter.";
private static final String TOP_N_QUERIES_EXPORTER_PREFIX = TOP_N_QUERIES_SETTING_PREFIX + ".exporter";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Self note: Will have to update the documentation since the current docs are now invalid.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I'll send a PR to update the document later.

verify(adminClient, times(3)).indices();
verify(indicesAdminClient, times(3)).delete(any(), any());
}
// public void testDeleteExpiredTopNIndices() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this commented out?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is moved to queryInsightsTests.

verify(localIndexExporter, times(9)).deleteSingleIndex(any(), any());
}

// TODO: comment out for now. Need to reenable this before mering
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Don't forget to resolve this

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

@ansjcy ansjcy force-pushed the refactor-exporter-and-reader branch from 851d174 to 9584b38 Compare January 26, 2025 00:54
Copy link
Collaborator

@deshsidd deshsidd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM overall with some minor comments.

@@ -22,4 +22,6 @@ public interface QueryInsightsExporter extends Closeable {
* @param records list of {@link SearchQueryRecord}
*/
void export(final List<SearchQueryRecord> records);

String getId();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: good to add some comments here since this is an interface and the intent may get lost over time

.format(Instant.now().atOffset(ZoneOffset.UTC).toLocalDate());
private boolean checkIndexExists(String indexName) {
ClusterState clusterState = clusterService.state();
return clusterState.getRoutingTable().hasIndex(indexName);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hope we don't need to handle any potential errors here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
} else {
// Disable exporter if exporter type is set to null
try {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Duplicated code few lines above, could refactor this out

}

queryInsightsService.deleteAllTopNIndices(client, indexMetadataMap, localIndexExporter);
// All 10 indices should be deleted
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

9 indices should be deleted?

@ansjcy
Copy link
Member Author

ansjcy commented Jan 27, 2025

@deshsidd Thanks for the review, I'll merge it for now to unblock the frontend, but we need to iterate from here to add missing doc/ refactor some code into util functions etc.

@ansjcy ansjcy merged commit 2d14764 into opensearch-project:main Jan 27, 2025
12 checks passed
opensearch-trigger-bot bot pushed a commit that referenced this pull request Jan 27, 2025
* Move exporter config to query insights level

Signed-off-by: Chenyang Ji <[email protected]>

* use index mapping and define default index metadata for top n queries

Signed-off-by: Chenyang Ji <[email protected]>

* improve safegard for deleting top queries indices with index mapping

Signed-off-by: Chenyang Ji <[email protected]>

* fix unit tests

Signed-off-by: Chenyang Ji <[email protected]>

* fix bug on local index reader with generateLocalIndexDateHash

Signed-off-by: Chenyang Ji <[email protected]>

* fix exception in query grouper

Signed-off-by: Chenyang Ji <[email protected]>

* update PR based on comments and re-enable unit tests

Signed-off-by: Chenyang Ji <[email protected]>

---------

Signed-off-by: Chenyang Ji <[email protected]>
(cherry picked from commit 2d14764)
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
ansjcy pushed a commit that referenced this pull request Jan 27, 2025
* Move exporter config to query insights level



* use index mapping and define default index metadata for top n queries



* improve safegard for deleting top queries indices with index mapping



* fix unit tests



* fix bug on local index reader with generateLocalIndexDateHash



* fix exception in query grouper



* update PR based on comments and re-enable unit tests



---------


(cherry picked from commit 2d14764)

Signed-off-by: Chenyang Ji <[email protected]>
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants