未验证 提交 b92eac2c 编写于 作者: Z Zhenxu Ke 提交者: GitHub

Add a new concept "Event" and its implementations to collect events (#6183)

上级 547f5f1e
......@@ -110,4 +110,7 @@ jobs:
with:
java-version: 8
- name: 'Install & Test'
run: ./mvnw --batch-mode -P"agent,backend,ui,dist" clean verify install
run: |
# Given packaging on Mac has a high possibility to fail, we retry one more time here
./mvnw --batch-mode -P"agent,backend,ui,dist" clean verify install || \
./mvnw --batch-mode -P"agent,backend,ui,dist" clean verify install
# 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.
name: E2E
on:
pull_request:
paths:
- '**'
- '!**.md'
schedule:
- cron: '0 18 * * *'
env:
SKIP_TEST: true
jobs:
Event:
name: Event
runs-on: ubuntu-latest
strategy:
matrix:
storage: ['h2', 'mysql', 'es6', 'es7.0', 'influxdb']
env:
SW_STORAGE: ${{ matrix.storage }}
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: Cache local Maven repository
uses: actions/cache@v2
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Run E2E Test
uses: ./.github/actions/e2e-test
with:
test_class: org.apache.skywalking.e2e.event.EventE2E
......@@ -15,6 +15,7 @@ Release Notes.
#### OAP-Backend
* Allow user-defined `JAVA_OPTS` in the startup script.
* Metrics combination API supports abandoning results.
* Add a new concept "Event" and its implementations to collect events.
* Add some defensive codes for NPE and bump up Kubernetes client version to expose exception stack trace.
#### UI
......
......@@ -10,7 +10,7 @@ microservices, cloud native and container-based (Docker, Kubernetes, Mesos) arch
[![Twitter Follow](https://img.shields.io/twitter/follow/asfskywalking.svg?style=for-the-badge&label=Follow&logo=twitter)](https://twitter.com/AsfSkyWalking)
[![Maven Central](https://img.shields.io/maven-central/v/org.apache.skywalking/apache-skywalking-apm.svg)](http://skywalking.apache.org/downloads/)
[![CI/IT Tests](https://github.com/apache/skywalking/workflows/CI%20AND%20IT/badge.svg?branch=master)](https://github.com/apache/skywalking/actions?query=branch%3Amaster+event%3Aschedule+workflow%3A%22CI+AND+IT%22)
[![CI/IT Tests](https://github.com/apache/skywalking/workflows/CI%20AND%20IT/badge.svg?branch=master)](https://github.com/apache/skywalking/actions?query=workflow%3ACI%2BAND%2BIT+event%3Aschedule+branch%3Amaster/)
[![E2E Tests](https://github.com/apache/skywalking/workflows/E2E/badge.svg?branch=master)](https://github.com/apache/skywalking/actions?query=branch%3Amaster+event%3Aschedule+workflow%3AE2E)
# Abstract
......
......@@ -23,3 +23,5 @@ SkyWalking already support.
- [Overview](ui-overview.md). A simple brief about SkyWalking UI.
- CLI
- [SkyWalking CLI](https://github.com/apache/skywalking-cli). A command line interface for SkyWalking.
- Events
- [Events](event.md). Introduce the concept of "Event" in SkyWalking.
# Events
SkyWalking already supports the three pillars of observability, namely logs, metrics, and traces.
In reality, a production system experiences many other events that may affect the performance of the system, such as upgrading, rebooting, chaos testing, etc.
Although some of these events are reflected in the logs, there are many other events that can not. Hence, SkyWalking provides a more native way to collect these events.
This doc covers the design of how SkyWalking collects events and what events look like in SkyWalking.
## How to Report Events
SkyWalking backend supports three protocols to collect events, gRPC, HTTP, and Kafka. Any agent or CLI that implements one of these protocols can report events to SkyWalking.
Currently, the officially supported clients to report events are:
- [ ] Java Agent Toolkit: Use the Java agent toolkit to report events from inside the applications.
- [x] SkyWalking CLI: Use the CLI to report events from the command line interface.
- [ ] Kubernetes Event Exporter: Deploy an event exporter to refine and report Kubernetes events.
## Event Definition
An event contains the following fields. The definitions of event can be found at the [protocol repo](https://github.com/apache/skywalking-data-collect-protocol/tree/master/event)
### UUID
Unique ID of the event. Because an event may span a long period of time, the UUID is necessary to associate the start time with the end time of the same event.
### Source
The source object that the event occurs on. In the concepts of SkyWalking, the object is typically service, service instance, etc.
### Name
The name of the event. For example, `Start`, `Stop`, `Crash`, `Reboot`, `Upgrade` etc.
### Type
The type of the event. This field is friendly for UI visualization, where events of type `Normal` are considered as normal operations,
while `Error` is considered as unexpected operations, such as `Crash` events, therefore we can mark them with different colors to be easier identified.
### Message
The detail of the event that describes why this event happened. This should be a one-line message that briefly describes why the event is reported. Examples of an `Upgrade` event may be something like `Upgrade from ${from_version} to ${to_version}`.
It's NOT encouraged to include the detailed logs of this event, such as the exception stack trace.
### Parameters
The parameters in the `message` field. This is a simple `<string,string>` map.
### Start Time
The start time of the event. This field is mandatory when an event occurs.
### End Time
The end time of the event. This field may be empty if the event has not stopped yet, otherwise it should be a valid timestamp after `startTime`.
**NOTE:** When reporting an event, you typically call the report function twice, one for starting of the event and the other one for ending of the event, with the same UUID.
There are also cases where you have both the start time and end time already, for example, when exporting events from a 3rd-party system, the start time and end time are already known so that you can call the report function only once.
......@@ -50,6 +50,9 @@ the following key info:
1. Protocol. HTTP, gRPC
1. DetectPoint. In Service Mesh sidecar, `client` or `server`. In normal L7 proxy, value is `proxy`.
### Events Report Protocol
The protocol is used to report events to the backend. The [doc](../concepts-and-designs/event.md) introduces the definition of an event, and [the protocol repository](https://github.com/apache/skywalking-data-collect-protocol/blob/master/event) defines gRPC services and messages formats of events.
### 3rd-party instrument protocol
3rd-party instrument protocols are not defined by SkyWalking. They are just protocols/formats, which SkyWalking is compatible and
......
......@@ -16,6 +16,7 @@ We have following receivers, and `default` implementors are provided in our Apac
1. **receiver-browser**. gRPC services to accept browser performance data and error log.
1. **receiver-log**. gRPC services accept log data.
1. **configuration-discovery**. gRPC services handle configurationDiscovery.
1. **receiver-event**. gRPC services to handle events data.
1. Experimental receivers. All following receivers are in the POC stage, not production ready.
1. **receiver_zipkin**. See [details](#zipkin-receiver). (Experimental)
1. **receiver_jaeger**. See [details](#jaeger-receiver). (Experimental)
......@@ -72,6 +73,11 @@ receiver-log:
configuration-discovery:
selector: ${SW_CONFIGURATION_DISCOVERY:default}
default:
receiver-event:
selector: ${SW_RECEIVER_EVENT:default}
default:
```
## gRPC/HTTP server for receiver
......@@ -207,4 +213,4 @@ receiver_jaeger:
gRPCPort: ${SW_RECEIVER_JAEGER_PORT:14250}
```
NOTICE, Jaeger receiver is only provided in `apache-skywalking-apm-x.y.z.tar.gz` tar.
\ No newline at end of file
NOTICE, Jaeger receiver is only provided in `apache-skywalking-apm-x.y.z.tar.gz` tar.
......@@ -261,6 +261,7 @@ core|default|role|Option values, `Mixed/Receiver/Aggregator`. **Receiver** mode
| - | - | targetPort | The port of target grpc server for receiving export data. | SW_EXPORTER_GRPC_PORT | 9870 |
| health-checker | default | checkIntervalSeconds | The period of check OAP internal health status. Unit is second. | SW_HEALTH_CHECKER_INTERVAL_SECONDS | 5 |
| configuration-discovery | default | disableMessageDigest | If true, agent receives the latest configuration every time even without change. In default, OAP uses SHA512 message digest mechanism to detect changes of configuration. | SW_DISABLE_MESSAGE_DIGEST | false
| receiver-event|default| Read [receiver doc](backend-receivers.md) for more details | - | - |
## Notice
¹ System Environment Variable name could be declared and changed in the application.yml. The names listed here,
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>analyzer</artifactId>
<groupId>org.apache.skywalking</groupId>
<version>8.5.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>event-analyzer</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>server-core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
/*
* 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.oap.server.analyzer.event;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.network.event.v3.Event;
import org.apache.skywalking.oap.server.analyzer.event.listener.EventAnalyzerListener;
import org.apache.skywalking.oap.server.analyzer.event.listener.EventAnalyzerListenerFactoryManager;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
/**
* Analyze the collected event data, is the entry point for event analysis.
*/
@Slf4j
@RequiredArgsConstructor
public class EventAnalyzer {
private final ModuleManager moduleManager;
private final EventAnalyzerListenerFactoryManager factoryManager;
private final List<EventAnalyzerListener> listeners = new ArrayList<>();
public void analyze(final Event builder) {
createListeners();
notifyListener(builder);
notifyListenerToBuild();
}
private void notifyListener(final Event event) {
listeners.forEach(listener -> listener.parse(event));
}
private void notifyListenerToBuild() {
listeners.forEach(EventAnalyzerListener::build);
}
private void createListeners() {
factoryManager.factories()
.forEach(factory -> listeners.add(factory.create(moduleManager)));
}
}
/*
* 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.oap.server.analyzer.event;
import org.apache.skywalking.oap.server.library.module.ModuleDefine;
public class EventAnalyzerModule extends ModuleDefine {
public static final String NAME = "event-analyzer";
public EventAnalyzerModule() {
super(NAME);
}
@Override
public Class<?>[] services() {
return new Class<?>[] {
EventAnalyzerService.class
};
}
}
/*
* 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.oap.server.analyzer.event;
import org.apache.skywalking.oap.server.library.module.ModuleConfig;
public class EventAnalyzerModuleConfig extends ModuleConfig {
}
/*
* 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.oap.server.analyzer.event;
import org.apache.skywalking.oap.server.analyzer.event.listener.EventRecordAnalyzerListener;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.library.module.ModuleConfig;
import org.apache.skywalking.oap.server.library.module.ModuleDefine;
import org.apache.skywalking.oap.server.library.module.ModuleProvider;
import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException;
public class EventAnalyzerModuleProvider extends ModuleProvider {
private EventAnalyzerServiceImpl analysisService;
@Override
public String name() {
return "default";
}
@Override
public Class<? extends ModuleDefine> module() {
return EventAnalyzerModule.class;
}
@Override
public ModuleConfig createConfigBeanIfAbsent() {
return new EventAnalyzerModuleConfig();
}
@Override
public void prepare() throws ServiceNotProvidedException {
analysisService = new EventAnalyzerServiceImpl(getManager());
registerServiceImplementation(EventAnalyzerService.class, analysisService);
}
@Override
public void start() {
analysisService.add(new EventRecordAnalyzerListener.Factory(getManager()));
}
@Override
public void notifyAfterCompleted() {
}
@Override
public String[] requiredModules() {
return new String[] {
CoreModule.NAME
};
}
}
/*
* 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.oap.server.analyzer.event;
import org.apache.skywalking.apm.network.event.v3.Event;
import org.apache.skywalking.oap.server.library.module.Service;
public interface EventAnalyzerService extends Service {
void analyze(final Event event);
}
/*
* 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.oap.server.analyzer.event;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.apache.skywalking.apm.network.event.v3.Event;
import org.apache.skywalking.oap.server.analyzer.event.listener.EventAnalyzerListener;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.analyzer.event.listener.EventAnalyzerListenerFactoryManager;
@RequiredArgsConstructor
public class EventAnalyzerServiceImpl implements EventAnalyzerService, EventAnalyzerListenerFactoryManager {
private final ModuleManager moduleManager;
private final List<EventAnalyzerListener.Factory> factories = new ArrayList<>();
@Override
public void analyze(final Event event) {
final EventAnalyzer analyzer = new EventAnalyzer(moduleManager, this);
analyzer.analyze(event);
}
@Override
public void add(final EventAnalyzerListener.Factory factory) {
factories.add(factory);
}
@Override
public List<EventAnalyzerListener.Factory> factories() {
return factories;
}
}
/*
* 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.oap.server.analyzer.event.listener;
import org.apache.skywalking.apm.network.event.v3.Event;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
/**
* {@code EventAnalyzerListener} represents the callback when OAP does the event data analysis.
*/
public interface EventAnalyzerListener {
/**
* Parse the raw data from the proto buffer messages.
*/
void parse(Event event);
/**
* The last step of the analysis process. Typically, the implementations forward the analysis results to the source receiver.
*/
void build();
interface Factory {
EventAnalyzerListener create(final ModuleManager moduleManager);
}
}
/*
* 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.oap.server.analyzer.event.listener;
import java.util.List;
import org.apache.skywalking.oap.server.library.module.Service;
public interface EventAnalyzerListenerFactoryManager extends Service {
void add(EventAnalyzerListener.Factory factory);
List<EventAnalyzerListener.Factory> factories();
}
/*
* 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.oap.server.analyzer.event.listener;
import com.google.gson.Gson;
import lombok.RequiredArgsConstructor;
import org.apache.skywalking.apm.network.event.v3.Source;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
import org.apache.skywalking.oap.server.core.config.NamingControl;
import org.apache.skywalking.oap.server.core.event.Event;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
/**
* EventRecordAnalyzerListener forwards the event data to the persistence layer with the query required conditions.
*/
@RequiredArgsConstructor
public class EventRecordAnalyzerListener implements EventAnalyzerListener {
private static final Gson GSON = new Gson();
private final NamingControl namingControl;
private final Event event = new Event();
@Override
public void build() {
MetricsStreamProcessor.getInstance().in(event);
}
@Override
public void parse(final org.apache.skywalking.apm.network.event.v3.Event e) {
event.setUuid(e.getUuid());
if (e.hasSource()) {
final Source source = e.getSource();
event.setService(namingControl.formatServiceName(source.getService()));
event.setServiceInstance(namingControl.formatInstanceName(source.getServiceInstance()));
event.setEndpoint(namingControl.formatEndpointName(source.getService(), source.getEndpoint()));
}
event.setName(e.getName());
event.setType(e.getType().name());
event.setMessage(e.getMessage());
if (e.getParametersCount() > 0) {
event.setParameters(GSON.toJson(e.getParametersMap()));
}
event.setStartTime(e.getStartTime());
event.setEndTime(e.getEndTime());
if (e.getStartTime() > 0) {
event.setTimeBucket(TimeBucket.getMinuteTimeBucket(e.getStartTime()));
} else if (e.getEndTime() > 0) {
event.setTimeBucket(TimeBucket.getMinuteTimeBucket(e.getEndTime()));
}
}
public static class Factory implements EventAnalyzerListener.Factory {
private final NamingControl namingControl;
public Factory(final ModuleManager moduleManager) {
this.namingControl = moduleManager.find(CoreModule.NAME)
.provider()
.getService(NamingControl.class);
}
@Override
public EventAnalyzerListener create(final ModuleManager moduleManager) {
return new EventRecordAnalyzerListener(namingControl);
}
}
}
#
# 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.
#
#
org.apache.skywalking.oap.server.analyzer.event.EventAnalyzerModule
#
# 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.
#
#
org.apache.skywalking.oap.server.analyzer.event.EventAnalyzerModuleProvider
......@@ -32,6 +32,7 @@
<module>agent-analyzer</module>
<module>log-analyzer</module>
<module>meter-analyzer</module>
<module>event-analyzer</module>
</modules>
<dependencies>
......@@ -51,4 +52,4 @@
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
</project>
......@@ -136,6 +136,11 @@
<artifactId>configuration-discovery-receiver-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>skywalking-event-receiver-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<!-- receiver module -->
<!-- fetcher module -->
......
......@@ -219,6 +219,10 @@ log-analyzer:
selector: ${SW_LOG_ANALYZER:default}
default:
event-analyzer:
selector: ${SW_EVENT_ANALYZER:default}
default:
receiver-sharing-server:
selector: ${SW_RECEIVER_SHARING_SERVER:default}
default:
......@@ -422,3 +426,7 @@ configuration-discovery:
selector: ${SW_CONFIGURATION_DISCOVERY:default}
default:
disableMessageDigest: ${SW_DISABLE_MESSAGE_DIGEST:false}
receiver-event:
selector: ${SW_RECEIVER_EVENT:default}
default:
......@@ -33,6 +33,7 @@
<logger name="org.apache.http" level="INFO"/>
<logger name="org.apache.skywalking.oap.server.core.alarm.AlarmStandardPersistence" level="DEBUG"/>
<logger name="org.apache.skywalking.oap.server.core" level="DEBUG"/>
<logger name="org.apache.skywalking.oap.server.core.storage.PersistenceTimer" level="INFO"/>
<logger name="org.apache.skywalking.oap.server.core.analysis.worker" level="DEBUG" />
<logger name="org.apache.skywalking.oap.server.core.remote.client" level="DEBUG"/>
<logger name="org.apache.skywalking.oap.server.library.buffer" level="INFO"/>
......
......@@ -34,6 +34,7 @@ import org.apache.skywalking.oap.server.core.profile.ProfileTaskMutationService;
import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
import org.apache.skywalking.oap.server.core.query.AlarmQueryService;
import org.apache.skywalking.oap.server.core.query.BrowserLogQueryService;
import org.apache.skywalking.oap.server.core.query.EventQueryService;
import org.apache.skywalking.oap.server.core.query.LogQueryService;
import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
......@@ -116,6 +117,7 @@ public class CoreModule extends ModuleDefine {
classes.add(AlarmQueryService.class);
classes.add(TopNRecordsQueryService.class);
classes.add(BrowserLogQueryService.class);
classes.add(EventQueryService.class);
}
private void addServerInterface(List<Class> classes) {
......
......@@ -54,6 +54,7 @@ import org.apache.skywalking.oap.server.core.profile.ProfileTaskMutationService;
import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
import org.apache.skywalking.oap.server.core.query.AlarmQueryService;
import org.apache.skywalking.oap.server.core.query.BrowserLogQueryService;
import org.apache.skywalking.oap.server.core.query.EventQueryService;
import org.apache.skywalking.oap.server.core.query.LogQueryService;
import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
......@@ -250,6 +251,7 @@ public class CoreModuleProvider extends ModuleProvider {
this.registerServiceImplementation(AggregationQueryService.class, new AggregationQueryService(getManager()));
this.registerServiceImplementation(AlarmQueryService.class, new AlarmQueryService(getManager()));
this.registerServiceImplementation(TopNRecordsQueryService.class, new TopNRecordsQueryService(getManager()));
this.registerServiceImplementation(EventQueryService.class, new EventQueryService(getManager()));
// add profile service implementations
this.registerServiceImplementation(
......
/*
* 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.oap.server.core.event;
import java.util.HashMap;
import java.util.Map;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.apache.skywalking.apm.util.StringUtil;
import org.apache.skywalking.oap.server.core.analysis.MetricsExtension;
import org.apache.skywalking.oap.server.core.analysis.Stream;
import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
import org.apache.skywalking.oap.server.core.analysis.worker.MetricsStreamProcessor;
import org.apache.skywalking.oap.server.core.remote.grpc.proto.RemoteData;
import org.apache.skywalking.oap.server.core.source.ScopeDeclaration;
import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.EVENT;
@Getter
@Setter
@ScopeDeclaration(id = EVENT, name = "Event")
@Stream(name = Event.INDEX_NAME, scopeId = EVENT, builder = Event.Builder.class, processor = MetricsStreamProcessor.class)
@EqualsAndHashCode(
callSuper = false,
of = "uuid"
)
@MetricsExtension(supportDownSampling = false, supportUpdate = true)
public class Event extends Metrics {
public static final String INDEX_NAME = "events";
public static final String UUID = "uuid";
public static final String SERVICE = "service";
public static final String SERVICE_INSTANCE = "service_instance";
public static final String ENDPOINT = "endpoint";
public static final String NAME = "name";
public static final String TYPE = "type";
public static final String MESSAGE = "message";
public static final String PARAMETERS = "parameters";
public static final String START_TIME = "start_time";
public static final String END_TIME = "end_time";
@Override
public String id() {
return getUuid();
}
@Column(columnName = UUID)
private String uuid;
@Column(columnName = SERVICE)
private String service;
@Column(columnName = SERVICE_INSTANCE)
private String serviceInstance;
@Column(columnName = ENDPOINT)
private String endpoint;
@Column(columnName = NAME)
private String name;
@Column(columnName = TYPE)
private String type;
@Column(columnName = MESSAGE)
private String message;
@Column(columnName = PARAMETERS, storageOnly = true)
private String parameters;
@Column(columnName = START_TIME)
private long startTime;
@Column(columnName = END_TIME)
private long endTime;
@Override
public boolean combine(final Metrics metrics) {
final Event event = (Event) metrics;
// Set time bucket only when it's never set.
if (getTimeBucket() <= 0) {
if (event.getStartTime() > 0) {
setTimeBucket(TimeBucket.getMinuteTimeBucket(event.getStartTime()));
} else if (event.getEndTime() > 0) {
setTimeBucket(TimeBucket.getMinuteTimeBucket(event.getEndTime()));
}
}
// Set start time only when it's never set, (`start` event may come after `end` event).
if (getStartTime() <= 0 && event.getStartTime() > 0) {
setStartTime(event.getStartTime());
}
if (event.getEndTime() > 0) {
setEndTime(event.getEndTime());
}
if (StringUtil.isNotBlank(event.getType())) {
setType(event.getType());
}
if (StringUtil.isNotBlank(event.getMessage())) {
setType(event.getMessage());
}
if (StringUtil.isNotBlank(event.getParameters())) {
setParameters(event.getParameters());
}
return true;
}
@Override
public void calculate() {
}
@Override
public Metrics toHour() {
return null;
}
@Override
public Metrics toDay() {
return null;
}
@Override
public void deserialize(final RemoteData remoteData) {
setUuid(remoteData.getDataStrings(0));
setService(remoteData.getDataStrings(1));
setServiceInstance(remoteData.getDataStrings(2));
setEndpoint(remoteData.getDataStrings(3));
setName(remoteData.getDataStrings(4));
setType(remoteData.getDataStrings(5));
setMessage(remoteData.getDataStrings(6));
setParameters(remoteData.getDataStrings(7));
setStartTime(remoteData.getDataLongs(0));
setEndTime(remoteData.getDataLongs(1));
setTimeBucket(remoteData.getDataLongs(2));
}
@Override
public RemoteData.Builder serialize() {
final RemoteData.Builder builder = RemoteData.newBuilder();
builder.addDataStrings(getUuid());
builder.addDataStrings(getService());
builder.addDataStrings(getServiceInstance());
builder.addDataStrings(getEndpoint());
builder.addDataStrings(getName());
builder.addDataStrings(getType());
builder.addDataStrings(getMessage());
builder.addDataStrings(getParameters());
builder.addDataLongs(getStartTime());
builder.addDataLongs(getEndTime());
builder.addDataLongs(getTimeBucket());
return builder;
}
@Override
public int remoteHashCode() {
return hashCode();
}
public static class Builder implements StorageBuilder<Event> {
@Override
public Map<String, Object> data2Map(Event storageData) {
Map<String, Object> map = new HashMap<>();
map.put(UUID, storageData.getUuid());
map.put(SERVICE, storageData.getService());
map.put(SERVICE_INSTANCE, storageData.getServiceInstance());
map.put(ENDPOINT, storageData.getEndpoint());
map.put(NAME, storageData.getName());
map.put(TYPE, storageData.getType());
map.put(MESSAGE, storageData.getMessage());
map.put(PARAMETERS, storageData.getParameters());
map.put(START_TIME, storageData.getStartTime());
map.put(END_TIME, storageData.getEndTime());
map.put(TIME_BUCKET, storageData.getTimeBucket());
return map;
}
@Override
public Event map2Data(Map<String, Object> dbMap) {
Event record = new Event();
record.setUuid((String) dbMap.get(UUID));
record.setService((String) dbMap.get(SERVICE));
record.setServiceInstance((String) dbMap.get(SERVICE_INSTANCE));
record.setEndpoint((String) dbMap.get(ENDPOINT));
record.setName((String) dbMap.get(NAME));
record.setType((String) dbMap.get(TYPE));
record.setMessage((String) dbMap.get(MESSAGE));
record.setParameters((String) dbMap.get(PARAMETERS));
record.setStartTime(((Number) dbMap.get(START_TIME)).longValue());
record.setEndTime(((Number) dbMap.get(END_TIME)).longValue());
record.setTimeBucket(((Number) dbMap.get(TIME_BUCKET)).longValue());
return record;
}
}
}
/*
* 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.oap.server.core.query;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.type.event.EventQueryCondition;
import org.apache.skywalking.oap.server.core.query.type.event.Events;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.module.Service;
import static java.util.Objects.isNull;
import static org.apache.skywalking.apm.util.StringUtil.isBlank;
public class EventQueryService implements Service {
private final ModuleManager moduleManager;
private IEventQueryDAO dao;
public EventQueryService(ModuleManager moduleManager) {
this.moduleManager = moduleManager;
}
private IEventQueryDAO getDao() {
if (dao == null) {
dao = moduleManager.find(StorageModule.NAME).provider().getService(IEventQueryDAO.class);
}
return dao;
}
public Events queryEvents(final EventQueryCondition condition) throws Exception {
if (isBlank(condition.getUuid()) && isDurationInvalid(condition.getTime())) {
throw new IllegalArgumentException("time field is required when uuid is absent.");
}
return getDao().queryEvents(condition);
}
boolean isDurationInvalid(final Duration duration) {
return isNull(duration) || (isBlank(duration.getStart()) || isBlank(duration.getEnd()));
}
}
/*
* 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.oap.server.core.query.type.event;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.Data;
import org.apache.skywalking.apm.util.StringUtil;
import org.apache.skywalking.oap.server.core.query.type.KeyValue;
@Data
public class Event {
private static final Gson GSON = new Gson();
private String uuid;
private Source source;
private String name;
private EventType type;
private String message;
private List<KeyValue> parameters;
private long startTime;
private long endTime;
public void setParameters(final List<KeyValue> parameters) {
this.parameters = parameters;
}
public void setParameters(final String json) {
if (StringUtil.isNotEmpty(json)) {
final Map<String, String> map = GSON.fromJson(json, new TypeToken<Map<String, String>>() {
}.getType());
this.parameters = map.entrySet().stream().map(e -> new KeyValue(e.getKey(), e.getValue())).collect(Collectors.toList());
}
}
}
/*
* 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.oap.server.core.query.type.event;
import lombok.Data;
import org.apache.skywalking.oap.server.core.query.enumeration.Order;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import static org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO.DEFAULT_SIZE;
import static org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO.MAX_SIZE;
@Data
public class EventQueryCondition {
private String uuid;
private Source source;
private String name;
private EventType type;
private Duration time;
private Order order;
private int size;
public int getSize() {
return size > 0 ? Math.min(size, MAX_SIZE) : DEFAULT_SIZE;
}
}
/*
* 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.oap.server.core.query.type.event;
import com.google.common.base.Strings;
import java.util.Objects;
public enum EventType {
Normal, Error;
public static EventType parse(final String raw) {
for (final EventType value : EventType.values()) {
if (Objects.equals(value.name().toLowerCase(), Strings.nullToEmpty(raw).toLowerCase())) {
return value;
}
}
return Normal;
}
}
/*
* 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.oap.server.core.query.type.event;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
@Data
public class Events {
private List<Event> events = new ArrayList<>();
private long total;
}
/*
* 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.oap.server.core.query.type.event;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Source {
private String service;
private String serviceInstance;
private String endpoint;
}
......@@ -81,6 +81,8 @@ public class DefaultScopeDefine {
public static final int LOG = 41;
public static final int ENDPOINT_META = 42;
public static final int EVENT = 43;
/**
* Catalog of scope, the metrics processor could use this to group all generated metrics by oal rt.
*/
......@@ -338,4 +340,4 @@ public class DefaultScopeDefine {
}
return scopeDefaultColumns;
}
}
\ No newline at end of file
}
......@@ -26,6 +26,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnaps
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -65,7 +66,8 @@ public class StorageModule extends ModuleDefine {
IProfileTaskLogQueryDAO.class,
IProfileThreadSnapshotQueryDAO.class,
UITemplateManagementDAO.class,
IBrowserLogQueryDAO.class
IBrowserLogQueryDAO.class,
IEventQueryDAO.class
};
}
}
/*
* 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.oap.server.core.storage.query;
import org.apache.skywalking.oap.server.core.query.type.event.EventQueryCondition;
import org.apache.skywalking.oap.server.core.query.type.event.Events;
import org.apache.skywalking.oap.server.core.storage.DAO;
public interface IEventQueryDAO extends DAO {
int DEFAULT_SIZE = 20;
int MAX_SIZE = 100;
Events queryEvents(final EventQueryCondition condition) throws Exception;
}
......@@ -26,6 +26,6 @@ public class CoreModuleTest {
public void testOpenServiceList() {
CoreModule coreModule = new CoreModule();
Assert.assertEquals(32, coreModule.services().length);
Assert.assertEquals(33, coreModule.services().length);
}
}
......@@ -60,4 +60,4 @@
<artifactId>jetty-servlet</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
</project>
......@@ -24,6 +24,7 @@ import graphql.schema.GraphQLSchema;
import org.apache.skywalking.oap.query.graphql.resolver.AggregationQuery;
import org.apache.skywalking.oap.query.graphql.resolver.AlarmQuery;
import org.apache.skywalking.oap.query.graphql.resolver.BrowserLogQuery;
import org.apache.skywalking.oap.query.graphql.resolver.EventQuery;
import org.apache.skywalking.oap.query.graphql.resolver.HealthQuery;
import org.apache.skywalking.oap.query.graphql.resolver.LogQuery;
import org.apache.skywalking.oap.query.graphql.resolver.MetadataQuery;
......@@ -107,6 +108,8 @@ public class GraphQLQueryProvider extends ModuleProvider {
.resolvers(new UIConfigurationManagement(getManager()))
.file("query-protocol/browser-log.graphqls")
.resolvers(new BrowserLogQuery(getManager()))
.file("query-protocol/event.graphqls")
.resolvers(new EventQuery(getManager()))
.build()
.makeExecutableSchema();
this.graphQL = GraphQL.newGraphQL(schema).build();
......
/*
* 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.oap.query.graphql.resolver;
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.query.EventQueryService;
import org.apache.skywalking.oap.server.core.query.type.event.EventQueryCondition;
import org.apache.skywalking.oap.server.core.query.type.event.Events;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
public class EventQuery implements GraphQLQueryResolver {
private EventQueryService queryService;
private final ModuleManager moduleManager;
public EventQuery(ModuleManager moduleManager) {
this.moduleManager = moduleManager;
}
EventQueryService queryService() {
if (queryService != null) {
return queryService;
}
queryService = moduleManager.find(CoreModule.NAME)
.provider()
.getService(EventQueryService.class);
return queryService;
}
public Events queryEvents(final EventQueryCondition condition) throws Exception {
return queryService().queryEvents(condition);
}
}
Subproject commit 3d91ce7e2704e2b4bf4b63d3f6a26dd19a59caa6
Subproject commit e0d3698dcd776230646acaeb219841adea193acf
......@@ -44,6 +44,7 @@
<module>skywalking-browser-receiver-plugin</module>
<module>skywalking-log-recevier-plugin</module>
<module>configuration-discovery-receiver-plugin</module>
<module>skywalking-event-receiver-plugin</module>
</modules>
<dependencies>
......@@ -68,4 +69,4 @@
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
</project>
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
~
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>server-receiver-plugin</artifactId>
<groupId>org.apache.skywalking</groupId>
<version>8.5.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>skywalking-event-receiver-plugin</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>event-analyzer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>skywalking-sharing-server-plugin</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
/*
* 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.oap.server.receiver.event;
import org.apache.skywalking.oap.server.library.module.ModuleDefine;
public class EventModule extends ModuleDefine {
public static final String NAME = "receiver-event";
public EventModule() {
super(NAME);
}
@Override
public Class<?>[] services() {
return new Class<?>[0];
}
}
/*
* 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.oap.server.receiver.event;
import org.apache.skywalking.oap.server.library.module.ModuleConfig;
public class EventModuleConfig extends ModuleConfig {
}
/*
* 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.oap.server.receiver.event;
import org.apache.skywalking.oap.server.analyzer.event.EventAnalyzerModule;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.server.GRPCHandlerRegister;
import org.apache.skywalking.oap.server.library.module.ModuleConfig;
import org.apache.skywalking.oap.server.library.module.ModuleDefine;
import org.apache.skywalking.oap.server.library.module.ModuleProvider;
import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException;
import org.apache.skywalking.oap.server.receiver.event.grpc.EventGrpcServiceHandler;
import org.apache.skywalking.oap.server.receiver.sharing.server.SharingServerModule;
public class EventModuleProvider extends ModuleProvider {
@Override
public String name() {
return "default";
}
@Override
public Class<? extends ModuleDefine> module() {
return EventModule.class;
}
@Override
public ModuleConfig createConfigBeanIfAbsent() {
return new EventModuleConfig();
}
@Override
public void prepare() throws ServiceNotProvidedException {
}
@Override
public void start() {
final GRPCHandlerRegister grpcHandlerRegister = getManager().find(SharingServerModule.NAME)
.provider()
.getService(GRPCHandlerRegister.class);
final EventGrpcServiceHandler eventGRPCServiceHandler = new EventGrpcServiceHandler(getManager());
grpcHandlerRegister.addHandler(eventGRPCServiceHandler);
}
@Override
public void notifyAfterCompleted() {
}
@Override
public String[] requiredModules() {
return new String[] {
CoreModule.NAME,
EventAnalyzerModule.NAME,
SharingServerModule.NAME
};
}
}
/*
* 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.oap.server.receiver.event.grpc;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.network.common.v3.Commands;
import org.apache.skywalking.apm.network.event.v3.Event;
import org.apache.skywalking.apm.network.event.v3.EventServiceGrpc;
import org.apache.skywalking.oap.server.analyzer.event.EventAnalyzerModule;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.server.grpc.GRPCHandler;
import org.apache.skywalking.oap.server.analyzer.event.EventAnalyzerService;
import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
import org.apache.skywalking.oap.server.telemetry.api.CounterMetrics;
import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics;
import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
import org.apache.skywalking.oap.server.telemetry.api.MetricsTag;
@Slf4j
public class EventGrpcServiceHandler extends EventServiceGrpc.EventServiceImplBase implements GRPCHandler {
private final HistogramMetrics histogram;
private final CounterMetrics errorCounter;
private final EventAnalyzerService eventAnalyzerService;
public EventGrpcServiceHandler(ModuleManager moduleManager) {
final MetricsCreator metricsCreator = moduleManager.find(TelemetryModule.NAME)
.provider()
.getService(MetricsCreator.class);
eventAnalyzerService = moduleManager.find(EventAnalyzerModule.NAME)
.provider()
.getService(EventAnalyzerService.class);
histogram = metricsCreator.createHistogramMetric(
"event_in_latency", "The process latency of event data",
new MetricsTag.Keys("protocol"), new MetricsTag.Values("grpc")
);
errorCounter = metricsCreator.createCounter(
"event_error_count", "The error number of event analysis",
new MetricsTag.Keys("protocol"), new MetricsTag.Values("grpc")
);
}
@Override
public StreamObserver<Event> collect(StreamObserver<Commands> responseObserver) {
return new StreamObserver<Event>() {
@Override
public void onNext(final Event event) {
try (HistogramMetrics.Timer ignored = histogram.createTimer()) {
eventAnalyzerService.analyze(event);
} catch (Exception e) {
errorCounter.inc();
log.error(e.getMessage(), e);
}
}
@Override
public void onError(Throwable throwable) {
log.error(throwable.getMessage(), throwable);
responseObserver.onCompleted();
}
@Override
public void onCompleted() {
responseObserver.onNext(Commands.newBuilder().build());
responseObserver.onCompleted();
}
};
}
}
#
# 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.
#
#
org.apache.skywalking.oap.server.receiver.event.EventModule
#
# 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.
#
#
org.apache.skywalking.oap.server.receiver.event.EventModuleProvider
......@@ -43,6 +43,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnaps
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -66,6 +67,7 @@ import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.cache.Netwo
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.AggregationQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.AlarmQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.BrowserLogQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.ESEventQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.LogQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.MetadataQueryEsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.MetricsQueryEsDAO;
......@@ -188,6 +190,8 @@ public class StorageModuleElasticsearchProvider extends ModuleProvider {
.getProfileTaskQueryMaxSize()));
this.registerServiceImplementation(
UITemplateManagementDAO.class, new UITemplateManagementEsDAO(elasticSearchClient));
this.registerServiceImplementation(IEventQueryDAO.class, new ESEventQueryDAO(elasticSearchClient));
}
@Override
......
/*
* 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.oap.server.storage.plugin.elasticsearch.query;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.skywalking.oap.server.core.event.Event;
import org.apache.skywalking.oap.server.core.query.enumeration.Order;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.type.event.EventQueryCondition;
import org.apache.skywalking.oap.server.core.query.type.event.EventType;
import org.apache.skywalking.oap.server.core.query.type.event.Events;
import org.apache.skywalking.oap.server.core.query.type.event.Source;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.EsDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.base.MatchCNameBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.util.Objects.isNull;
public class ESEventQueryDAO extends EsDAO implements IEventQueryDAO {
public ESEventQueryDAO(ElasticSearchClient client) {
super(client);
}
@Override
public Events queryEvents(final EventQueryCondition condition) throws Exception {
final SearchSourceBuilder sourceBuilder = buildQuery(condition);
final SearchResponse response = getClient().search(Event.INDEX_NAME, sourceBuilder);
final Events events = new Events();
events.setTotal((int) response.getHits().totalHits);
events.setEvents(Stream.of(response.getHits().getHits())
.map(this::parseSearchHit)
.collect(Collectors.toList()));
return events;
}
protected SearchSourceBuilder buildQuery(final EventQueryCondition condition) {
final SearchSourceBuilder sourceBuilder = SearchSourceBuilder.searchSource();
final BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
sourceBuilder.query(boolQueryBuilder);
final List<QueryBuilder> mustQueryList = boolQueryBuilder.must();
if (!isNullOrEmpty(condition.getUuid())) {
mustQueryList.add(QueryBuilders.termQuery(Event.UUID, condition.getUuid()));
}
final Source source = condition.getSource();
if (source != null) {
if (!isNullOrEmpty(source.getService())) {
mustQueryList.add(QueryBuilders.termQuery(Event.SERVICE, source.getService()));
}
if (!isNullOrEmpty(source.getServiceInstance())) {
mustQueryList.add(QueryBuilders.termQuery(Event.SERVICE_INSTANCE, source.getServiceInstance()));
}
if (!isNullOrEmpty(source.getEndpoint())) {
mustQueryList.add(QueryBuilders.matchPhraseQuery(MatchCNameBuilder.INSTANCE.build(Event.ENDPOINT), source.getEndpoint()));
}
}
if (!isNullOrEmpty(condition.getName())) {
mustQueryList.add(QueryBuilders.termQuery(Event.NAME, condition.getName()));
}
if (condition.getType() != null) {
mustQueryList.add(QueryBuilders.termQuery(Event.TYPE, condition.getType().name()));
}
final Duration startTime = condition.getTime();
if (startTime != null) {
if (startTime.getStartTimestamp() > 0) {
mustQueryList.add(QueryBuilders.rangeQuery(Event.START_TIME)
.gt(startTime.getStartTimestamp()));
}
if (startTime.getEndTimestamp() > 0) {
mustQueryList.add(QueryBuilders.rangeQuery(Event.END_TIME)
.lt(startTime.getEndTimestamp()));
}
}
final Order queryOrder = isNull(condition.getOrder()) ? Order.DES : condition.getOrder();
sourceBuilder.sort(Event.START_TIME, Order.DES.equals(queryOrder) ? SortOrder.DESC : SortOrder.ASC);
sourceBuilder.size(condition.getSize());
return sourceBuilder;
}
protected org.apache.skywalking.oap.server.core.query.type.event.Event parseSearchHit(final SearchHit searchHit) {
final org.apache.skywalking.oap.server.core.query.type.event.Event event = new org.apache.skywalking.oap.server.core.query.type.event.Event();
event.setUuid((String) searchHit.getSourceAsMap().get(Event.UUID));
String service = searchHit.getSourceAsMap().getOrDefault(Event.SERVICE, "").toString();
String serviceInstance = searchHit.getSourceAsMap().getOrDefault(Event.SERVICE_INSTANCE, "").toString();
String endpoint = searchHit.getSourceAsMap().getOrDefault(Event.ENDPOINT, "").toString();
event.setSource(new Source(service, serviceInstance, endpoint));
event.setName((String) searchHit.getSourceAsMap().get(Event.NAME));
event.setType(EventType.parse(searchHit.getSourceAsMap().get(Event.TYPE).toString()));
event.setMessage((String) searchHit.getSourceAsMap().get(Event.MESSAGE));
event.setParameters((String) searchHit.getSourceAsMap().get(Event.PARAMETERS));
event.setStartTime(Long.parseLong(searchHit.getSourceAsMap().get(Event.START_TIME).toString()));
String endTimeStr = searchHit.getSourceAsMap().getOrDefault(Event.END_TIME, "0").toString();
if (!endTimeStr.isEmpty() && !Objects.equals(endTimeStr, "0")) {
event.setEndTime(Long.parseLong(endTimeStr));
}
return event;
}
}
......@@ -41,6 +41,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnaps
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -68,6 +69,7 @@ import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.dao.Storag
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.AggregationQueryEs7DAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.AlarmQueryEs7DAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.BrowserLogQueryEs7DAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.ES7EventQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.LogQueryEs7DAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.MetadataQueryEs7DAO;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch7.query.MetricsQueryEs7DAO;
......@@ -197,6 +199,8 @@ public class StorageModuleElasticsearch7Provider extends ModuleProvider {
));
this.registerServiceImplementation(
UITemplateManagementDAO.class, new UITemplateManagementEsDAO(elasticSearch7Client));
this.registerServiceImplementation(IEventQueryDAO.class, new ES7EventQueryDAO(elasticSearch7Client));
}
@Override
......
/*
* 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.oap.server.storage.plugin.elasticsearch7.query;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.skywalking.oap.server.core.event.Event;
import org.apache.skywalking.oap.server.core.query.type.event.EventQueryCondition;
import org.apache.skywalking.oap.server.core.query.type.event.Events;
import org.apache.skywalking.oap.server.library.client.elasticsearch.ElasticSearchClient;
import org.apache.skywalking.oap.server.storage.plugin.elasticsearch.query.ESEventQueryDAO;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.builder.SearchSourceBuilder;
public class ES7EventQueryDAO extends ESEventQueryDAO {
public ES7EventQueryDAO(final ElasticSearchClient client) {
super(client);
}
@Override
public Events queryEvents(final EventQueryCondition condition) throws Exception {
final SearchSourceBuilder sourceBuilder = buildQuery(condition);
final SearchResponse response = getClient().search(Event.INDEX_NAME, sourceBuilder);
final Events events = new Events();
events.setTotal(response.getHits().getTotalHits().value);
events.setEvents(Stream.of(response.getHits().getHits())
.map(this::parseSearchHit)
.collect(Collectors.toList()));
return events;
}
}
......@@ -34,6 +34,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnaps
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -51,6 +52,7 @@ import org.apache.skywalking.oap.server.storage.plugin.influxdb.base.InfluxStora
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.AggregationQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.AlarmQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.BrowserLogQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.EventQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.LogQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.MetadataQuery;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.query.MetricsQuery;
......@@ -119,6 +121,8 @@ public class InfluxStorageProvider extends ModuleProvider {
this.registerServiceImplementation(
IHistoryDeleteDAO.class, new HistoryDeleteDAO(client));
this.registerServiceImplementation(UITemplateManagementDAO.class, new UITemplateManagementDAOImpl(client));
this.registerServiceImplementation(IEventQueryDAO.class, new EventQueryDAO(client));
}
@Override
......
/*
* 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.oap.server.storage.plugin.influxdb.query;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.event.Event;
import org.apache.skywalking.oap.server.core.query.enumeration.Order;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.type.event.EventQueryCondition;
import org.apache.skywalking.oap.server.core.query.type.event.Events;
import org.apache.skywalking.oap.server.core.query.type.event.Source;
import org.apache.skywalking.oap.server.core.query.type.event.EventType;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.core.storage.type.StorageDataComplexObject;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxClient;
import org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants;
import org.influxdb.dto.Query;
import org.influxdb.dto.QueryResult;
import org.influxdb.querybuilder.SelectQueryImpl;
import org.influxdb.querybuilder.WhereQueryImpl;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.apache.skywalking.oap.server.storage.plugin.influxdb.InfluxConstants.ALL_FIELDS;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.contains;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.eq;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.gt;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.lt;
import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.select;
@Slf4j
@RequiredArgsConstructor
public class EventQueryDAO implements IEventQueryDAO {
private final InfluxClient client;
@Override
public Events queryEvents(final EventQueryCondition condition) throws Exception {
final WhereQueryImpl<SelectQueryImpl> recallQuery = buildQuery(condition);
final SelectQueryImpl countQuery = select().count(Event.UUID).from(client.getDatabase(), Event.INDEX_NAME);
recallQuery.getClauses().forEach(countQuery::where);
final Query query = new Query(countQuery.getCommand() + recallQuery.getCommand());
final List<QueryResult.Result> results = client.query(query);
if (log.isDebugEnabled()) {
log.debug("SQL: {}", query.getCommand());
log.debug("Result: {}", results);
}
if (results.size() != 2) {
throw new IOException("Expecting to get 2 Results, but it is " + results.size());
}
final QueryResult.Series counterSeries = results.get(0).getSeries().get(0);
final List<QueryResult.Series> recallSeries = results.get(1).getSeries();
final Events events = new Events();
events.setTotal(((Number) counterSeries.getValues().get(0).get(1)).longValue());
recallSeries.forEach(
series -> series.getValues().forEach(
values -> events.getEvents().add(parseSeriesValues(series, values))
)
);
return events;
}
protected org.apache.skywalking.oap.server.core.query.type.event.Event parseSeriesValues(final QueryResult.Series series, final List<Object> values) {
final org.apache.skywalking.oap.server.core.query.type.event.Event event = new org.apache.skywalking.oap.server.core.query.type.event.Event();
final List<String> columns = series.getColumns();
final Map<String, Object> data = new HashMap<>();
for (int i = 1; i < columns.size(); i++) {
Object value = values.get(i);
if (value instanceof StorageDataComplexObject) {
value = ((StorageDataComplexObject) value).toStorageData();
}
data.put(columns.get(i), value);
}
event.setUuid((String) data.get(Event.UUID));
final String service = (String) data.get(Event.SERVICE);
final String serviceInstance = (String) data.get(Event.SERVICE_INSTANCE);
final String endpoint = (String) data.get(Event.ENDPOINT);
event.setSource(new Source(service, serviceInstance, endpoint));
event.setName((String) data.get(Event.NAME));
event.setType(EventType.parse((String) data.get(Event.TYPE)));
event.setMessage((String) data.get(Event.MESSAGE));
event.setParameters((String) data.get(Event.PARAMETERS));
event.setStartTime(((Number) data.get(Event.START_TIME)).longValue());
event.setEndTime(((Number) data.get(Event.END_TIME)).longValue());
return event;
}
protected WhereQueryImpl<SelectQueryImpl> buildQuery(final EventQueryCondition condition) {
final String topFunc = Order.DES.equals(condition.getOrder()) ? InfluxConstants.SORT_DES : InfluxConstants.SORT_ASC;
final WhereQueryImpl<SelectQueryImpl> query =
select().raw(ALL_FIELDS)
.function(topFunc, Event.START_TIME, condition.getSize())
.from(client.getDatabase(), Event.INDEX_NAME)
.where();
if (!isNullOrEmpty(condition.getUuid())) {
query.and(eq(Event.UUID, condition.getUuid()));
}
final Source source = condition.getSource();
if (source != null) {
if (!isNullOrEmpty(source.getService())) {
query.and(eq(Event.SERVICE, source.getService()));
}
if (!isNullOrEmpty(source.getServiceInstance())) {
query.and(eq(Event.SERVICE_INSTANCE, source.getServiceInstance()));
}
if (!isNullOrEmpty(source.getEndpoint())) {
query.and(contains(Event.ENDPOINT, source.getEndpoint().replaceAll("/", "\\\\/")));
}
}
if (!isNullOrEmpty(condition.getName())) {
query.and(eq(InfluxConstants.NAME, condition.getName()));
}
if (condition.getType() != null) {
query.and(eq(Event.TYPE, condition.getType().name()));
}
final Duration startTime = condition.getTime();
if (startTime != null) {
if (startTime.getStartTimestamp() > 0) {
query.and(gt(Event.START_TIME, startTime.getStartTimestamp()));
}
if (startTime.getEndTimestamp() > 0) {
query.and(lt(Event.END_TIME, startTime.getEndTimestamp()));
}
}
return query;
}
}
......@@ -37,6 +37,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnaps
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -53,6 +54,7 @@ import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2Aggregation
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2AlarmQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2BatchDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2BrowserLogQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2EventQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2HistoryDeleteDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2LogQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2MetadataQueryDAO;
......@@ -154,6 +156,8 @@ public class H2StorageProvider extends ModuleProvider {
this.registerServiceImplementation(
IProfileThreadSnapshotQueryDAO.class, new H2ProfileThreadSnapshotQueryDAO(h2Client));
this.registerServiceImplementation(UITemplateManagementDAO.class, new H2UITemplateManagementDAO(h2Client));
this.registerServiceImplementation(IEventQueryDAO.class, new H2EventQueryDAO(h2Client));
}
@Override
......
/*
* 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.oap.server.storage.plugin.jdbc.h2.dao;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.event.Event;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.type.event.EventQueryCondition;
import org.apache.skywalking.oap.server.core.query.type.event.Events;
import org.apache.skywalking.oap.server.core.query.type.event.Source;
import org.apache.skywalking.oap.server.core.query.type.event.EventType;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import static com.google.common.base.Strings.isNullOrEmpty;
@Slf4j
@RequiredArgsConstructor
public class H2EventQueryDAO implements IEventQueryDAO {
private final JDBCHikariCPClient client;
@Override
public Events queryEvents(final EventQueryCondition condition) throws Exception {
final List<String> conditions = new ArrayList<>();
final List<Object> parameters = new ArrayList<>();
if (!isNullOrEmpty(condition.getUuid())) {
conditions.add(Event.UUID + "=?");
parameters.add(condition.getUuid());
}
final Source source = condition.getSource();
if (source != null) {
if (!isNullOrEmpty(source.getService())) {
conditions.add(Event.SERVICE + "=?");
parameters.add(source.getService());
}
if (!isNullOrEmpty(source.getServiceInstance())) {
conditions.add(Event.SERVICE_INSTANCE + "=?");
parameters.add(source.getServiceInstance());
}
if (!isNullOrEmpty(source.getEndpoint())) {
conditions.add(Event.ENDPOINT + "=?");
parameters.add(source.getEndpoint());
}
}
if (!isNullOrEmpty(condition.getName())) {
conditions.add(Event.NAME + "=?");
parameters.add(condition.getName());
}
if (condition.getType() != null) {
conditions.add(Event.TYPE + "=?");
parameters.add(condition.getType().name());
}
final Duration time = condition.getTime();
if (time != null) {
if (time.getStartTimestamp() > 0) {
conditions.add(Event.START_TIME + ">?");
parameters.add(time.getStartTimestamp());
}
if (time.getEndTimestamp() > 0) {
conditions.add(Event.END_TIME + "<?");
parameters.add(time.getEndTimestamp());
}
}
final String whereClause = conditions.isEmpty() ? "" : conditions.stream().collect(Collectors.joining(" and ", " where ", ""));
final Events result = new Events();
try (final Connection connection = client.getConnection()) {
String sql = "select count(1) total from " + Event.INDEX_NAME + whereClause;
if (log.isDebugEnabled()) {
log.debug("Count SQL: {}, parameters: {}", sql, parameters);
}
try (final ResultSet resultSet = client.executeQuery(connection, sql, parameters.toArray())) {
if (!resultSet.next()) {
return result;
}
result.setTotal(resultSet.getInt("total"));
}
sql = "select * from " + Event.INDEX_NAME + whereClause + " limit " + condition.getSize();
if (log.isDebugEnabled()) {
log.debug("Query SQL: {}, parameters: {}", sql, parameters);
}
try (final ResultSet resultSet = client.executeQuery(connection, sql, parameters.toArray())) {
while (resultSet.next()) {
result.getEvents().add(parseResultSet(resultSet));
}
}
}
return result;
}
protected org.apache.skywalking.oap.server.core.query.type.event.Event parseResultSet(final ResultSet resultSet) throws SQLException {
final org.apache.skywalking.oap.server.core.query.type.event.Event event = new org.apache.skywalking.oap.server.core.query.type.event.Event();
event.setUuid(resultSet.getString(Event.UUID));
final String service = resultSet.getString(Event.SERVICE);
final String serviceInstance = resultSet.getString(Event.SERVICE_INSTANCE);
final String endpoint = resultSet.getString(Event.ENDPOINT);
event.setSource(new Source(service, serviceInstance, endpoint));
event.setName(resultSet.getString(Event.NAME));
event.setType(EventType.parse(resultSet.getString(Event.TYPE)));
event.setMessage(resultSet.getString(Event.MESSAGE));
event.setParameters(resultSet.getString(Event.PARAMETERS));
event.setStartTime(resultSet.getLong(Event.START_TIME));
event.setEndTime(resultSet.getLong(Event.END_TIME));
return event;
}
}
......@@ -36,6 +36,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnaps
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -49,6 +50,7 @@ import org.apache.skywalking.oap.server.library.module.ModuleProvider;
import org.apache.skywalking.oap.server.library.module.ModuleStartException;
import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2BatchDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2EventQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2HistoryDeleteDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2MetadataQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2MetricsQueryDAO;
......@@ -141,6 +143,8 @@ public class MySQLStorageProvider extends ModuleProvider {
this.registerServiceImplementation(
IProfileThreadSnapshotQueryDAO.class, new H2ProfileThreadSnapshotQueryDAO(mysqlClient));
this.registerServiceImplementation(UITemplateManagementDAO.class, new H2UITemplateManagementDAO(mysqlClient));
this.registerServiceImplementation(IEventQueryDAO.class, new H2EventQueryDAO(mysqlClient));
}
@Override
......
......@@ -36,6 +36,7 @@ import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnaps
import org.apache.skywalking.oap.server.core.storage.query.IAggregationQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IAlarmQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IBrowserLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ILogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetadataQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO;
......@@ -49,6 +50,7 @@ import org.apache.skywalking.oap.server.library.module.ModuleProvider;
import org.apache.skywalking.oap.server.library.module.ModuleStartException;
import org.apache.skywalking.oap.server.library.module.ServiceNotProvidedException;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2BatchDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2EventQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2HistoryDeleteDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2MetadataQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2MetricsQueryDAO;
......@@ -146,6 +148,8 @@ public class TiDBStorageProvider extends ModuleProvider {
this.registerServiceImplementation(UITemplateManagementDAO.class, new H2UITemplateManagementDAO(mysqlClient));
this.registerServiceImplementation(IHistoryDeleteDAO.class, new TiDBHistoryDeleteDAO(mysqlClient));
this.registerServiceImplementation(IEventQueryDAO.class, new H2EventQueryDAO(mysqlClient));
}
@Override
......
......@@ -39,6 +39,7 @@ import org.apache.skywalking.oap.server.core.profile.ProfileTaskMutationService;
import org.apache.skywalking.oap.server.core.query.AggregationQueryService;
import org.apache.skywalking.oap.server.core.query.AlarmQueryService;
import org.apache.skywalking.oap.server.core.query.BrowserLogQueryService;
import org.apache.skywalking.oap.server.core.query.EventQueryService;
import org.apache.skywalking.oap.server.core.query.LogQueryService;
import org.apache.skywalking.oap.server.core.query.MetadataQueryService;
import org.apache.skywalking.oap.server.core.query.MetricsMetadataQueryService;
......@@ -170,6 +171,8 @@ public class MockCoreModuleProvider extends CoreModuleProvider {
// Management
this.registerServiceImplementation(UITemplateManagementService.class, new UITemplateManagementService(getManager()));
this.registerServiceImplementation(EventQueryService.class, new EventQueryService(getManager()));
}
@Override
......
......@@ -32,6 +32,9 @@ import org.apache.skywalking.e2e.alarm.GetAlarmData;
import org.apache.skywalking.e2e.browser.BrowserErrorLog;
import org.apache.skywalking.e2e.browser.BrowserErrorLogQuery;
import org.apache.skywalking.e2e.browser.BrowserErrorLogsData;
import org.apache.skywalking.e2e.event.Event;
import org.apache.skywalking.e2e.event.EventData;
import org.apache.skywalking.e2e.event.EventsQuery;
import org.apache.skywalking.e2e.log.Log;
import org.apache.skywalking.e2e.log.LogData;
import org.apache.skywalking.e2e.log.LogsQuery;
......@@ -437,4 +440,22 @@ public class SimpleQueryClient {
}
return Objects.requireNonNull(responseEntity.getBody().getData().isSupport());
}
public List<Event> events(final EventsQuery query) throws Exception {
final URL queryFileUrl = Resources.getResource("events.gql");
final String queryString = Resources.readLines(queryFileUrl, StandardCharsets.UTF_8)
.stream().filter(it -> !it.startsWith("#"))
.collect(Collectors.joining())
.replace("{uuid}", query.uuid());
LOGGER.info("Query: {}", queryString);
final ResponseEntity<GQLResponse<EventData>> responseEntity = restTemplate.exchange(
new RequestEntity<>(queryString, HttpMethod.POST, URI.create(endpointUrl)),
new ParameterizedTypeReference<GQLResponse<EventData>>() {
}
);
if (responseEntity.getStatusCode() != HttpStatus.OK) {
throw new RuntimeException("Response status != 200, actual: " + responseEntity.getStatusCode());
}
return Objects.requireNonNull(responseEntity.getBody()).getData().getEvents().getData();
}
}
......@@ -27,7 +27,7 @@ import static java.util.Objects.nonNull;
@Setter
@Getter
@ToString(callSuper = true)
@ToString
@EqualsAndHashCode(callSuper = true)
public class KeyValueMatcher extends AbstractMatcher<KeyValue> {
......
/*
* 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.e2e.event;
import java.util.List;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.skywalking.e2e.common.KeyValue;
@Data
@Accessors(chain = true)
public class Event {
private String uuid;
private Source source;
private String name;
private String type;
private String message;
private List<KeyValue> parameters;
private String startTime;
private String endTime;
@Data
@Accessors(chain = true)
static class Source {
private String service;
private String serviceInstance;
private String endpoint;
}
}
/*
* 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.e2e.event;
import java.util.List;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
public class EventData {
@Data
@Accessors(chain = true)
public static class Events {
private List<Event> data;
}
private Events events;
}
/*
* 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.e2e.event;
import java.util.List;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.skywalking.e2e.common.KeyValue;
import org.apache.skywalking.e2e.common.KeyValueMatcher;
import org.apache.skywalking.e2e.verification.AbstractMatcher;
import static java.util.Objects.nonNull;
import static org.assertj.core.api.Assertions.fail;
@Setter
@Getter
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class EventMatcher extends AbstractMatcher<Event> {
private String uuid;
private Source source;
private String name;
private String type;
private String message;
private List<KeyValueMatcher> parameters;
private String startTime;
private String endTime;
@Override
public void verify(final Event event) {
if (nonNull(getUuid())) {
doVerify(getUuid(), event.getUuid());
}
if (nonNull(getSource())) {
if (nonNull(getSource().getService())) {
doVerify(getSource().getService(), event.getSource().getService());
}
if (nonNull(getSource().getServiceInstance())) {
doVerify(getSource().getServiceInstance(), event.getSource().getServiceInstance());
}
if (nonNull(getSource().getEndpoint())) {
doVerify(getSource().getEndpoint(), event.getSource().getEndpoint());
}
}
if (nonNull(getName())) {
doVerify(getName(), event.getName());
}
if (nonNull(getType())) {
doVerify(getType(), event.getType());
}
if (nonNull(getMessage())) {
doVerify(getMessage(), event.getMessage());
}
if (nonNull(getStartTime())) {
doVerify(getStartTime(), event.getStartTime());
}
if (nonNull(getEndTime())) {
doVerify(getEndTime(), event.getEndTime());
}
if (nonNull(getParameters())) {
for (final KeyValueMatcher matcher : getParameters()) {
boolean matched = false;
for (final KeyValue keyValue : event.getParameters()) {
try {
matcher.verify(keyValue);
matched = true;
} catch (Throwable ignore) {
}
}
if (!matched) {
fail("\nExpected: %s\n Actual: %s", getParameters(), event.getParameters());
}
}
}
}
@Getter
@Setter
@ToString
public static class Source {
private String service;
private String serviceInstance;
private String endpoint;
}
}
/*
* 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.e2e.event;
import java.util.LinkedList;
import java.util.List;
import lombok.Data;
import static org.assertj.core.api.Assertions.fail;
@Data
public class EventsMatcher {
private List<EventMatcher> events;
public EventsMatcher() {
this.events = new LinkedList<>();
}
public void verifyLoosely(final List<Event> events) {
for (final EventMatcher matcher : getEvents()) {
boolean matched = false;
for (final Event log : events) {
try {
matcher.verify(log);
matched = true;
} catch (Throwable e) {
// ignore
}
}
if (!matched) {
fail("\nExpected: %s\n Actual: %s", getEvents(), events);
}
}
}
}
/*
* 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.e2e.event;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.skywalking.e2e.AbstractQuery;
@Getter
@Setter
@Accessors(fluent = true)
public class EventsQuery extends AbstractQuery<EventsQuery> {
private String uuid;
}
# 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.
{
"query": "query queryEvents($condition: EventQueryCondition) {
events: queryEvents(condition: $condition) {
data: events {
name
source {
service serviceInstance endpoint
}
startTime
endTime
message
parameters {
key value
}
uuid
}
}
}",
"variables": {
"condition": {
"uuid": "{uuid}"
}
}
}
# 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.
FROM golang:1.14 AS builder
ARG COMMIT_HASH=ae085deb32434a0859e49c45819fed7a5c4010b5
ARG CLI_CODE=${COMMIT_HASH}.tar.gz
ARG CLI_CODE_URL=https://github.com/apache/skywalking-cli/archive/${CLI_CODE}
ENV CGO_ENABLED=0
ENV GO111MODULE=on
WORKDIR /cli
ADD ${CLI_CODE_URL} .
RUN tar -xf ${CLI_CODE} --strip 1
RUN rm ${CLI_CODE}
RUN make build && mv bin/swctl-latest-linux-amd64 /swctl
ENTRYPOINT [ "/swctl" ]
# 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.
version: '2.1'
services:
es:
image: elastic/elasticsearch:6.3.2
expose:
- 9200
networks:
- e2e
environment:
- discovery.type=single-node
- cluster.routing.allocation.disk.threshold_enabled=false
healthcheck:
test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9200"]
interval: 5s
timeout: 60s
retries: 120
oap:
extends:
file: ../base-compose.yml
service: oap
environment:
SW_STORAGE: elasticsearch
SW_PROMETHEUS_FETCHER: "default"
SW_TELEMETRY: prometheus
depends_on:
es:
condition: service_healthy
networks:
e2e:
# 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.
version: '2.1'
services:
es:
image: elastic/elasticsearch:7.0.0
expose:
- 9200
networks:
- e2e
environment:
- discovery.type=single-node
- cluster.routing.allocation.disk.threshold_enabled=false
healthcheck:
test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9200"]
interval: 5s
timeout: 60s
retries: 120
oap:
extends:
file: ../base-compose.yml
service: oap-es7
environment:
SW_STORAGE: elasticsearch7
SW_PROMETHEUS_FETCHER: "default"
SW_TELEMETRY: prometheus
depends_on:
es:
condition: service_healthy
networks:
e2e:
# 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.
version: '2.1'
services:
h2db:
build:
context: .
dockerfile: ../Dockerfile.h2
networks:
- e2e
expose:
- 1521
healthcheck:
test: ["CMD", "sh", "-c", "nc -z 127.0.0.1 1521"]
interval: 5s
timeout: 60s
retries: 120
oap:
extends:
file: ../base-compose.yml
service: oap
environment:
SW_STORAGE: h2
SW_STORAGE_H2_URL: jdbc:h2:tcp://h2db:1521/skywalking-oap-db
depends_on:
h2db:
condition: service_healthy
networks:
e2e:
\ No newline at end of file
# 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.
version: '2.1'
services:
influxdb:
image: influxdb:1.7.9
expose:
- 8086
networks:
- e2e
healthcheck:
test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/8086"]
interval: 5s
timeout: 60s
retries: 120
oap:
extends:
file: ../base-compose.yml
service: oap
environment:
SW_STORAGE: influxdb
SW_PROMETHEUS_FETCHER: "default"
SW_TELEMETRY: prometheus
depends_on:
influxdb:
condition: service_healthy
networks:
e2e:
# 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.
version: '2.1'
services:
mysql:
image: mysql/mysql-server:8.0.13
networks:
- e2e
expose:
- 3306
environment:
- MYSQL_ROOT_PASSWORD=root@1234
- MYSQL_DATABASE=swtest
- MYSQL_ROOT_HOST=%
healthcheck:
test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/3306"]
interval: 5s
timeout: 60s
retries: 120
oap:
extends:
file: ../base-compose.yml
service: oap
environment:
SW_STORAGE: mysql
SW_PROMETHEUS_FETCHER: "default"
SW_TELEMETRY: prometheus
depends_on:
mysql:
condition: service_healthy
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
networks:
e2e:
# 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.
version: '3.8'
services:
ui:
extends:
file: ../base-compose.yml
service: ui
depends_on:
oap:
condition: service_healthy
cli:
build:
context: .
dockerfile: ../Dockerfile.cli
networks:
- e2e
entrypoint:
- /bin/sh
- -c
command:
- >-
/swctl
--grpcAddr=oap:11800
event report
--uuid=abcde
--name=Upgrade
--service=e2e-service
--instance=e2e-service-instance
--endpoint='/e2e-endpoint'
--message='Upgrade from {fromVersion} to {toVersion}'
--startTime=`date +%s`000
--endTime=`date +%s`999
fromVersion=v1
toVersion=v2
depends_on:
oap:
condition: service_healthy
networks:
e2e:
/*
* 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.e2e.event;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.e2e.ProfileClient;
import org.apache.skywalking.e2e.annotation.ContainerHostAndPort;
import org.apache.skywalking.e2e.annotation.DockerCompose;
import org.apache.skywalking.e2e.base.SkyWalkingE2E;
import org.apache.skywalking.e2e.base.SkyWalkingTestAdapter;
import org.apache.skywalking.e2e.common.HostAndPort;
import org.apache.skywalking.e2e.retryable.RetryableTest;
import org.junit.jupiter.api.BeforeAll;
import org.testcontainers.containers.DockerComposeContainer;
import static org.apache.skywalking.e2e.utils.Times.now;
import static org.apache.skywalking.e2e.utils.Yamls.load;
@Slf4j
@SkyWalkingE2E
public class EventE2E extends SkyWalkingTestAdapter {
@SuppressWarnings("unused")
@DockerCompose({
"docker/event/docker-compose.yml",
"docker/event/docker-compose.${SW_STORAGE}.yml",
})
protected DockerComposeContainer<?> compose;
@SuppressWarnings("unused")
@ContainerHostAndPort(name = "ui", port = 8080)
protected HostAndPort swWebappHostPort;
private ProfileClient graphql;
@BeforeAll
public void setUp() {
graphql = new ProfileClient(swWebappHostPort.host(), swWebappHostPort.port());
}
@RetryableTest
void events() throws Exception {
final List<Event> events = graphql.events(new EventsQuery().start(startTime).end(now()).uuid("abcde"));
LOGGER.info("events: {}", events);
load("expected/event/events.yml").as(EventsMatcher.class).verifyLoosely(events);
}
}
# 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.
events:
- name: Upgrade
source:
service: e2e-service
serviceInstance: e2e-service-instance
endpoint: /e2e-endpoint
startTime: gt 0
endTime: gt 0
message: Upgrade from {fromVersion} to {toVersion}
parameters:
- key: fromVersion
value: v1
- key: toVersion
value: v2
uuid: abcde
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册