Merge pull request #707 from apache/feature/ui-protocol
Init ui-protocol
This commit is contained in:
commit
8399452ec8
|
|
@ -27,7 +27,13 @@
|
|||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>apm-ui-query</artifactId>
|
||||
<artifactId>apm-ui-protocol</artifactId>
|
||||
|
||||
|
||||
</project>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.graphql-java</groupId>
|
||||
<artifactId>graphql-java</artifactId>
|
||||
<version>6.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
# Abstract
|
||||
**apm-ui-protocol** declares all services, using GraphQL API style, which provide by Collector UI module.
|
||||
|
||||
## Services
|
||||
### [Common](common.graphqls)
|
||||
|
||||
Include common objects, which used in global
|
||||
|
||||
### [Overview Layer Service](overview-layer.graphqls)
|
||||
|
||||
Query data without specific application, server or service. It includes info for overview the whole cluster.
|
||||
|
||||
### [Application Layer Service](application-layer.graphqls)
|
||||
|
||||
Query application related data with specific application code.
|
||||
|
||||
### [Server Layer Service](server-layer.graphqls)
|
||||
|
||||
Query server related data with specific server id.
|
||||
|
||||
### [Service Layer Service](service-layer.graphqls)
|
||||
|
||||
Query service related data with specific service id
|
||||
|
||||
### [Trace Service](trace.graphqls)
|
||||
|
||||
Query trace by some conditions.
|
||||
|
||||
### [Alarm Service](alarm.graphqls)
|
||||
|
||||
Query alarm info.
|
||||
|
||||
## Version
|
||||
v1alpha1
|
||||
|
||||
### Versioning
|
||||
Use URI Versioning, to follow the most straightforward approach,
|
||||
though it does violate the principle that a URI should refer to a unique resource.
|
||||
|
||||
e.g.
|
||||
http://collector.host/graphql/v1alpha1
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
type AlarmItem {
|
||||
content: String!
|
||||
startTime: String!
|
||||
alertType: AlarmType!
|
||||
}
|
||||
|
||||
enum AlarmType {
|
||||
APPLICATION,
|
||||
SERVER,
|
||||
SERVICE
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
loadAlertList(keyword: String, alertType: AlarmType, duration:Duration!):[AlarmItem]
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# ApplicationNode represents this node is under monitoring by agent.
|
||||
type ApplicationNode implements Node {
|
||||
id: ID!
|
||||
name: String!
|
||||
type: String
|
||||
# Success rate of all incoming requests.
|
||||
# Max value is 100.
|
||||
# 2 Digits after floating point.
|
||||
sla: Float!
|
||||
# The number of incoming calls
|
||||
calls: Long!
|
||||
# ref: http://www.apdex.org/
|
||||
# Max value is 1
|
||||
# 2 Digits after floating point.
|
||||
apdex: Float!
|
||||
# The number of servers in the application code
|
||||
numOfServer: Int!
|
||||
# The number of servers alerting
|
||||
numOfServerAlarm: Int!
|
||||
# The number of services alerting
|
||||
numOfServiceAlarm: Int!
|
||||
}
|
||||
|
||||
# The conjectural node generated by exit span
|
||||
type ConjecturalNode implements Node {
|
||||
id: ID!
|
||||
name: String!
|
||||
type: String
|
||||
}
|
||||
|
||||
|
||||
extend type Query {
|
||||
getAllApplication(duration: Duration!): [ApplicationNode]
|
||||
getApplicationTopology(applicationId: ID!, duration: Duration!): Topology
|
||||
getSlowService(applicationId: ID!, duration: Duration!): [ServiceInfo!]
|
||||
getServerThroughput(applicationId: ID!, duration: Duration!): [AppServerInfo!]
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
schema {
|
||||
query: Query
|
||||
}
|
||||
|
||||
#Root node
|
||||
type Query {
|
||||
version: String
|
||||
}
|
||||
|
||||
# The Duration defines the start and end time for each query operation.
|
||||
# Fields: `start` and `end`
|
||||
# represents the time span. And each of them matches the step.
|
||||
# ref https://www.ietf.org/rfc/rfc3339.txt
|
||||
# The time formats are
|
||||
# `SECOND` step: yyyy-MM-dd HHmmss
|
||||
# `MINUTE` step: yyyy-MM-dd HHmm
|
||||
# `HOUR` step: yyyy-MM-dd HH
|
||||
# `DAY` step: yyyy-MM-dd
|
||||
# `MONTH` step: yyyy-MM
|
||||
# Field: `step`
|
||||
# represents the accurate time point.
|
||||
# e.g.
|
||||
# if step==HOUR , start=2017-11-08 09, end=2017-11-08 19
|
||||
# then
|
||||
# metrics from the following time points expected
|
||||
# 2017-11-08 9:00 -> 2017-11-08 19:00
|
||||
# there are 11 time points (hours) in the time span.
|
||||
input Duration {
|
||||
start: String!
|
||||
end: String!
|
||||
step: Step!
|
||||
}
|
||||
|
||||
enum Step {
|
||||
MONTH
|
||||
DAY
|
||||
HOUR
|
||||
MINUTE
|
||||
SECOND
|
||||
}
|
||||
|
||||
######################################
|
||||
# Common Metrics and Trends
|
||||
######################################
|
||||
type ResponseTimeTrend {
|
||||
trendList: [Int!]
|
||||
}
|
||||
|
||||
type ThroughputTrend {
|
||||
trendList: [Int!]
|
||||
}
|
||||
|
||||
type SLATrend {
|
||||
trendList: [Int!]
|
||||
}
|
||||
|
||||
# The overview topology of the whole application cluster or services,
|
||||
type Topology {
|
||||
nodes: [Node]!
|
||||
calls: [Call]
|
||||
}
|
||||
|
||||
# The base Node of all node types in topology
|
||||
interface Node {
|
||||
# The global id of each node,
|
||||
# 1. `Application ID` represents application under monitoring
|
||||
# 2. `Peer ID` string represents the conjectural dependency.
|
||||
id: ID!
|
||||
# Application Code or literal Peer
|
||||
name: String!
|
||||
# The type name
|
||||
# 1. The most important component in the application, from service provider perspective.
|
||||
# 2. Conjectural dependent component, e.g. MySQL, Redis, Kafka
|
||||
type: String
|
||||
}
|
||||
|
||||
# The Call represents a directed distributed call,
|
||||
# from the `source` to the `target`.
|
||||
type Call {
|
||||
source: ID!
|
||||
target: ID!
|
||||
isAlert: Boolean
|
||||
# The protocol and tech stack used in this distributed call
|
||||
callType: String!
|
||||
callsPerSec: Int!
|
||||
# Unit: millisecond
|
||||
responseTimePerSec: Int!
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# Query the cluster brief based on the given duration
|
||||
type ClusterBrief {
|
||||
numOfApplication: Int
|
||||
numOfService: Int
|
||||
numOfDatabase: Int
|
||||
numOfCache: Int
|
||||
numOfMQ: Int
|
||||
}
|
||||
|
||||
# Query the trend of alarm rate based on the given duration
|
||||
type AlarmTrend {
|
||||
numOfAlarmRate: [Int]!
|
||||
}
|
||||
|
||||
# Query all conjectural applications based on the given duration
|
||||
# All applications here are not installed agent.
|
||||
type ConjecturalAppBrief {
|
||||
apps: [ConjecturalApp!]
|
||||
}
|
||||
|
||||
# The basic info of the conjectural application,
|
||||
# includes the type and num of same type application
|
||||
type ConjecturalApp {
|
||||
# The display name of the application
|
||||
# e.g. MySQL, RocketMQ, Kafka, Nginx
|
||||
name: String!
|
||||
num: Int!
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
getClusterTopology(duration: Duration!): Topology
|
||||
getClusterBrief(duration: Duration!): ClusterBrief
|
||||
getAlarmTrend(duration: Duration!): AlarmTrend
|
||||
getConjecturalApps(duration: Duration!): ConjecturalAppBrief
|
||||
getTopNSlowService(duration: Duration!, topN: Int!): [ServiceInfo!]
|
||||
getTopNServerThroughput(duration: Duration!, topN: Int!): [AppServerInfo!]
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# The server info.
|
||||
# At here, `Server` represents a process in OS,
|
||||
# e.g.
|
||||
# 1. Spring boot application
|
||||
# 2. A Tomcat server instance
|
||||
type AppServerInfo {
|
||||
id: ID!
|
||||
name: String!
|
||||
tps: Int!
|
||||
os: String
|
||||
host: String
|
||||
pid: Int
|
||||
IPv4: String
|
||||
IPv6: String
|
||||
}
|
||||
|
||||
type CPUTrend {
|
||||
cost: [Int!]
|
||||
}
|
||||
|
||||
# The gc trend represents the numbers of Garbage Collector execution
|
||||
type GCTrend {
|
||||
youngGC: [Int!]
|
||||
oldGC: [Int!]
|
||||
}
|
||||
|
||||
# The memory used and max limit in heap and noheap space.
|
||||
type MemoryTrend {
|
||||
heap: [Int!]
|
||||
maxHeap: [Int!]
|
||||
noheap: [Int!]
|
||||
maxNoheap: [Int!]
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
searchServer(keyword: String!, duration: Duration!): [AppServerInfo]
|
||||
getServerResponseTimeTrend(serverId: ID!, duration: Duration!): ResponseTimeTrend
|
||||
getServerTPSTrend(serverId: ID!, duration: Duration!): ThroughputTrend
|
||||
getCPUTrend(serverId: ID!, duration: Duration!): CPUTrend
|
||||
getGCTrend(serverId: ID!, duration: Duration!): GCTrend
|
||||
getMemoryTrend(serverId: ID!, duration: Duration!): MemoryTrend
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
type ServiceNode implements Node {
|
||||
id: ID!
|
||||
name: String!
|
||||
type: String
|
||||
# Success rate of all incoming requests.
|
||||
# Max value is 100.
|
||||
# 2 Digits after floating point.
|
||||
sla: Float!
|
||||
# The number of incoming calls
|
||||
calls: Long!
|
||||
# The number of services alerting
|
||||
numOfServiceAlarm: Int!
|
||||
}
|
||||
|
||||
type ServiceInfo {
|
||||
id: ID!
|
||||
name: String
|
||||
# The unit is millisecond.
|
||||
avgResponseTime: Int!
|
||||
tps: Int!
|
||||
}
|
||||
|
||||
type TraceItem {
|
||||
time: String!
|
||||
entry: String!
|
||||
duration: Int!
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
searchService(keyword: String!, duration: Duration!): [ServiceNode]
|
||||
getServiceResponseTimeTrend(serviceId: ID!, duration: Duration!): ResponseTimeTrend
|
||||
getServiceTPSTrend(serviceId: ID!, duration: Duration!): ThroughputTrend
|
||||
getServiceSLATrend(serviceId: ID!, duration: Duration!): SLATrend
|
||||
getServiceTopology(serviceId: ID!, duration: Duration!): Topology
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
# The list of traces
|
||||
type TraceBrief {
|
||||
traces: [BasicTrace!]
|
||||
}
|
||||
|
||||
# Trace basic info
|
||||
type BasicTrace {
|
||||
operationName: String!
|
||||
duration: Int!
|
||||
start: String!
|
||||
isError: Boolean
|
||||
traceId: String
|
||||
}
|
||||
|
||||
# Represent the conditions used for query TraceBrief
|
||||
input TraceQueryCondition {
|
||||
applicationCodes: [String!]
|
||||
traceId: String
|
||||
operationName: String
|
||||
# The time range of traces started
|
||||
queryDuration: Duration
|
||||
# The mix time of trace
|
||||
minTraceDuration: Int
|
||||
# The max time of trace
|
||||
maxTraceDuration: Int
|
||||
topN: Boolean
|
||||
needTotal: Int
|
||||
}
|
||||
|
||||
enum QueryOrder {
|
||||
BY_START_TIME
|
||||
BY_DURATION
|
||||
}
|
||||
|
||||
# The trace represents a distributed trace, includes all segments and spans.
|
||||
type Trace {
|
||||
traceId: ID!
|
||||
segments: [Segment!]
|
||||
}
|
||||
|
||||
type Segment {
|
||||
segmentId: ID!
|
||||
appName: String!
|
||||
isSizeLimited: Boolean!
|
||||
spans: [Span!]!
|
||||
}
|
||||
|
||||
type Span {
|
||||
refs: [Ref!]
|
||||
spanId: Int!
|
||||
parentSpanId: Int!
|
||||
startTime: Long!
|
||||
endTime: Long!
|
||||
operationName: String
|
||||
# There are three span types: Local, Entry and Exit
|
||||
type: String!
|
||||
# Peer network id, e.g. host+port, ip+port
|
||||
peer: String
|
||||
component: String
|
||||
isError: Boolean
|
||||
# There are 5 layers: Unknown, Database, RPCFramework, Http, MQ and Cache
|
||||
layer: String
|
||||
tags: [KeyValue!]
|
||||
logs: [LogEntity!]
|
||||
}
|
||||
|
||||
# Ref represents the link between the segment and its parents.
|
||||
type Ref {
|
||||
parentSegmentId: ID!
|
||||
parentSpanId: Int!
|
||||
# Ref type represents why did the ref happen.
|
||||
# Include: 1) CrossProcess 2) CrossThread
|
||||
type: String!
|
||||
}
|
||||
|
||||
type KeyValue {
|
||||
key: String!
|
||||
value: String
|
||||
}
|
||||
|
||||
type LogEntity {
|
||||
time: String
|
||||
data: [KeyValue!]
|
||||
}
|
||||
|
||||
extend type Query {
|
||||
queryBasicTraces(condition: TraceQueryCondition): TraceBrief
|
||||
queryTrace(traceId: ID!): Trace
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You 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.apache.skywalking.apm.ui.protocol;
|
||||
|
||||
import graphql.schema.idl.EchoingWiringFactory;
|
||||
import graphql.schema.idl.RuntimeWiring;
|
||||
import graphql.schema.idl.SchemaGenerator;
|
||||
import graphql.schema.idl.SchemaParser;
|
||||
import graphql.schema.idl.TypeDefinitionRegistry;
|
||||
import java.io.File;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class GraphQLScriptTest {
|
||||
|
||||
@Test
|
||||
public void assertScriptFormat() {
|
||||
SchemaParser schemaParser = new SchemaParser();
|
||||
SchemaGenerator schemaGenerator = new SchemaGenerator();
|
||||
|
||||
TypeDefinitionRegistry typeRegistry = new TypeDefinitionRegistry();
|
||||
typeRegistry.merge(schemaParser.parse(loadSchema("common.graphqls")));
|
||||
typeRegistry.merge(schemaParser.parse(loadSchema("trace.graphqls")));
|
||||
typeRegistry.merge(schemaParser.parse(loadSchema("overview-layer.graphqls")));
|
||||
typeRegistry.merge(schemaParser.parse(loadSchema("application-layer.graphqls")));
|
||||
typeRegistry.merge(schemaParser.parse(loadSchema("server-layer.graphqls")));
|
||||
typeRegistry.merge(schemaParser.parse(loadSchema("service-layer.graphqls")));
|
||||
typeRegistry.merge(schemaParser.parse(loadSchema("alarm.graphqls")));
|
||||
RuntimeWiring wiring = buildRuntimeWiring();
|
||||
assertTrue(schemaGenerator.makeExecutableSchema(typeRegistry, wiring).getAllTypesAsList().size() > 0);
|
||||
}
|
||||
|
||||
private File loadSchema(final String s) {
|
||||
return new File(GraphQLScriptTest.class.getClassLoader().getResource("ui-graphql/" + s).getFile());
|
||||
}
|
||||
|
||||
private RuntimeWiring buildRuntimeWiring() {
|
||||
return RuntimeWiring.newRuntimeWiring().wiringFactory(new EchoingWiringFactory()).build();
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,6 @@
|
|||
|
||||
<modules>
|
||||
<module>apm-network</module>
|
||||
<module>apm-ui-query</module>
|
||||
<module>apm-ui-protocol</module>
|
||||
</modules>
|
||||
</project>
|
||||
Loading…
Reference in New Issue