const rootValue = { | |
user, | |
client, | |
...root, | |
__timing: [] // store the timing info in here -- sorta hacky! | |
} | |
return graphql(schema, query, rootValue, variables).then(response => { | |
response.__timing = rootValue.__timing; // take the timing info and shove it in the result now | |
return response; | |
}); |
// time resolve functions ... I hope I am promising correctly! | |
const withTiming = (next) => { | |
return (obj, args, info) => { | |
const start = new Date().getTime(); | |
return Promise.resolve(next(obj, args, info)).then(res => { | |
info.rootValue.__timing.push({ | |
status: 'ok', | |
type: info.parentType.name, | |
field: info.fieldName, | |
args, | |
duration: (new Date().getTime() - start) / 1000 | |
}); | |
return res; | |
}, err => { | |
info.rootValue.__timing.push({ | |
status: 'error', | |
type: info.parentType.name, | |
field: info.fieldName, | |
args, | |
duration: (new Date().getTime() - start) / 1000 | |
}); | |
return Promise.reject(err); | |
}); | |
} | |
} | |
// default resolve fn | |
const dot = (name) => { | |
return obj => obj ? obj[name] : null; | |
} | |
// modify the schema -- add middleware to every resolve function, lulz | |
Object.keys(schema.getTypeMap()) | |
.filter(typeName => typeName.indexOf('__') !== 0) // remove schema fields... | |
.map(typeName => schema.getType(typeName)) | |
.filter(type => type instanceof GraphQLObjectType) // make sure its an object | |
.forEach(type => { | |
let fields = type.getFields(); | |
Object.keys(fields).forEach(fieldName => { | |
let field = fields[fieldName] | |
field.resolve = withTiming(field.resolve || dot(fieldName)); | |
}); | |
}); |
// omg incredibly boring timing | |
// ... toods I added a 1500 setTimeout at least :p | |
{ | |
"data": { | |
"viewer": { | |
"id": "9b0be370-8417-11e5-bfe9-95f5551e5224", | |
"todos": [ | |
{ | |
"id": "9b0be371-8417-11e5-bfe9-95f5551e5224", | |
"text": "Buy a unicorn", | |
"completed": false | |
}, | |
{ | |
"id": "9b0be372-8417-11e5-bfe9-95f5551e5224", | |
"text": "Try out GraphQL Subscriptions", | |
"completed": false | |
} | |
], | |
"clients": [ | |
{ | |
"id": "9b0be373-8417-11e5-bfe9-95f5551e5224", | |
"type": "WEBSOCKET", | |
"subscriptions": [] | |
} | |
] | |
} | |
}, | |
"__timing": [ | |
{ | |
"status": "ok", | |
"type": "QueryRoot", | |
"field": "viewer", | |
"args": {}, | |
"duration": 0 | |
}, | |
{ | |
"status": "ok", | |
"type": "Viewer", | |
"field": "id", | |
"args": {}, | |
"duration": 0 | |
}, | |
{ | |
"status": "ok", | |
"type": "Viewer", | |
"field": "clients", | |
"args": {}, | |
"duration": 0 | |
}, | |
{ | |
"status": "ok", | |
"type": "WebsocketClient", | |
"field": "id", | |
"args": {}, | |
"duration": 0 | |
}, | |
{ | |
"status": "ok", | |
"type": "WebsocketClient", | |
"field": "type", | |
"args": {}, | |
"duration": 0 | |
}, | |
{ | |
"status": "ok", | |
"type": "WebsocketClient", | |
"field": "subscriptions", | |
"args": {}, | |
"duration": 0 | |
}, | |
{ | |
"status": "ok", | |
"type": "Viewer", | |
"field": "todos", | |
"args": {}, | |
"duration": 1.503 | |
}, | |
{ | |
"status": "ok", | |
"type": "Todo", | |
"field": "id", | |
"args": {}, | |
"duration": 0.001 | |
}, | |
{ | |
"status": "ok", | |
"type": "Todo", | |
"field": "text", | |
"args": {}, | |
"duration": 0.001 | |
}, | |
{ | |
"status": "ok", | |
"type": "Todo", | |
"field": "completed", | |
"args": {}, | |
"duration": 0.001 | |
}, | |
{ | |
"status": "ok", | |
"type": "Todo", | |
"field": "id", | |
"args": {}, | |
"duration": 0.001 | |
}, | |
{ | |
"status": "ok", | |
"type": "Todo", | |
"field": "text", | |
"args": {}, | |
"duration": 0.001 | |
}, | |
{ | |
"status": "ok", | |
"type": "Todo", | |
"field": "completed", | |
"args": {}, | |
"duration": 0.001 | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment