This is the fourth day of my participation in the November Gwen Challenge. Check out the details: The last Gwen Challenge 2021
Front that
Skywalking is a distributed link tracking system (application performance monitoring tool) developed by Chinese people. This article focuses on how GraphQL is applied in the project, other core features and implementation, and will be supplemented later.
I mentioned how to configure the Skywalking development environment locally in my previous article: IDEA Configuring the Skywalking development environment. If you are interested in the above blog to clone the code down, configure, to the source code.
Or just look below and I’ll post the key code.
The following is for Skywalking version 8.5.0.
Skywalking application GraphQL source code
GraphQL rely on
The following dependencies are not exactly the same as the ones I used in my previous articles and examples:
< the dependency > < groupId > com. Graphql - Java < / groupId > < artifactId > graphql - Java - tools < / artifactId > < version > 5.2.3 requires < / version > </dependency> <dependency> <groupId>com.graphql-java</groupId> <artifactId>graphql-java</artifactId> The < version > 8.0 < / version > < / dependency >Copy the code
Initialize GraphQL
Initialization mode
The GraphQL instance is initialized in the following class, in the prepare method
oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/GraphQLQueryPr ovider.javaCopy the code
There is not much to say about its initialization, but I used it in similar ways in the previous sample of GraphQL and in the example of GraphQL being used quickly in the Spring Boot project.
GraphQLSchema schema = SchemaParser.newParser() .file("query-protocol/common.graphqls") .resolvers(new Query(), new Mutation(), new HealthQuery(getManager())) .file("query-protocol/metadata.graphqls") .resolvers(new MetadataQuery(getManager())) // . File ("query-protocol/event.graphqls").resolvers(new EventQuery(getManager())).build() .makeExecutableSchema(); this.graphQL = GraphQL.newGraphQL(schema).build();Copy the code
Initialization time
Using the debug call stack, you can quickly see where and by whom the prepare method was called to initialize GraphQL:
The oapserverstart #main() and OAPServerBootstrap#start() methods are both simpler, with a focus on MoudleManager#init() as follows:
QueryMoulde initializes the GraphQL instance when all modules are loaded in the first step.
Apply the GraphQL instance
Having initialized the GraphQL instance earlier, we need to take a look at how it is nested within an Http Server. Here’s the code, again in the GraphQLProvider class:
The start method is called in the second step of start in the screenshot above, when the start() method of all loaded Modules is called.
GraphQLQueryHandler is a subclass of HttpServlet, and GraphQL is passed in as a construct argument:
Take a look at the implementation of the GraphQLQueryHandler. I’ve removed all the irrelevant code, leaving only the core code:
@RequiredArgsConstructor public class GraphQLQueryHandler extends JettyJsonHandler { @Override protected JsonElement DoGet (it the req) {/ / not supported GET request throw new UnsupportedOperationException (" GraphQL only supports the POST method"); } @Override protected JsonElement doPost(HttpServletRequest req) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(req.getInputStream())); String line; StringBuilder request = new StringBuilder(); while ((line = reader.readLine()) ! = null) { request.append(line); } JsonObject requestJson = gson.fromJson(request.toString(), JsonObject.class); // When the parameters are parsed, Return execute(requestjson.get (QUERY).getasString (), gson.fromjson (requestjson.get (VARIABLES), mapOfStringObjectType)); } private JsonObject execute(String request, Map<String, Object> variables) { try { ExecutionInput executionInput = ExecutionInput.newExecutionInput() .query(request) .variables(variables) .build(); ExecutionResult executionResult = graphQL.execute(executionInput); LOGGER.debug("Execution result is {}", executionResult); Object data = executionResult.getData(); List<GraphQLError> errors = executionResult.getErrors(); JsonObject jsonObject = new JsonObject(); if (data ! Jsonobject.add (DATA, gson.fromjson (gson.tojson (DATA), jsonObject.class)); } / / exception handling the if (CollectionUtils isNotEmpty (errors)) {JsonArray errorArray = new JsonArray (); errors.forEach(error -> { JsonObject errorJson = new JsonObject(); errorJson.addProperty(MESSAGE, error.getMessage()); errorArray.add(errorJson); }); jsonObject.add(ERRORS, errorArray); } return jsonObject; } catch (final Throwable e) {// Return jsonObject; }}}Copy the code
As you can see, the Get request is not supported. When the Post request comes in, it parses the parameters, makes the call, and returns the result.
In the call screenshot service.addHandler(…) Method to register the servert with the following call stack:
This JettyServer is implemented by SkyWalking itself:
Expose interfaces and provide services
Finally, take a look at what time SkyWalking starts the Http Server, and take a look at the debug stack:
In step 3 of our previous screenshot, notifyAfterCompleted(), all of the notifyAfterCompleted methods that load the Module are called, and this one belongs to CoreModuleProvider, as follows:
At this point, the whole process has been connected.