@@ -11,7 +11,7 @@ use crate::cheap_clone::CheapClone;
1111use crate :: data:: graphql:: { ObjectOrInterface , ObjectTypeExt , TypeExt } ;
1212use crate :: data:: store:: IdType ;
1313use crate :: env:: ENV_VARS ;
14- use crate :: schema:: { ast, META_FIELD_NAME , META_FIELD_TYPE , SCHEMA_TYPE_NAME } ;
14+ use crate :: schema:: { ast, LOGS_FIELD_NAME , META_FIELD_NAME , META_FIELD_TYPE , SCHEMA_TYPE_NAME } ;
1515
1616use crate :: data:: graphql:: ext:: {
1717 camel_cased_names, DefinitionExt , DirectiveExt , DocumentExt , ValueExt ,
@@ -350,7 +350,7 @@ pub(in crate::schema) fn api_schema(
350350) -> Result < s:: Document , APISchemaError > {
351351 // Refactor: Don't clone the schema.
352352 let mut api = init_api_schema ( input_schema) ?;
353- add_meta_field_type ( & mut api. document ) ;
353+ add_builtin_field_types ( & mut api. document ) ;
354354 add_types_for_object_types ( & mut api, input_schema) ?;
355355 add_types_for_interface_types ( & mut api, input_schema) ?;
356356 add_types_for_aggregation_types ( & mut api, input_schema) ?;
@@ -445,18 +445,24 @@ fn init_api_schema(input_schema: &InputSchema) -> Result<Schema, APISchemaError>
445445 . map_err ( |e| APISchemaError :: SchemaCreationFailed ( e. to_string ( ) ) )
446446}
447447
448- /// Adds a global `_Meta_` type to the schema. The `_meta` field
449- /// accepts values of this type
450- fn add_meta_field_type ( api : & mut s:: Document ) {
448+ /// Adds built-in field types to the schema. Currently adds `_Meta_` and `_Log_` types
449+ /// which are used by the `_meta` and `_logs` fields respectively.
450+ fn add_builtin_field_types ( api : & mut s:: Document ) {
451451 lazy_static ! {
452452 static ref META_FIELD_SCHEMA : s:: Document = {
453453 let schema = include_str!( "meta.graphql" ) ;
454454 s:: parse_schema( schema) . expect( "the schema `meta.graphql` is invalid" )
455455 } ;
456+ static ref LOGS_FIELD_SCHEMA : s:: Document = {
457+ let schema = include_str!( "logs.graphql" ) ;
458+ s:: parse_schema( schema) . expect( "the schema `logs.graphql` is invalid" )
459+ } ;
456460 }
457461
458462 api. definitions
459463 . extend ( META_FIELD_SCHEMA . definitions . iter ( ) . cloned ( ) ) ;
464+ api. definitions
465+ . extend ( LOGS_FIELD_SCHEMA . definitions . iter ( ) . cloned ( ) ) ;
460466}
461467
462468fn add_types_for_object_types (
@@ -1073,6 +1079,7 @@ fn add_query_type(api: &mut s::Document, input_schema: &InputSchema) -> Result<(
10731079 fields. append ( & mut agg_fields) ;
10741080 fields. append ( & mut fulltext_fields) ;
10751081 fields. push ( meta_field ( ) ) ;
1082+ fields. push ( logs_field ( ) ) ;
10761083
10771084 let typedef = s:: TypeDefinition :: Object ( s:: ObjectType {
10781085 position : Pos :: default ( ) ,
@@ -1278,6 +1285,102 @@ fn meta_field() -> s::Field {
12781285 META_FIELD . clone ( )
12791286}
12801287
1288+ fn logs_field ( ) -> s:: Field {
1289+ lazy_static ! {
1290+ static ref LOGS_FIELD : s:: Field = s:: Field {
1291+ position: Pos :: default ( ) ,
1292+ description: Some (
1293+ "Query execution logs emitted by the subgraph during indexing. \
1294+ Results are sorted by timestamp in descending order (newest first)."
1295+ . to_string( )
1296+ ) ,
1297+ name: LOGS_FIELD_NAME . to_string( ) ,
1298+ arguments: vec![
1299+ // level: LogLevel
1300+ s:: InputValue {
1301+ position: Pos :: default ( ) ,
1302+ description: Some (
1303+ "Filter logs by severity level. Only logs at this level will be returned."
1304+ . to_string( )
1305+ ) ,
1306+ name: String :: from( "level" ) ,
1307+ value_type: s:: Type :: NamedType ( String :: from( "LogLevel" ) ) ,
1308+ default_value: None ,
1309+ directives: vec![ ] ,
1310+ } ,
1311+ // from: String (RFC3339 timestamp)
1312+ s:: InputValue {
1313+ position: Pos :: default ( ) ,
1314+ description: Some (
1315+ "Filter logs from this timestamp onwards (inclusive). \
1316+ Must be in RFC3339 format (e.g., '2024-01-15T10:30:00Z')."
1317+ . to_string( )
1318+ ) ,
1319+ name: String :: from( "from" ) ,
1320+ value_type: s:: Type :: NamedType ( String :: from( "String" ) ) ,
1321+ default_value: None ,
1322+ directives: vec![ ] ,
1323+ } ,
1324+ // to: String (RFC3339 timestamp)
1325+ s:: InputValue {
1326+ position: Pos :: default ( ) ,
1327+ description: Some (
1328+ "Filter logs until this timestamp (inclusive). \
1329+ Must be in RFC3339 format (e.g., '2024-01-15T23:59:59Z')."
1330+ . to_string( )
1331+ ) ,
1332+ name: String :: from( "to" ) ,
1333+ value_type: s:: Type :: NamedType ( String :: from( "String" ) ) ,
1334+ default_value: None ,
1335+ directives: vec![ ] ,
1336+ } ,
1337+ // search: String (full-text search)
1338+ s:: InputValue {
1339+ position: Pos :: default ( ) ,
1340+ description: Some (
1341+ "Search for logs containing this text in the message. \
1342+ Case-insensitive substring match. Maximum length: 1000 characters."
1343+ . to_string( )
1344+ ) ,
1345+ name: String :: from( "search" ) ,
1346+ value_type: s:: Type :: NamedType ( String :: from( "String" ) ) ,
1347+ default_value: None ,
1348+ directives: vec![ ] ,
1349+ } ,
1350+ // first: Int (default 100, max 1000)
1351+ s:: InputValue {
1352+ position: Pos :: default ( ) ,
1353+ description: Some (
1354+ "Maximum number of logs to return. Default: 100, Maximum: 1000."
1355+ . to_string( )
1356+ ) ,
1357+ name: String :: from( "first" ) ,
1358+ value_type: s:: Type :: NamedType ( String :: from( "Int" ) ) ,
1359+ default_value: Some ( s:: Value :: Int ( 100 . into( ) ) ) ,
1360+ directives: vec![ ] ,
1361+ } ,
1362+ // skip: Int (default 0, max 10000)
1363+ s:: InputValue {
1364+ position: Pos :: default ( ) ,
1365+ description: Some (
1366+ "Number of logs to skip (for pagination). Default: 0, Maximum: 10000."
1367+ . to_string( )
1368+ ) ,
1369+ name: String :: from( "skip" ) ,
1370+ value_type: s:: Type :: NamedType ( String :: from( "Int" ) ) ,
1371+ default_value: Some ( s:: Value :: Int ( 0 . into( ) ) ) ,
1372+ directives: vec![ ] ,
1373+ } ,
1374+ ] ,
1375+ field_type: s:: Type :: NonNullType ( Box :: new( s:: Type :: ListType ( Box :: new(
1376+ s:: Type :: NonNullType ( Box :: new( s:: Type :: NamedType ( String :: from( "_Log_" ) ) ) ) ,
1377+ ) ) ) ) ,
1378+ directives: vec![ ] ,
1379+ } ;
1380+ }
1381+ LOGS_FIELD . clone ( )
1382+ }
1383+
12811384#[ cfg( test) ]
12821385mod tests {
12831386 use crate :: {
0 commit comments