Skip to content

Commit

Permalink
Merge pull request #2525 from Tharsanan1/ai-analytics
Browse files Browse the repository at this point in the history
Add AI Analytics
  • Loading branch information
CrowleyRajapakse authored Oct 2, 2024
2 parents 3ff1612 + fd4654a commit b4b3312
Show file tree
Hide file tree
Showing 7 changed files with 348 additions and 54 deletions.
3 changes: 3 additions & 0 deletions adapter/internal/oasparser/envoyconf/http_filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,9 @@ func getExtProcessHTTPFilter() *hcmv3.HttpFilter {
ForwardingNamespaces: &ext_process.MetadataOptions_MetadataNamespaces{
Untyped: []string{"envoy.filters.http.ext_authz", "envoy.filters.http.ext_proc"},
},
ReceivingNamespaces: &ext_process.MetadataOptions_MetadataNamespaces{
Untyped: []string{"envoy.filters.http.ext_proc"},
},
},
RequestAttributes: []string{"xds.route_metadata"},
ResponseAttributes: []string{"xds.route_metadata"},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.wso2.apk.enforcer.commons.analytics.publishers.dto;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
* AI metadata in analytics event.
*/
public class AIMetadata {
@JsonProperty("model")
private String model;

@JsonProperty("vendor_name")
private String vendorName;

@JsonProperty("vendor_version")
private String vendorVersion;

public String getModel() {

return model;
}

public void setModel(String model) {

this.model = model;
}

public String getVendorName() {

return vendorName;
}

public void setVendorName(String vendorName) {

this.vendorName = vendorName;
}

public String getVendorVersion() {

return vendorVersion;
}

public void setVendorVersion(String vendorVersion) {

this.vendorVersion = vendorVersion;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.wso2.apk.enforcer.commons.analytics.publishers.dto;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
* AI token usage in analytics event.
*/
public class AITokenUsage {
@JsonProperty("totalTokens")
private Double totalTokens;

@JsonProperty("promptTokens")
private Double promptTokens;

@JsonProperty("completionTokens")
private Double completionTokens;

@JsonProperty("hour")
private Integer hour;

public Double getTotalTokens() {

return totalTokens;
}

public Integer getHour() {

return hour;
}

public void setHour(Integer hour) {

this.hour = hour;
}

public void setTotalTokens(Double totalTokens) {

this.totalTokens = totalTokens;
}

public Double getPromptTokens() {

return promptTokens;
}

public void setPromptTokens(Double promptTokens) {

this.promptTokens = promptTokens;
}

public Double getCompletionTokens() {

return completionTokens;
}

public void setCompletionTokens(Double completionTokens) {

this.completionTokens = completionTokens;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@

package org.wso2.apk.enforcer.analytics;

import com.google.protobuf.Struct;
import com.google.protobuf.Value;
import io.envoyproxy.envoy.data.accesslog.v3.AccessLogCommon;
import io.envoyproxy.envoy.data.accesslog.v3.HTTPAccessLogEntry;
import io.envoyproxy.envoy.service.ext_proc.v3.ProcessingResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.wso2.apk.enforcer.commons.analytics.collectors.AnalyticsCustomDataProvider;
import org.wso2.apk.enforcer.commons.analytics.collectors.AnalyticsDataProvider;
import org.wso2.apk.enforcer.commons.analytics.publishers.dto.AIMetadata;
import org.wso2.apk.enforcer.commons.analytics.publishers.dto.AITokenUsage;
import org.wso2.apk.enforcer.commons.analytics.publishers.dto.API;
import org.wso2.apk.enforcer.commons.analytics.publishers.dto.Application;
import org.wso2.apk.enforcer.commons.analytics.publishers.dto.Error;
Expand Down Expand Up @@ -252,6 +256,32 @@ public Map<String, Object> getProperties() {
Map<String,Object> map = new HashMap();
Map<String, Value> fieldsMap = getFieldsMapFromLogEntry();
String gwURL = getValueAsString(fieldsMap, MetadataConstants.GATEWAY_URL);
Double totalTokenCount = getValueAsDouble(fieldsMap, MetadataConstants.TOTAL_TOKEN_COUNT);
Double completionTokenCount = getValueAsDouble(fieldsMap, MetadataConstants.COMPLETION_TOKEN_COUNT);
Double promptTokenCount = getValueAsDouble(fieldsMap, MetadataConstants.PROMPT_TOKEN_COUNT);
String model = getValueAsString(fieldsMap, MetadataConstants.MODEL);
String providerName = getValueAsString(fieldsMap, MetadataConstants.AI_PROVIDER_NAME);
String providerAPIVersion = getValueAsString(fieldsMap, MetadataConstants.AI_PROVIDER_API_VERSION);

// AI Token Usage
AITokenUsage aiTokenUsage = new AITokenUsage();
if (totalTokenCount != null) aiTokenUsage.setTotalTokens(totalTokenCount);
if (promptTokenCount != null) aiTokenUsage.setPromptTokens(promptTokenCount);
if (completionTokenCount != null) aiTokenUsage.setCompletionTokens(completionTokenCount);

if (aiTokenUsage.getTotalTokens() != null || aiTokenUsage.getPromptTokens() != null || aiTokenUsage.getCompletionTokens() != null) {
map.put("aiTokenUsage", aiTokenUsage);
}

// AI Metadata
AIMetadata aiMetadata = new AIMetadata();
if (model != null) aiMetadata.setModel(model);
if (providerName != null) aiMetadata.setVendorName(providerName);
if (providerAPIVersion != null) aiMetadata.setVendorVersion(providerAPIVersion);

if (aiMetadata.getModel() != null || aiMetadata.getVendorName() != null || aiMetadata.getVendorVersion() != null) {
map.put("aiMetadata", aiMetadata);
}
map.put(AnalyticsConstants.GATEWAY_URL, gwURL);
if (customDataProvider != null && customDataProvider.getCustomProperties(customProperties) != null) {
Map<String, Object> customPropertiesFromProvider = customDataProvider.getCustomProperties(customProperties);
Expand All @@ -272,6 +302,14 @@ private String getValueAsString(Map<String, Value> fieldsMap, String key) {
return fieldsMap.get(key).getStringValue();
}

private Double getValueAsDouble(Map<String, Value> fieldsMap, String key) {

if (fieldsMap == null || !fieldsMap.containsKey(key)) {
return null;
}
return fieldsMap.get(key).getNumberValue();
}

private Map<String, Value> getFieldsMapFromLogEntry() {

if (logEntry.getCommonProperties() == null
Expand All @@ -281,8 +319,21 @@ private Map<String, Value> getFieldsMapFromLogEntry() {
.containsKey(MetadataConstants.EXT_AUTH_METADATA_CONTEXT_KEY)) {
return new HashMap<>(0);
}
return logEntry.getCommonProperties().getMetadata().getFilterMetadataMap()
Map<String, Value> metadataFromExtProc = logEntry.getCommonProperties().getMetadata().getFilterMetadataMap()
.get(MetadataConstants.EXT_PROC_METADATA_CONTEXT_KEY).getFieldsMap();
Map<String, Value> metadataFromExtAuthz = logEntry.getCommonProperties().getMetadata().getFilterMetadataMap()
.get(MetadataConstants.EXT_AUTH_METADATA_CONTEXT_KEY).getFieldsMap();
Map<String, Value> mergedMetadata = new HashMap<>(metadataFromExtProc);
mergedMetadata.putAll(metadataFromExtAuthz);
return mergedMetadata;
}

private void addMetadata(Struct.Builder structBuilder, String key, String value) {
structBuilder.putFields(key, Value.newBuilder().setStringValue(value).build());
}

private void addMetadata(Struct.Builder structBuilder, String key, double value) {
structBuilder.putFields(key, Value.newBuilder().setNumberValue(value).build());
}

private void setCustomPropertiesMap(HTTPAccessLogEntry logEntry, Map<String, Object> customProperties) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*/
public class MetadataConstants {
public static final String EXT_AUTH_METADATA_CONTEXT_KEY = "envoy.filters.http.ext_authz";

public static final String EXT_PROC_METADATA_CONTEXT_KEY = "envoy.filters.http.ext_proc";
public static final String WSO2_METADATA_PREFIX = "x-wso2-";
public static final String API_ID_KEY = WSO2_METADATA_PREFIX + "api-id";
public static final String API_CREATOR_KEY = WSO2_METADATA_PREFIX + "api-creator";
Expand Down Expand Up @@ -57,5 +57,18 @@ public class MetadataConstants {
public static final String RATELIMIT_WSO2_ORG_PREFIX = "customorg";
public static final String GATEWAY_URL = WSO2_METADATA_PREFIX + "x-original-gw-url";
public static final String API_ENVIRONMENT = WSO2_METADATA_PREFIX + "api-environment";
public static final String ORGANIZATION_AND_AIRL_POLICY = "ratelimit:organization-and-rlpolicy";
public static final String SUBSCRIPTION = "ratelimit:subscription";
public static final String EXTRACT_TOKEN_FROM = "aitoken:extracttokenfrom";
public static final String PROMPT_TOKEN_ID = "aitoken:prompttokenid";
public static final String COMPLETION_TOKEN_ID = "aitoken:completiontokenid";
public static final String TOTAL_TOKEN_ID = "aitoken:totaltokenid";
public static final String PROMPT_TOKEN_COUNT = "aitoken:prompttokencount";
public static final String COMPLETION_TOKEN_COUNT = "aitoken:completiontokencount";
public static final String TOTAL_TOKEN_COUNT = "aitoken:totaltokencount";
public static final String MODEL_ID = "aitoken:modelid";
public static final String MODEL = "aitoken:model";
public static final String AI_PROVIDER_NAME = "ai:providername";
public static final String AI_PROVIDER_API_VERSION = "ai:providerversion";

}
Loading

0 comments on commit b4b3312

Please sign in to comment.