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

Add AggregationResultBucket #148

Merged
merged 1 commit into from
Aug 23, 2021
Merged
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
@@ -0,0 +1,93 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

package org.opensearch.alerting.model

import org.opensearch.common.ParsingException
import org.opensearch.common.io.stream.StreamInput
import org.opensearch.common.io.stream.StreamOutput
import org.opensearch.common.io.stream.Writeable
import org.opensearch.common.xcontent.ToXContent
import org.opensearch.common.xcontent.ToXContentObject
import org.opensearch.common.xcontent.XContentBuilder
import org.opensearch.common.xcontent.XContentParser
import org.opensearch.common.xcontent.XContentParser.Token
import org.opensearch.common.xcontent.XContentParserUtils.ensureExpectedToken
import java.io.IOException
import java.util.Locale

data class AggregationResultBucket(
val parentBucketPath: String?,
val bucketKeys: List<String>,
val bucket: Map<String, Any>? // TODO: Should reduce contents to only top-level to not include sub-aggs here
) : Writeable, ToXContentObject {

@Throws(IOException::class)
constructor(sin: StreamInput) : this(sin.readString(), sin.readStringList(), sin.readMap())

override fun writeTo(out: StreamOutput) {
out.writeString(parentBucketPath)
out.writeStringCollection(bucketKeys)
out.writeMap(bucket)
}

override fun toXContent(builder: XContentBuilder, params: ToXContent.Params): XContentBuilder {
builder.startObject()
innerXContent(builder)
return builder.endObject()
}

fun innerXContent(builder: XContentBuilder): XContentBuilder {
builder.startObject(CONFIG_NAME)
.field(PARENTS_BUCKET_PATH, parentBucketPath)
.field(BUCKET_KEYS, bucketKeys.toTypedArray())
.field(BUCKET, bucket)
.endObject()
return builder
}

companion object {
const val CONFIG_NAME = "agg_alert_content"
const val PARENTS_BUCKET_PATH = "parent_bucket_path"
const val BUCKET_KEYS = "bucket_keys"
private const val BUCKET = "bucket"

fun parse(xcp: XContentParser): AggregationResultBucket {
var parentBucketPath: String? = null
var bucketKeys = mutableListOf<String>()
var bucket: MutableMap<String, Any>? = null
ensureExpectedToken(XContentParser.Token.START_OBJECT, xcp.currentToken(), xcp)

if (CONFIG_NAME != xcp.currentName()) {
throw ParsingException(xcp.tokenLocation,
String.format(
Locale.ROOT, "Failed to parse object: expecting token with name [%s] but found [%s]",
CONFIG_NAME, xcp.currentName())
)
}
while (xcp.nextToken() != Token.END_OBJECT) {
val fieldName = xcp.currentName()
xcp.nextToken()
when (fieldName) {
PARENTS_BUCKET_PATH -> parentBucketPath = xcp.text()
BUCKET_KEYS -> {
ensureExpectedToken(Token.START_ARRAY, xcp.currentToken(), xcp)
while (xcp.nextToken() != Token.END_ARRAY) {
bucketKeys.add(xcp.text())
}
}
BUCKET -> bucket = xcp.map()
}
}
return AggregationResultBucket(parentBucketPath, bucketKeys, bucket)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import inet.ipaddr.IPAddressString
import org.opensearch.OpenSearchStatusException
import org.opensearch.action.ActionListener
import org.opensearch.alerting.destination.message.BaseMessage
import org.opensearch.alerting.model.AggregationResultBucket
import org.opensearch.alerting.model.destination.Destination
import org.opensearch.alerting.settings.DestinationSettings
import org.opensearch.commons.authuser.User
Expand Down Expand Up @@ -139,3 +140,9 @@ fun <T : Any> checkUserFilterByPermissions(
}
return true
}

/**
* Since buckets can have multi-value keys, this converts the bucket key values to a string that can be used
* as the key for a HashMap to easily retrieve [AggregationResultBucket] based on the bucket key values.
*/
fun AggregationResultBucket.getBucketKeysHash(): String = this.bucketKeys.joinToString(separator = "#")