runtime: emit metering events via public seam

This commit is contained in:
github-ops
2026-05-15 14:12:59 +00:00
parent 280ea99628
commit 42312ff76f
10 changed files with 270 additions and 19 deletions
+45 -2
View File
@@ -4,7 +4,7 @@ use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::{ExecutionMode, Protocol, StreamSession, Target};
use crate::{AgentId, ExecutionMode, InvocationSource, Protocol, StreamSession, Target, WorkspaceId};
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct ResponseCacheScope {
@@ -17,6 +17,14 @@ pub struct RuntimeRequestContext {
pub request_id: String,
pub correlation_id: String,
pub response_cache_scope: Option<ResponseCacheScope>,
pub metering_context: Option<MeteringContext>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MeteringContext {
pub workspace_id: WorkspaceId,
pub agent_id: Option<AgentId>,
pub source: InvocationSource,
}
impl RuntimeRequestContext {
@@ -25,6 +33,7 @@ impl RuntimeRequestContext {
request_id: request_id.into(),
correlation_id: correlation_id.into(),
response_cache_scope: None,
metering_context: None,
}
}
@@ -55,6 +64,24 @@ impl RuntimeRequestContext {
pub fn response_cache_scope(&self) -> Option<&ResponseCacheScope> {
self.response_cache_scope.as_ref()
}
pub fn with_metering_context(
mut self,
workspace_id: WorkspaceId,
agent_id: Option<AgentId>,
source: InvocationSource,
) -> Self {
self.metering_context = Some(MeteringContext {
workspace_id,
agent_id,
source,
});
self
}
pub fn metering_context(&self) -> Option<&MeteringContext> {
self.metering_context.as_ref()
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Default)]
@@ -191,7 +218,9 @@ mod tests {
AdapterRegistry, AdapterResponse, PreparedRequest, ProtocolAdapter, ProtocolAdapterError,
RuntimeRequestContext,
};
use crate::{ExecutionMode, HttpMethod, Protocol, RestTarget, Target};
use crate::{
ExecutionMode, HttpMethod, InvocationSource, Protocol, RestTarget, Target, WorkspaceId,
};
#[derive(Clone)]
struct StubAdapter(Protocol);
@@ -253,6 +282,20 @@ mod tests {
assert_eq!(scope.agent_key, "agent_01");
}
#[test]
fn request_context_attaches_metering_context() {
let context = RuntimeRequestContext::from_request_id("req_123").with_metering_context(
WorkspaceId::new("ws_01"),
None,
InvocationSource::AgentToolCall,
);
let metering = context.metering_context().unwrap();
assert_eq!(metering.workspace_id, WorkspaceId::new("ws_01"));
assert_eq!(metering.agent_id, None);
assert_eq!(metering.source, InvocationSource::AgentToolCall);
}
#[tokio::test]
async fn registry_returns_registered_adapter() {
let registry = AdapterRegistry::empty().register(Arc::new(StubAdapter(Protocol::Rest)));
+2 -1
View File
@@ -54,7 +54,8 @@ pub use ext::capability::{CapabilityProfile, CommunityCapabilityProfile};
pub use ext::metering::{MeteringEvent, MeteringSink, NoopMeteringSink, SharedMeteringSink};
pub use ext::protocol::{
AdapterRegistry, AdapterResponse, PreparedRequest, ProtocolAdapter, ProtocolAdapterError,
ResponseCacheScope, RuntimeRequestContext, SharedProtocolAdapter, WindowExecutionResult,
MeteringContext, ResponseCacheScope, RuntimeRequestContext, SharedProtocolAdapter,
WindowExecutionResult,
};
pub use ext::tenancy::{
SharedTenantController, SingleTenantController, TenantController, TenantResolutionContext,