Support sharding MySQL database instances and tables. (#9689)

* [**Breaking Change**] Support sharding MySQL database instances and tables by [Shardingsphere-Proxy](https://shardingsphere.apache.org/document/current/en/overview/#shardingsphere-proxy).
  SQL-Database requires removing tables `log_tag/segment_tag/zipkin_query` before OAP starts, if bump up from previous releases.
This commit is contained in:
Wan Kai 2022-09-30 08:39:14 +08:00 committed by GitHub
parent fdc24ed822
commit d7ee9a01d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
101 changed files with 3208 additions and 64 deletions

View File

@ -573,6 +573,15 @@ jobs:
config: test/e2e-v2/cases/zipkin/postgres/e2e.yaml
- name: Zipkin Kafka
config: test/e2e-v2/cases/zipkin/kafka/e2e.yaml
- name: MySQL-Sharding storage
config: test/e2e-v2/cases/storage/mysql/sharding/e2e.yaml
- name: MySQL-Sharding log
config: test/e2e-v2/cases/log/mysql/sharding/e2e.yaml
- name: MySQL-Sharding browser
config: test/e2e-v2/cases/browser/mysql/sharding/e2e.yaml
- name: MySQL-Sharding zipkin
config: test/e2e-v2/cases/zipkin/mysql/sharding/e2e.yaml
steps:
- uses: actions/checkout@v3
with:

View File

@ -50,7 +50,7 @@ and multiple formats, including
6. Browser agent.
7. Service Mesh Observability. Control plane and data plane.
8. Metrics system, including Prometheus, OpenTelemetry, Micrometer(Spring Sleuth), Zabbix.
9. Logs including OpenTelemetry.
9. Logs, including OpenTelemetry.
10. Zipkin v1/v2 trace.(No Analysis).
# Documentation

View File

@ -20,6 +20,8 @@
in `no-init` mode.
* Make sure instance list ordered in TTL processor to avoid TTL timer never runs.
* Support monitoring PostgreSQL slow SQLs.
* [**Breaking Change**] Support sharding MySQL database instances and tables by [Shardingsphere-Proxy](https://shardingsphere.apache.org/document/current/en/overview/#shardingsphere-proxy).
SQL-Database requires removing tables `log_tag/segment_tag/zipkin_query` before OAP starts, if bump up from previous releases.
* Fix meter functions `avgHistogram`, `avgHistogramPercentile`, `avgLabeled`, `sumHistogram` having data conflict when
downsampling.
* Do sorting `readLabeledMetricsValues` result forcedly in case the storage(database) doesn't return data consistent

View File

@ -12,6 +12,7 @@ Natively supported storage:
- OpenSearch
- ElasticSearch 6, 7, 8
- MySQL
- MySQL-Sharding(Shardingsphere-Proxy 5.1.2)
- TiDB
- PostgreSQL
- BanyanDB
@ -211,6 +212,34 @@ All connection-related settings, including URL link, username, and password, are
Only part of the settings is listed here. See the [HikariCP](https://github.com/brettwooldridge/HikariCP) connection pool document for full settings.
To understand the function of the parameter `rewriteBatchedStatements=true` in MySQL, see the [MySQL official document](https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-performance-extensions.html#cj-conn-prop_rewriteBatchedStatements).
## MySQL-Sharding
MySQL-Sharding plugin provides the MySQL database sharding and table sharding, this feature
leverage [Shardingsphere-Proxy](https://shardingsphere.apache.org/document/current/en/overview/#shardingsphere-proxy)
to manage the JDBC between OAP and multi-database instances, and according to the sharding rules do routing to the database and table sharding.
Tested Shardingsphere-Proxy 5.1.2 version, and MySQL Client driver 8.0.13 version is currently available.
Activate MySQL and Shardingsphere-Proxy as storage, and set storage provider to **mysql-sharding**.
**NOTE:** MySQL driver is NOT allowed in Apache official distribution and source codes.
Please download the MySQL driver on your own. Copy the connection driver jar to `oap-libs`.
```yaml
storage:
selector: ${SW_STORAGE:mysql-sharding}
mysql-sharding:
properties:
jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:13307/swtest?rewriteBatchedStatements=true"}
dataSource.user: ${SW_DATA_SOURCE_USER:root}
dataSource.password: ${SW_DATA_SOURCE_PASSWORD:root}
metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}
maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:2000}
asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:4}
# The dataSources are configured in ShardingSphere-Proxy config-sharding.yaml
# The dataSource name should include the prefix "ds_" and separated by ","
dataSources: ${SW_JDBC_SHARDING_DATA_SOURCES:ds_0,ds_1}
```
## TiDB
Tested TiDB Server 4.0.8 version, and MySQL Client driver 8.0.13 version is currently available.
Activate TiDB as storage, and set storage provider to **tidb**.

View File

@ -126,15 +126,17 @@ The Configuration Vocabulary lists all available configurations provided by `app
| - | mysql | - | MySQL Storage. The MySQL JDBC Driver is not in the dist. Please copy it into the oap-lib folder manually. | - | - |
| - | - | properties | Hikari connection pool configurations. | - | Listed in the `application.yaml`. |
| - | - | metadataQueryMaxSize | The maximum size of metadata per query. | SW_STORAGE_MYSQL_QUERY_MAX_SIZE | 5000 |
| - | - | maxSizeOfArrayColumn | Some entities (e.g. trace segments) include the logic column with multiple values. In MySQL, we use multiple physical columns to host the values, e.g. change column_a with values [1,2,3,4,5] to `column_a_0 = 1, column_a_1 = 2, column_a_2 = 3 , column_a_3 = 4, column_a_4 = 5`. | SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN | 20 |
| - | - | numOfSearchableValuesPerTag | In a trace segment, this includes multiple spans with multiple tags. Different spans may have same tag key, e.g. multiple HTTP exit spans all have their own `http.method` tags. This configuration sets the limit on the maximum number of values for the same tag key. | SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG | 2 |
| - | - | maxSizeOfBatchSql | The maximum size of batch size of SQL execution | SW_STORAGE_MAX_SIZE_OF_BATCH_SQL | 2000 |
| - | - | asyncBatchPersistentPoolSize | async flush data into database thread size | SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE | 4 |
| - | mysql-sharding | - | Sharding-Proxy for MySQL properties. The MySQL JDBC Driver is not in the dist. Please copy it into the oap-lib folder manually. | - | - |
| - | - | properties | Hikari connection pool configurations. | - | Listed in the `application.yaml`. |
| - | - | metadataQueryMaxSize | The maximum size of metadata per query. | SW_STORAGE_MYSQL_QUERY_MAX_SIZE | 5000 |
| - | - | maxSizeOfBatchSql | The maximum size of batch size of SQL execution | SW_STORAGE_MAX_SIZE_OF_BATCH_SQL | 2000 |
| - | - | asyncBatchPersistentPoolSize | async flush data into database thread size | SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE | 4 |
| - | - | dataSources | The dataSources are configured in ShardingSphere-Proxy config-sharding.yaml.The dataSource name should include the prefix "ds_" and separated by "," and start from ds_0 | SW_JDBC_SHARDING_DATA_SOURCES | ds_0,ds_1 |
| - | postgresql | - | PostgreSQL storage. | - | - |
| - | - | properties | Hikari connection pool configurations. | - | Listed in the `application.yaml`. |
| - | - | metadataQueryMaxSize | The maximum size of metadata per query. | SW_STORAGE_MYSQL_QUERY_MAX_SIZE | 5000 |
| - | - | maxSizeOfArrayColumn | Some entities (e.g. trace segments) include the logic column with multiple values. In PostgreSQL, we use multiple physical columns to host the values, e.g. change column_a with values [1,2,3,4,5] to `column_a_0 = 1, column_a_1 = 2, column_a_2 = 3 , column_a_3 = 4, column_a_4 = 5` | SW_STORAGE_MAX_SIZE_OF_ARRAY_COLUMN | 20 |
| - | - | numOfSearchableValuesPerTag | In a trace segment, this includes multiple spans with multiple tags. Different spans may have same tag key, e.g. multiple HTTP exit spans all have their own `http.method` tags. This configuration sets the limit on the maximum number of values for the same tag key. | SW_STORAGE_NUM_OF_SEARCHABLE_VALUES_PER_TAG | 2 |
| - | - | maxSizeOfBatchSql | The maximum size of batch size of SQL execution | SW_STORAGE_MAX_SIZE_OF_BATCH_SQL | 2000 |
| - | - | asyncBatchPersistentPoolSize | async flush data into database thread size | SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE | 4 |
| - | banyandb | - | BanyanDB storage. | - | - |

View File

@ -25,7 +25,7 @@ import org.apache.skywalking.oap.server.core.analysis.Layer;
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.source.Event;
import org.apache.skywalking.oap.server.core.analysis.metrics.Event;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import lombok.RequiredArgsConstructor;

View File

@ -30,16 +30,22 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.ElasticSearch;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.ID;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.TIME_BUCKET;
@Stream(name = EndpointTraffic.INDEX_NAME, scopeId = DefaultScopeDefine.ENDPOINT,
builder = EndpointTraffic.Builder.class, processor = MetricsStreamProcessor.class)
@MetricsExtension(supportDownSampling = false, supportUpdate = false)
@EqualsAndHashCode
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.TIME_MIN_RANGE_SHARDING_ALGORITHM, tableShardingColumn = TIME_BUCKET, dataSourceShardingColumn = ID)
public class EndpointTraffic extends Metrics {
public static final String INDEX_NAME = "endpoint_traffic";

View File

@ -30,8 +30,10 @@ import org.apache.skywalking.oap.server.core.analysis.Stream;
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.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.ElasticSearch;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -46,6 +48,7 @@ import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.SE
"serviceId",
"name"
})
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class InstanceTraffic extends Metrics {
public static final String INDEX_NAME = "instance_traffic";
public static final String SERVICE_ID = "service_id";

View File

@ -50,6 +50,7 @@ public abstract class AbstractLogRecord extends Record {
@Getter
@Column(columnName = SERVICE_ID)
@BanyanDB.ShardingKey(index = 0)
@SQLDatabase.AdditionalEntity(additionalTables = {ADDITIONAL_TAG_TABLE}, reserveOriginalColumns = true)
private String serviceId;
@Setter
@Getter

View File

@ -22,16 +22,20 @@ import lombok.Setter;
import org.apache.skywalking.oap.server.core.analysis.Stream;
import org.apache.skywalking.oap.server.core.analysis.worker.RecordStreamProcessor;
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.annotation.SuperDataset;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import static org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord.SERVICE_ID;
import static org.apache.skywalking.oap.server.core.analysis.record.Record.TIME_BUCKET;
@SuperDataset
@Stream(name = LogRecord.INDEX_NAME, scopeId = DefaultScopeDefine.LOG, builder = LogRecord.Builder.class, processor = RecordStreamProcessor.class)
@SQLDatabase.ExtraColumn4AdditionalEntity(additionalTable = AbstractLogRecord.ADDITIONAL_TAG_TABLE, parentColumn = TIME_BUCKET)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.TIME_SEC_RANGE_SHARDING_ALGORITHM, dataSourceShardingColumn = SERVICE_ID, tableShardingColumn = TIME_BUCKET)
public class LogRecord extends AbstractLogRecord {
public static final String INDEX_NAME = "log";

View File

@ -28,8 +28,10 @@ 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.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.BanyanDB;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -43,6 +45,7 @@ import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.NE
@EqualsAndHashCode(of = {
"address"
})
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class NetworkAddressAlias extends Metrics {
public static final String INDEX_NAME = "network_address_alias";
public static final String ADDRESS = "address";

View File

@ -31,7 +31,9 @@ import org.apache.skywalking.oap.server.core.analysis.Stream;
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.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -48,6 +50,7 @@ import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.PR
"instanceId",
"name",
})
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class ProcessTraffic extends Metrics {
public static final String INDEX_NAME = "process_traffic";
public static final String SERVICE_ID = "service_id";

View File

@ -26,7 +26,9 @@ import org.apache.skywalking.oap.server.core.analysis.Stream;
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.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -50,6 +52,7 @@ import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.SE
"serviceId",
"label"
})
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class ServiceLabelRecord extends Metrics {
public static final String INDEX_NAME = "service_label";
@ -125,4 +128,4 @@ public class ServiceLabelRecord extends Metrics {
converter.accept(TIME_BUCKET, entity.getTimeBucket());
}
}
}
}

View File

@ -27,17 +27,23 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.BanyanDB;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.ENTITY_ID;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.TIME_BUCKET;
@Stream(name = EndpointRelationServerSideMetrics.INDEX_NAME, scopeId = DefaultScopeDefine.ENDPOINT_RELATION,
builder = EndpointRelationServerSideMetrics.Builder.class, processor = MetricsStreamProcessor.class)
@EqualsAndHashCode(of = {
"entityId"
}, callSuper = true)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.TIME_BUCKET_SHARDING_ALGORITHM, tableShardingColumn = TIME_BUCKET, dataSourceShardingColumn = ENTITY_ID)
public class EndpointRelationServerSideMetrics extends Metrics {
public static final String INDEX_NAME = "endpoint_relation_server_side";

View File

@ -27,16 +27,22 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.ENTITY_ID;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.TIME_BUCKET;
@Stream(name = ServiceInstanceRelationClientSideMetrics.INDEX_NAME, scopeId = DefaultScopeDefine.SERVICE_INSTANCE_RELATION,
builder = ServiceInstanceRelationClientSideMetrics.Builder.class, processor = MetricsStreamProcessor.class)
@EqualsAndHashCode(of = {
"entityId"
}, callSuper = true)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.TIME_BUCKET_SHARDING_ALGORITHM, tableShardingColumn = TIME_BUCKET, dataSourceShardingColumn = ENTITY_ID)
public class ServiceInstanceRelationClientSideMetrics extends Metrics {
public static final String INDEX_NAME = "service_instance_relation_client_side";

View File

@ -27,17 +27,23 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.BanyanDB;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.ENTITY_ID;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.TIME_BUCKET;
@Stream(name = ServiceInstanceRelationServerSideMetrics.INDEX_NAME, scopeId = DefaultScopeDefine.SERVICE_INSTANCE_RELATION,
builder = ServiceInstanceRelationServerSideMetrics.Builder.class, processor = MetricsStreamProcessor.class)
@EqualsAndHashCode(of = {
"entityId"
}, callSuper = true)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.TIME_BUCKET_SHARDING_ALGORITHM, tableShardingColumn = TIME_BUCKET, dataSourceShardingColumn = ENTITY_ID)
public class ServiceInstanceRelationServerSideMetrics extends Metrics {
public static final String INDEX_NAME = "service_instance_relation_server_side";

View File

@ -28,7 +28,9 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -39,6 +41,7 @@ import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@EqualsAndHashCode(of = {
"entityId"
}, callSuper = true)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class ProcessRelationClientSideMetrics extends Metrics {
public static final String INDEX_NAME = "process_relation_client_side";
@ -146,4 +149,4 @@ public class ProcessRelationClientSideMetrics extends Metrics {
converter.accept(COMPONENT_ID, storageData.getComponentId());
}
}
}
}

View File

@ -28,7 +28,9 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -39,6 +41,7 @@ import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@EqualsAndHashCode(of = {
"entityId"
}, callSuper = true)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class ProcessRelationServerSideMetrics extends Metrics {
public static final String INDEX_NAME = "process_relation_server_side";

View File

@ -27,16 +27,22 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.ENTITY_ID;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.TIME_BUCKET;
@Stream(name = ServiceRelationClientSideMetrics.INDEX_NAME, scopeId = DefaultScopeDefine.SERVICE_RELATION,
builder = ServiceRelationClientSideMetrics.Builder.class, processor = MetricsStreamProcessor.class)
@EqualsAndHashCode(of = {
"entityId"
}, callSuper = true)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.TIME_BUCKET_SHARDING_ALGORITHM, tableShardingColumn = TIME_BUCKET, dataSourceShardingColumn = ENTITY_ID)
public class ServiceRelationClientSideMetrics extends Metrics {
public static final String INDEX_NAME = "service_relation_client_side";

View File

@ -27,17 +27,23 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.BanyanDB;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.ENTITY_ID;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.TIME_BUCKET;
@Stream(name = ServiceRelationServerSideMetrics.INDEX_NAME, scopeId = DefaultScopeDefine.SERVICE_RELATION,
builder = ServiceRelationServerSideMetrics.Builder.class, processor = MetricsStreamProcessor.class)
@EqualsAndHashCode(of = {
"entityId"
}, callSuper = true)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.TIME_BUCKET_SHARDING_ALGORITHM, tableShardingColumn = TIME_BUCKET, dataSourceShardingColumn = ENTITY_ID)
public class ServiceRelationServerSideMetrics extends Metrics {
public static final String INDEX_NAME = "service_relation_server_side";

View File

@ -27,7 +27,9 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -40,6 +42,7 @@ import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
"tagValue",
"tagType"
})
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class TagAutocompleteData extends Metrics {
public static final String INDEX_NAME = "tag_autocomplete";
public static final String TAG_KEY = "tag_key";

View File

@ -25,6 +25,7 @@ import org.apache.skywalking.oap.server.core.analysis.Stream;
import org.apache.skywalking.oap.server.core.analysis.record.Record;
import org.apache.skywalking.oap.server.core.analysis.worker.RecordStreamProcessor;
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.BanyanDB;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
@ -32,11 +33,14 @@ import org.apache.skywalking.oap.server.core.storage.annotation.SuperDataset;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
import static org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord.SERVICE_ID;
import static org.apache.skywalking.oap.server.core.analysis.record.Record.TIME_BUCKET;
@SuperDataset
@Stream(name = SegmentRecord.INDEX_NAME, scopeId = DefaultScopeDefine.SEGMENT, builder = SegmentRecord.Builder.class, processor = RecordStreamProcessor.class)
@SQLDatabase.ExtraColumn4AdditionalEntity(additionalTable = SegmentRecord.ADDITIONAL_TAG_TABLE, parentColumn = TIME_BUCKET)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.TIME_SEC_RANGE_SHARDING_ALGORITHM, dataSourceShardingColumn = SERVICE_ID, tableShardingColumn = TIME_BUCKET)
public class SegmentRecord extends Record {
public static final String INDEX_NAME = "segment";
@ -65,6 +69,7 @@ public class SegmentRecord extends Record {
@Getter
@Column(columnName = SERVICE_ID)
@BanyanDB.ShardingKey(index = 0)
@SQLDatabase.AdditionalEntity(additionalTables = {ADDITIONAL_TAG_TABLE}, reserveOriginalColumns = true)
private String serviceId;
@Setter
@Getter

View File

@ -30,8 +30,10 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.ElasticSearch;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -46,6 +48,7 @@ import static org.apache.skywalking.oap.server.core.Const.DOUBLE_COLONS_SPLIT;
"name",
"layer"
})
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class ServiceTraffic extends Metrics {
public static final String INDEX_NAME = "service_traffic";

View File

@ -193,4 +193,4 @@ public abstract class SumPerMinFunction extends Meter implements AcceptableValue
public int hashCode() {
return Objects.hash(getEntityId(), getTimeBucket());
}
}
}

View File

@ -16,7 +16,7 @@
*
*/
package org.apache.skywalking.oap.server.core.source;
package org.apache.skywalking.oap.server.core.analysis.metrics;
import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.EVENT;
import static org.apache.skywalking.oap.server.library.util.StringUtil.isNotBlank;
@ -25,10 +25,12 @@ import org.apache.skywalking.oap.server.core.analysis.Layer;
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.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -45,6 +47,7 @@ import lombok.Setter;
callSuper = false,
of = "uuid"
)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class Event extends Metrics {
public static final String INDEX_NAME = "events";

View File

@ -25,9 +25,6 @@ import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Metrics
import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.SourceFrom;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
/**
*
**/
@MetricsFunction(functionName = "max")
public abstract class MaxLongMetrics extends Metrics implements LongValueHolder {

View File

@ -23,8 +23,13 @@ import lombok.Getter;
import lombok.Setter;
import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
import org.apache.skywalking.oap.server.core.remote.data.StreamData;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.StorageData;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.ENTITY_ID;
import static org.apache.skywalking.oap.server.core.analysis.metrics.Metrics.ID;
/**
* Metrics represents the statistic data, which analysis by OAL script or hard code. It has the lifecycle controlled by
@ -33,10 +38,12 @@ import org.apache.skywalking.oap.server.core.storage.annotation.Column;
@EqualsAndHashCode(of = {
"timeBucket"
})
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.TIME_RELATIVE_ID_SHARDING_ALGORITHM, tableShardingColumn = ID, dataSourceShardingColumn = ENTITY_ID)
public abstract class Metrics extends StreamData implements StorageData {
public static final String TIME_BUCKET = "time_bucket";
public static final String ENTITY_ID = "entity_id";
public static final String ID = "id";
/**
* Time attribute

View File

@ -23,15 +23,21 @@ import org.apache.skywalking.oap.server.core.analysis.Stream;
import org.apache.skywalking.oap.server.core.analysis.record.Record;
import org.apache.skywalking.oap.server.core.analysis.worker.RecordStreamProcessor;
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.BanyanDB;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.annotation.SuperDataset;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
import static org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord.SERVICE_ID;
import static org.apache.skywalking.oap.server.core.analysis.record.Record.TIME_BUCKET;
@SuperDataset
@Stream(name = BrowserErrorLogRecord.INDEX_NAME, scopeId = DefaultScopeDefine.BROWSER_ERROR_LOG, builder = BrowserErrorLogRecord.Builder.class, processor = RecordStreamProcessor.class)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.TIME_SEC_RANGE_SHARDING_ALGORITHM, dataSourceShardingColumn = SERVICE_ID, tableShardingColumn = TIME_BUCKET)
public class BrowserErrorLogRecord extends Record {
public static final String INDEX_NAME = "browser_error_log";
public static final String UNIQUE_ID = "unique_id";

View File

@ -29,6 +29,8 @@ public class ConfigService implements Service {
private final String searchableTracesTags;
private final String searchableLogsTags;
private final String searchableAlarmTags;
private final int metricsDataTTL;
private final int recordDataTTL;
public ConfigService(CoreModuleConfig moduleConfig) {
this.gRPCHost = moduleConfig.getGRPCHost();
@ -36,5 +38,7 @@ public class ConfigService implements Service {
this.searchableTracesTags = moduleConfig.getSearchableTracesTags();
this.searchableLogsTags = moduleConfig.getSearchableLogsTags();
this.searchableAlarmTags = moduleConfig.getSearchableAlarmTags();
this.metricsDataTTL = moduleConfig.getMetricsDataTTL();
this.recordDataTTL = moduleConfig.getRecordDataTTL();
}
}

View File

@ -26,7 +26,9 @@ import org.apache.skywalking.oap.server.core.analysis.Stream;
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.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -48,6 +50,7 @@ import static org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.EB
"processId",
"startTime",
})
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class EBPFProfilingScheduleRecord extends Metrics {
public static final String INDEX_NAME = "ebpf_profiling_schedule";

View File

@ -0,0 +1,189 @@
/*
* 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;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
/**
* The following algorithms represent different Table Sharding strategies.
* Cooperate with tableShardingColumn and dataSourceShardingColumn which are defined in {@link SQLDatabase.Sharding}
*
* The DataSource sharding strategy are same:
* If we have {dataSourceList = ds_0...ds_n} and {dataSourceShardingColumn.hashcode() % dataSourceList.size() = 2}
* then the route target is ds_2
*
* The sharding number of the tables is according to TTL, One table per day:
* {tableName = table_timeSeries}, {timeSeries = currentDate - TTL +1 ... currentDate + 1}
* For example: if TTL=3, currentDate = 20220907, the sharding tables are:
* Table_20220905
* Table_20220906
* Table_20220907
* Table_20220908
*/
public enum ShardingAlgorithm {
/**
* Wouldn't sharding Table nor DataSource, keep single Table.
*/
NO_SHARDING,
/**
* Use the time_bucket inside the ID column to sharding by day.
* The precision of time_bucket could be second, minute, hour and day in the same table.
*
* For example, the single table `service_metrics`:
*
* id value
*
* 20220905_Service_A 300
*
* 2022090512_Service_A 200
*
* 202209051211_Service_A 100
*
* 20220906_Service_A 500
*
* 2022090612_Service_A 300
*
* 202209061211_Service_A 100
*
*
* The sharding tables will be:
* `service_metrics_20220905`
*
* id value
*
* 20220905_Service_A 300
*
* 2022090512_Service_A 200
*
* 202209051211_Service_A 100
*
* and `service_metrics_20220906`
*
* id value
*
* 20220906_Service_A 500
*
* 2022090612_Service_A 300
*
* 202209061211_Service_A 100
*
*
*/
TIME_RELATIVE_ID_SHARDING_ALGORITHM,
/**
* Use the time_bucket column to sharding by day.
* The precision of time_bucket should be `second`.
*
* For example, the single table `service_records`:
*
* Service time_bucket value
*
* Service_A 20220905121130 300
*
* Service_A 20220906181233 200
*
* The sharding tables will be:
* `service_records_20220905`
*
* Service time_bucket value
*
* Service_A 20220905121130 300
*
* and `service_records_20220906`
*
* Service time_bucket value
*
* Service_A 20220906181233 200
*
*/
TIME_SEC_RANGE_SHARDING_ALGORITHM,
/**
* Use the time_bucket column to sharding by day.
* The precision of time_bucket should be `minute`.
*
* For example, the single table `endpoint_traffic`:
*
* Endpoint time_bucket
*
* Endpoint_A 202209051211
*
* Endpoint_B 202209061812
*
* The sharding tables will be:
* `endpoint_traffic_20220905`
*
* Endpoint time_bucket
*
* Endpoint_A 202209051211
*
* and `endpoint_traffic_20220906`
*
* Endpoint time_bucket
*
* Endpoint_B 202209061812
*
*/
TIME_MIN_RANGE_SHARDING_ALGORITHM,
/**
* Use the time_bucket column to sharding by day.
* The precision of time_bucket could be `second, minute, hour and day` in the same table.
* For example, the single table `service_relation`:
*
* relation time_bucket
*
* Service_A_B 20220905
*
* Service_A_B 2022090512
*
* Service_A_B 202209051211
*
* Service_A_B 20220906
*
* Service_A_B 2022090612
*
* Service_A_B 202209061211
*
* The sharding tables will be:
* `service_relation_20220905`
*
* relation time_bucket
*
* Service_A_B 20220905
*
* Service_A_B 2022090512
*
* Service_A_B 202209051211
*
* and `endpoint_traffic_20220906`
*
* relation time_bucket
*
* Service_A_B 20220906
*
* Service_A_B 2022090612
*
* Service_A_B 202209061211
*
*/
TIME_BUCKET_SHARDING_ALGORITHM
}

View File

@ -23,6 +23,7 @@ import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
/**
* SQLDatabase annotation is a holder including all annotations for SQL-based RDBMS storage
@ -135,4 +136,16 @@ public @interface SQLDatabase {
@interface MultipleExtraColumn4AdditionalEntity {
ExtraColumn4AdditionalEntity[] value();
}
/**
* Support add sharding policy for a table model. Can be declared on the superclass and overridden by subclass..
* @since 9.3.0
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface Sharding {
ShardingAlgorithm shardingAlgorithm();
String dataSourceShardingColumn() default "";
String tableShardingColumn() default "";
}
}

View File

@ -22,10 +22,13 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
/**
* @since 9.1.0
@ -37,6 +40,9 @@ public class SQLDatabaseModelExtension {
//exclude the columns from the main table
private final List<ModelColumn> excludeColumns = new ArrayList<>(5);
@Setter
private Optional<Sharding> sharding = Optional.empty();
public void appendAdditionalTable(String tableName, ModelColumn column) {
additionalTables.computeIfAbsent(tableName, AdditionalTable::new)
.appendColumn(column);
@ -46,6 +52,10 @@ public class SQLDatabaseModelExtension {
excludeColumns.add(column);
}
public boolean isShardingTable() {
return this.sharding.isPresent() && !this.sharding.get().getShardingAlgorithm().equals(ShardingAlgorithm.NO_SHARDING);
}
@Getter
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public static class AdditionalTable {
@ -63,4 +73,12 @@ public class SQLDatabaseModelExtension {
columns.add(column);
}
}
@Getter
@RequiredArgsConstructor
public static class Sharding {
private final ShardingAlgorithm shardingAlgorithm;
private final String dataSourceShardingColumn;
private final String tableShardingColumn;
}
}

View File

@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.StorageException;
@ -250,6 +251,16 @@ public class StorageModels implements IModelManager, ModelCreator, ModelManipula
}
}
// For the annotation need to be declared on the superclass, the other annotation should be declared on the subclass.
if (!sqlDBModelExtension.getSharding().isPresent() && clazz.isAnnotationPresent(SQLDatabase.Sharding.class)) {
SQLDatabase.Sharding sharding = clazz.getAnnotation(SQLDatabase.Sharding.class);
sqlDBModelExtension.setSharding(
Optional.of(new SQLDatabaseModelExtension.Sharding(sharding.shardingAlgorithm(),
sharding.dataSourceShardingColumn(),
sharding.tableShardingColumn()
)));
}
if (Objects.nonNull(clazz.getSuperclass())) {
retrieval(clazz.getSuperclass(), modelName, modelColumns, scopeId, checker, sqlDBModelExtension, record);
}

View File

@ -28,7 +28,9 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -40,6 +42,7 @@ import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
"serviceName",
"remoteServiceName"
})
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class ZipkinServiceRelationTraffic extends Metrics {
public static final String INDEX_NAME = "zipkin_service_relation_traffic";

View File

@ -28,7 +28,9 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -40,6 +42,7 @@ import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
"serviceName",
"spanName"
})
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class ZipkinServiceSpanTraffic extends Metrics {
public static final String INDEX_NAME = "zipkin_service_span_traffic";

View File

@ -28,7 +28,9 @@ 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.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@ -39,6 +41,7 @@ import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
@EqualsAndHashCode(of = {
"serviceName"
})
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.NO_SHARDING)
public class ZipkinServiceTraffic extends Metrics {
public static final String INDEX_NAME = "zipkin_service_traffic";

View File

@ -28,6 +28,7 @@ import org.apache.skywalking.oap.server.core.analysis.Stream;
import org.apache.skywalking.oap.server.core.analysis.record.Record;
import org.apache.skywalking.oap.server.core.analysis.worker.RecordStreamProcessor;
import org.apache.skywalking.oap.server.core.source.DefaultScopeDefine;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.annotation.BanyanDB;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.SQLDatabase;
@ -37,11 +38,14 @@ import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
import org.apache.skywalking.oap.server.library.util.BooleanUtils;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import static org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord.TRACE_ID;
import static org.apache.skywalking.oap.server.core.analysis.record.Record.TIME_BUCKET;
@SuperDataset
@Stream(name = ZipkinSpanRecord.INDEX_NAME, scopeId = DefaultScopeDefine.ZIPKIN_SPAN, builder = ZipkinSpanRecord.Builder.class, processor = RecordStreamProcessor.class)
@SQLDatabase.ExtraColumn4AdditionalEntity(additionalTable = ZipkinSpanRecord.ADDITIONAL_QUERY_TABLE, parentColumn = TIME_BUCKET)
@SQLDatabase.Sharding(shardingAlgorithm = ShardingAlgorithm.TIME_SEC_RANGE_SHARDING_ALGORITHM, dataSourceShardingColumn = TRACE_ID, tableShardingColumn = TIME_BUCKET)
public class ZipkinSpanRecord extends Record {
private static final Gson GSON = new Gson();
public static final String INDEX_NAME = "zipkin_span";
@ -71,6 +75,7 @@ public class ZipkinSpanRecord extends Record {
@Setter
@Getter
@Column(columnName = TRACE_ID)
@SQLDatabase.AdditionalEntity(additionalTables = {ADDITIONAL_QUERY_TABLE}, reserveOriginalColumns = true)
private String traceId;
@Setter
@Getter
@ -210,6 +215,7 @@ public class ZipkinSpanRecord extends Record {
converter.accept(KIND, storageData.getKind());
converter.accept(TIMESTAMP, storageData.getTimestamp());
converter.accept(TIMESTAMP_MILLIS, storageData.getTimestampMillis());
converter.accept(TIME_BUCKET, storageData.getTimeBucket());
converter.accept(DURATION, storageData.getDuration());
converter.accept(LOCAL_ENDPOINT_SERVICE_NAME, storageData.getLocalEndpointServiceName());
converter.accept(LOCAL_ENDPOINT_IPV4, storageData.getLocalEndpointIPV4());

View File

@ -18,6 +18,9 @@
package org.apache.skywalking.oap.server.core.query;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.skywalking.oap.server.core.query.enumeration.Step;
import org.junit.Assert;
import org.junit.Test;
@ -80,4 +83,11 @@ public class DurationTest {
Assert.assertTrue(true);
}
}
@Test
public void testGetDurationPoints() {
List<PointOfTime> pointOfTimes = DurationUtils.INSTANCE.getDurationPoints(Step.DAY, 20220910, 20220912);
Assert.assertTrue(Arrays.asList(20220910L, 20220911L, 20220912L)
.equals(pointOfTimes.stream().map(PointOfTime::getPoint).collect(Collectors.toList())));
}
}

View File

@ -84,7 +84,6 @@ public class MetricQuery implements GraphQLQueryResolver {
public IntValues getLinearIntValues(final MetricCondition metrics,
final Duration duration) throws IOException {
MetricsCondition condition = new MetricsCondition();
condition.setName(metrics.getName());
condition.setEntity(new MockEntity(metrics.getId()));

View File

@ -197,6 +197,11 @@
<artifactId>storage-banyandb-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>storage-shardingsphere-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<!-- storage module -->
<!-- queryBuild module -->

View File

@ -187,6 +187,17 @@ storage:
metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}
maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:2000}
asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:4}
mysql-sharding:
properties:
jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:13307/swtest?rewriteBatchedStatements=true"}
dataSource.user: ${SW_DATA_SOURCE_USER:root}
dataSource.password: ${SW_DATA_SOURCE_PASSWORD:root}
metadataQueryMaxSize: ${SW_STORAGE_MYSQL_QUERY_MAX_SIZE:5000}
maxSizeOfBatchSql: ${SW_STORAGE_MAX_SIZE_OF_BATCH_SQL:2000}
asyncBatchPersistentPoolSize: ${SW_STORAGE_ASYNC_BATCH_PERSISTENT_POOL_SIZE:4}
# The dataSources are configured in ShardingSphere-Proxy config-sharding.yaml.
# The dataSource name should include the prefix "ds_" and separated by "," and start from ds_0
dataSources: ${SW_JDBC_SHARDING_DATA_SOURCES:ds_0,ds_1}
tidb:
properties:
jdbcUrl: ${SW_JDBC_URL:"jdbc:mysql://localhost:4000/tidbswtest?rewriteBatchedStatements=true"}

View File

@ -32,5 +32,6 @@
<module>storage-elasticsearch-plugin</module>
<module>storage-tidb-plugin</module>
<module>storage-banyandb-plugin</module>
<module>storage-shardingsphere-plugin</module>
</modules>
</project>

View File

@ -36,7 +36,7 @@ import org.apache.skywalking.oap.server.core.query.type.event.EventQueryConditio
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.source.Event;
import org.apache.skywalking.oap.server.core.analysis.metrics.Event;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.BanyanDBStorageClient;
import org.apache.skywalking.oap.server.storage.plugin.banyandb.stream.AbstractBanyanDBDAO;

View File

@ -37,7 +37,7 @@ import org.apache.skywalking.oap.server.core.query.type.event.EventQueryConditio
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.source.Event;
import org.apache.skywalking.oap.server.core.analysis.metrics.Event;
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;

View File

@ -83,13 +83,15 @@ public class H2AggregationQueryDAO implements IAggregationQueryDAO {
protected StringBuilder buildMetricsValueSql(String valueColumnName, String metricsName) {
StringBuilder sql = new StringBuilder();
sql.append("select * from (select avg(")
.append(valueColumnName)
.append(") result,")
.append(Metrics.ENTITY_ID)
.append(" from ")
.append(metricsName)
.append(" where ");
sql.append("select result,")
.append(Metrics.ENTITY_ID)
.append(" from (select avg(")
.append(valueColumnName)
.append(") result,")
.append(Metrics.ENTITY_ID)
.append(" from ")
.append(metricsName)
.append(" where ");
return sql;
}
}

View File

@ -36,7 +36,7 @@ import org.apache.skywalking.oap.server.core.query.type.event.EventQueryConditio
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.source.Event;
import org.apache.skywalking.oap.server.core.analysis.metrics.Event;
import org.apache.skywalking.oap.server.core.storage.query.IEventQueryDAO;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;

View File

@ -118,7 +118,7 @@ public class H2LogQueryDAO implements ILogQueryDAO {
}
if (StringUtil.isNotEmpty(serviceId)) {
sql.append(" and ").append(SERVICE_ID).append(" = ?");
sql.append(" and ").append(LogRecord.INDEX_NAME).append(".").append(SERVICE_ID).append(" = ?");
parameters.add(serviceId);
}
if (StringUtil.isNotEmpty(serviceInstanceId)) {

View File

@ -52,6 +52,12 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
public long readMetricsValue(final MetricsCondition condition,
String valueColumnName,
final Duration duration) throws IOException {
final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
List<String> ids = new ArrayList<>(pointOfTimes.size());
final String entityId = condition.getEntity().buildId();
pointOfTimes.forEach(pointOfTime -> {
ids.add(pointOfTime.id(entityId));
});
int defaultValue = ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName());
final Function function = ValueColumnMetadata.INSTANCE.getValueFunction(condition.getName());
if (function == Function.Latest) {
@ -66,15 +72,22 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
op = "sum";
}
StringBuilder sql = buildMetricsValueSql(op, valueColumnName, condition.getName());
final String entityId = condition.getEntity().buildId();
List<Object> parameters = new ArrayList();
if (entityId != null) {
sql.append(Metrics.ENTITY_ID + " = ? and ");
parameters.add(entityId);
}
sql.append(Metrics.TIME_BUCKET + ">= ? and " + Metrics.TIME_BUCKET + "<=?" + " group by " + Metrics.ENTITY_ID);
parameters.add(duration.getStartTimeBucket());
parameters.add(duration.getEndTimeBucket());
sql.append("id in (");
for (int i = 0; i < ids.size(); i++) {
if (i == 0) {
sql.append("?");
} else {
sql.append(",?");
}
parameters.add(ids.get(i));
}
sql.append(")");
sql.append(" group by " + Metrics.ENTITY_ID);
try (Connection connection = h2Client.getConnection()) {
try (ResultSet resultSet = h2Client.executeQuery(
@ -103,8 +116,9 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
final Duration duration) throws IOException {
final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
List<String> ids = new ArrayList<>(pointOfTimes.size());
final String entityId = condition.getEntity().buildId();
pointOfTimes.forEach(pointOfTime -> {
ids.add(pointOfTime.id(condition.getEntity().buildId()));
ids.add(pointOfTime.id(entityId));
});
StringBuilder sql = new StringBuilder(
@ -120,6 +134,8 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
}
sql.append(")");
buildShardingCondition(sql, parameters, entityId);
MetricsValues metricsValues = new MetricsValues();
// Label is null, because in readMetricsValues, no label parameter.
final IntValues intValues = metricsValues.getValues();
@ -152,8 +168,9 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
final Duration duration) throws IOException {
final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
List<String> ids = new ArrayList<>(pointOfTimes.size());
final String entityId = condition.getEntity().buildId();
pointOfTimes.forEach(pointOfTime -> {
ids.add(pointOfTime.id(condition.getEntity().buildId()));
ids.add(pointOfTime.id(entityId));
});
StringBuilder sql = new StringBuilder(
@ -170,6 +187,8 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
}
sql.append(")");
buildShardingCondition(sql, parameters, entityId);
Map<String, DataTable> idMap = new HashMap<>();
try (Connection connection = h2Client.getConnection()) {
try (ResultSet resultSet = h2Client.executeQuery(
@ -199,8 +218,9 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
final Duration duration) throws IOException {
final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
List<String> ids = new ArrayList<>(pointOfTimes.size());
final String entityId = condition.getEntity().buildId();
pointOfTimes.forEach(pointOfTime -> {
ids.add(pointOfTime.id(condition.getEntity().buildId()));
ids.add(pointOfTime.id(entityId));
});
StringBuilder sql = new StringBuilder(
@ -216,6 +236,8 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
}
sql.append(")");
buildShardingCondition(sql, parameters, entityId);
final int defaultValue = ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName());
try (Connection connection = h2Client.getConnection()) {
@ -236,4 +258,7 @@ public class H2MetricsQueryDAO extends H2SQLExecutor implements IMetricsQueryDAO
throw new IOException(e);
}
}
protected void buildShardingCondition(StringBuilder sql, List<Object> parameters, String entityId) {
}
}

View File

@ -27,6 +27,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.UnexpectedException;
import org.apache.skywalking.oap.server.core.storage.StorageData;
import org.apache.skywalking.oap.server.core.storage.model.Model;
import org.apache.skywalking.oap.server.core.storage.model.ModelColumn;
@ -225,23 +226,30 @@ public class H2SQLExecutor {
storageBuilder.entity2Storage(metrics, toStorage);
Map<String, Object> objectMap = toStorage.obtain();
SQLBuilder sqlBuilder = new SQLBuilder("UPDATE " + modelName + " SET ");
List<ModelColumn> columns = TableMetaInfo.get(modelName).getColumns();
StringBuilder sqlBuilder = new StringBuilder("UPDATE " + modelName + " SET ");
Model model = TableMetaInfo.get(modelName);
List<ModelColumn> columns = model.getColumns();
List<Object> param = new ArrayList<>();
for (int i = 0; i < columns.size(); i++) {
ModelColumn column = columns.get(i);
sqlBuilder.append(column.getColumnName().getStorageName() + "= ?");
if (i != columns.size() - 1) {
sqlBuilder.append(",");
String columnName = column.getColumnName().getName();
if (model.getSqlDBModelExtension().isShardingTable()) {
SQLDatabaseModelExtension.Sharding sharding = model.getSqlDBModelExtension().getSharding().orElseThrow(
() -> new UnexpectedException("Sharding should not be empty."));
if (columnName.equals(sharding.getDataSourceShardingColumn()) || columnName.equals(sharding.getTableShardingColumn())) {
continue;
}
}
sqlBuilder.append(column.getColumnName().getStorageName()).append("= ?,");
Object value = objectMap.get(column.getColumnName().getName());
Object value = objectMap.get(columnName);
if (value instanceof StorageDataComplexObject) {
param.add(((StorageDataComplexObject) value).toStorageData());
} else {
param.add(value);
}
}
sqlBuilder.replace(sqlBuilder.length() - 1, sqlBuilder.length(), "");
sqlBuilder.append(" WHERE id = ?");
param.add(metrics.id());

View File

@ -27,6 +27,7 @@ import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.analysis.Layer;
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
import org.apache.skywalking.oap.server.core.storage.StorageException;
import org.apache.skywalking.oap.server.core.storage.model.Model;
import org.apache.skywalking.oap.server.core.storage.model.ModelColumn;
@ -46,7 +47,7 @@ import org.apache.skywalking.oap.server.storage.plugin.jdbc.TableMetaInfo;
*/
@Slf4j
public class H2TableInstaller extends ModelInstaller {
public static final String ID_COLUMN = "id";
public static final String ID_COLUMN = Metrics.ID;
public H2TableInstaller(Client client, ModuleManager moduleManager) {
super(client, moduleManager);
@ -128,7 +129,7 @@ public class H2TableInstaller extends ModelInstaller {
}
}
private void createTable(JDBCHikariCPClient client,
protected void createTable(JDBCHikariCPClient client,
Connection connection,
String tableName, List<ModelColumn> columns, boolean additionalTable) throws JDBCClientException {
SQLBuilder tableCreateSQL = new SQLBuilder("CREATE TABLE IF NOT EXISTS " + tableName + " (");

View File

@ -121,7 +121,7 @@ public class H2TraceQueryDAO implements ITraceQueryDAO {
parameters.add(maxDuration);
}
if (StringUtil.isNotEmpty(serviceId)) {
sql.append(" and ").append(SegmentRecord.SERVICE_ID).append(" = ?");
sql.append(" and ").append(SegmentRecord.INDEX_NAME).append(".").append(SegmentRecord.SERVICE_ID).append(" = ?");
parameters.add(serviceId);
}
if (StringUtil.isNotEmpty(serviceInstanceId)) {

View File

@ -144,7 +144,7 @@ public class H2ZipkinQueryDAO implements IZipkinQueryDAO {
StringBuilder sql = new StringBuilder();
List<Object> condition = new ArrayList<>(5);
List<Map.Entry<String, String>> annotations = new ArrayList<>(request.annotationQuery().entrySet());
sql.append("select ").append(ZipkinSpanRecord.TRACE_ID).append(", ")
sql.append("select ").append(ZipkinSpanRecord.INDEX_NAME).append(".").append(ZipkinSpanRecord.TRACE_ID).append(", ")
.append("max(").append(ZipkinSpanRecord.TIMESTAMP_MILLIS).append(")").append(" from ");
sql.append(ZipkinSpanRecord.INDEX_NAME);
/**
@ -168,6 +168,7 @@ public class H2ZipkinQueryDAO implements IZipkinQueryDAO {
sql.append(" and ");
sql.append(ZipkinSpanRecord.TIMESTAMP_MILLIS).append(" <= ?");
condition.add(endTimeMillis);
buildShardingCondition(sql, condition, startTimeMillis, endTimeMillis);
}
if (request.minDuration() != null) {
sql.append(" and ");
@ -319,4 +320,7 @@ public class H2ZipkinQueryDAO implements IZipkinQueryDAO {
}
return span.build();
}
protected void buildShardingCondition(StringBuilder sql, List<Object> parameters, long startTimeMillis, long endTimeMillis) {
}
}

View File

@ -0,0 +1,49 @@
<?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-storage-plugin</artifactId>
<groupId>org.apache.skywalking</groupId>
<version>9.3.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>storage-shardingsphere-plugin</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>server-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>library-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.skywalking</groupId>
<artifactId>storage-jdbc-hikaricp-plugin</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,140 @@
/*
* 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.shardingsphere;
import lombok.Setter;
import org.apache.skywalking.oap.server.core.UnexpectedException;
import org.apache.skywalking.oap.server.core.config.ConfigService;
import org.apache.skywalking.oap.server.core.query.DurationUtils;
import org.apache.skywalking.oap.server.core.query.enumeration.Step;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
public enum DurationWithinTTL {
INSTANCE;
private static final DateTimeFormatter YYYYMMDD = DateTimeFormat.forPattern("yyyyMMdd");
private static final DateTimeFormatter YYYYMMDDHH = DateTimeFormat.forPattern("yyyyMMddHH");
private static final DateTimeFormatter YYYYMMDDHHMM = DateTimeFormat.forPattern("yyyyMMddHHmm");
private static final DateTimeFormatter YYYYMMDDHHMMSS = DateTimeFormat.forPattern("yyyyMMddHHmmss");
@Setter
private ConfigService configService;
/**
* @param duration Origin Duration instance
* @return new Duration instance and the time range within the Metrics TTL, if origin duration is null then return null.
*/
public Duration getMetricDurationWithinTTL(final Duration duration) {
if (duration == null) {
return null;
}
Duration durationWithinTTL = new Duration();
durationWithinTTL.setStart(DurationWithinTTL.INSTANCE.getTrimmedMetricStartTime(duration.getStep(), duration.getStart()));
durationWithinTTL.setEnd(DurationWithinTTL.INSTANCE.getTrimmedMetricEndTime(duration.getStep(), duration.getEnd()));
durationWithinTTL.setStep(duration.getStep());
return durationWithinTTL;
}
/**
* @param duration Origin Duration instance
* @return new Duration instance and the time range within the Record TTL, if origin duration is null then return null.
*/
public Duration getRecordDurationWithinTTL(final Duration duration) {
if (duration == null) {
return null;
}
Duration durationWithinTTL = new Duration();
durationWithinTTL.setStart(DurationWithinTTL.INSTANCE.getTrimmedRecordStartTime(duration.getStep(), duration.getStart()));
durationWithinTTL.setEnd(DurationWithinTTL.INSTANCE.getTrimmedRecordEndTime(duration.getStep(), duration.getEnd()));
durationWithinTTL.setStep(duration.getStep());
return durationWithinTTL;
}
// Trim the startStr according to the record TTL, for query
public String getTrimmedRecordStartTime(Step step, String startStr) {
if (configService == null) {
throw new UnexpectedException("ConfigService can not be null, should set ConfigService first.");
}
return trimStartTime(step, startStr, configService.getRecordDataTTL());
}
// Trim the startStr according to the metric TTL, for query
public String getTrimmedMetricStartTime(Step step, String startStr) {
if (configService == null) {
throw new UnexpectedException("ConfigService can not be null, should set ConfigService first.");
}
return trimStartTime(step, startStr, configService.getMetricsDataTTL());
}
// Trim the endStr according to the record TTL, for query
public String getTrimmedRecordEndTime(Step step, String endStr) {
return trimEndTime(step, endStr);
}
// Trim the endStr according to the metric TTL, for query
public String getTrimmedMetricEndTime(Step step, String endStr) {
return trimEndTime(step, endStr);
}
private String trimStartTime(Step step, String startStr, int ttl) {
long startDate = DurationUtils.INSTANCE.convertToTimeBucket(step, startStr);
long timeFloor = Long.parseLong(DateTime.now().plusDays(1 - ttl).toString("yyyyMMdd"));
switch (step) {
case DAY:
return YYYYMMDD.parseDateTime(String.valueOf(Math.max(timeFloor, startDate))).toString("yyyy-MM-dd");
case HOUR:
timeFloor = timeFloor * 100;
return YYYYMMDDHH.parseDateTime(String.valueOf(Math.max(timeFloor, startDate))).toString("yyyy-MM-dd HH");
case MINUTE:
timeFloor = timeFloor * 100 * 100;
return YYYYMMDDHHMM.parseDateTime(String.valueOf(Math.max(timeFloor, startDate))).toString("yyyy-MM-dd HHmm");
case SECOND:
timeFloor = timeFloor * 100 * 100 * 100;
return YYYYMMDDHHMMSS.parseDateTime(String.valueOf(Math.max(timeFloor, startDate))).toString("yyyy-MM-dd HHmmss");
}
throw new UnexpectedException("Unsupported step " + step.name());
}
// Trim the endStr according to the real date, for query
public String trimEndTime(Step step, String endStr) {
long endDate = DurationUtils.INSTANCE.convertToTimeBucket(step, endStr);
long timeCeiling = Long.parseLong(DateTime.now().toString("yyyyMMdd"));
switch (step) {
case DAY:
return YYYYMMDD.parseDateTime(String.valueOf(Math.min(endDate, timeCeiling))).toString("yyyy-MM-dd");
case HOUR:
timeCeiling = (timeCeiling * 100) + 23;
return YYYYMMDDHH.parseDateTime(String.valueOf(Math.min(endDate, timeCeiling))).toString("yyyy-MM-dd HH");
case MINUTE:
timeCeiling = ((timeCeiling * 100) + 23) * 100 + 59;
return YYYYMMDDHHMM.parseDateTime(String.valueOf(Math.min(endDate, timeCeiling))).toString("yyyy-MM-dd HHmm");
case SECOND:
timeCeiling = (((timeCeiling * 100) + 23) * 100 + 59) * 100 + 59;
return YYYYMMDDHHMMSS.parseDateTime(String.valueOf(Math.min(endDate, timeCeiling))).toString("yyyy-MM-dd HHmmss");
}
throw new UnexpectedException("Unsupported step " + step.name());
}
}

View File

@ -0,0 +1,64 @@
/*
* 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.shardingsphere;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.SQLBuilder;
@Getter
@Setter
@Builder(toBuilder = true)
public class ShardingRule {
private String operation;
private String table;
private String actualDataNodes;
private String actualDataSources;
private String databaseStrategyType;
private String databaseShardingColumn;
private String databaseShardingAlgorithmType;
private String databaseShardingAlgorithmProps;
private String tableStrategyType;
private String tableShardingColumn;
private String tableShardingAlgorithmType;
private String tableShardingAlgorithmProps;
private String keyGenerateColumn;
private String keyGeneratorType;
private String keyGeneratorProps;
public String toShardingRuleSQL() {
SQLBuilder ruleSQL = new SQLBuilder();
ruleSQL.append(operation);
ruleSQL.append(" SHARDING TABLE RULE ");
ruleSQL.append(table).appendLine("(");
ruleSQL.append("DATANODES(").append(actualDataNodes).appendLine("),");
ruleSQL.append("DATABASE_STRATEGY(TYPE=").append(databaseStrategyType).appendLine(",");
ruleSQL.append("SHARDING_COLUMN=").append(databaseShardingColumn).appendLine(",");
ruleSQL.append("SHARDING_ALGORITHM(TYPE(NAME=").append(databaseShardingAlgorithmType).appendLine(",");
ruleSQL.append("PROPERTIES(").append(databaseShardingAlgorithmProps);
ruleSQL.appendLine(")))),");
ruleSQL.append("TABLE_STRATEGY(TYPE=").append(tableStrategyType).appendLine(",");
ruleSQL.append("SHARDING_COLUMN=").append(tableShardingColumn).appendLine(",");
ruleSQL.append("SHARDING_ALGORITHM(TYPE(NAME=").append(tableShardingAlgorithmType).appendLine(",");
ruleSQL.append("PROPERTIES(").append(tableShardingAlgorithmProps);
ruleSQL.append(")))))");
return ruleSQL.toString();
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.shardingsphere.dao;
import java.io.IOException;
import java.util.List;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.input.TopNCondition;
import org.apache.skywalking.oap.server.core.query.type.KeyValue;
import org.apache.skywalking.oap.server.core.query.type.SelectedRecord;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2AggregationQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.DurationWithinTTL;
public class ShardingAggregationQueryDAO extends H2AggregationQueryDAO {
public ShardingAggregationQueryDAO(JDBCHikariCPClient h2Client) {
super(h2Client);
}
@Override
public List<SelectedRecord> sortMetrics(final TopNCondition metrics,
final String valueColumnName,
final Duration duration,
List<KeyValue> additionalConditions) throws IOException {
return super.sortMetrics(
metrics,
valueColumnName,
DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration),
additionalConditions
);
}
}

View File

@ -0,0 +1,52 @@
/*
* 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.shardingsphere.dao;
import java.io.IOException;
import org.apache.skywalking.oap.server.core.browser.source.BrowserErrorCategory;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.type.BrowserErrorLogs;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2BrowserLogQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.DurationWithinTTL;
public class ShardingBrowserLogQueryDAO extends H2BrowserLogQueryDAO {
public ShardingBrowserLogQueryDAO(JDBCHikariCPClient h2Client) {
super(h2Client);
}
@Override
public BrowserErrorLogs queryBrowserErrorLogs(String serviceId,
String serviceVersionId,
String pagePathId,
BrowserErrorCategory category,
Duration duration,
int limit,
int from) throws IOException {
return super.queryBrowserErrorLogs(
serviceId,
serviceVersionId,
pagePathId,
category,
DurationWithinTTL.INSTANCE.getRecordDurationWithinTTL(duration),
limit,
from
);
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.shardingsphere.dao;
import java.io.IOException;
import java.util.List;
import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag;
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.input.TraceScopeCondition;
import org.apache.skywalking.oap.server.core.query.type.Logs;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2LogQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.DurationWithinTTL;
public class ShardingLogQueryDAO extends H2LogQueryDAO {
public ShardingLogQueryDAO(final JDBCHikariCPClient h2Client,
final ModuleManager manager) {
super(h2Client, manager);
}
@Override
public Logs queryLogs(String serviceId,
String serviceInstanceId,
String endpointId,
TraceScopeCondition relatedTrace,
Order queryOrder,
int from,
int limit,
final Duration duration,
final List<Tag> tags,
final List<String> keywordsOfContent,
final List<String> excludingKeywordsOfContent) throws IOException {
return super.queryLogs(
serviceId,
serviceInstanceId,
endpointId,
relatedTrace,
queryOrder,
from,
limit,
DurationWithinTTL.INSTANCE.getRecordDurationWithinTTL(duration),
tags,
keywordsOfContent,
excludingKeywordsOfContent
);
}
}

View File

@ -0,0 +1,102 @@
/*
* 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.shardingsphere.dao;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
import org.apache.skywalking.oap.server.core.query.PointOfTime;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.input.MetricsCondition;
import org.apache.skywalking.oap.server.core.query.type.HeatMap;
import org.apache.skywalking.oap.server.core.query.type.MetricsValues;
import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2MetricsQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.DurationWithinTTL;
public class ShardingMetricsQueryDAO extends H2MetricsQueryDAO {
public ShardingMetricsQueryDAO(JDBCHikariCPClient h2Client) {
super(h2Client);
}
@Override
public long readMetricsValue(final MetricsCondition condition,
String valueColumnName,
final Duration duration) throws IOException {
return super.readMetricsValue(condition, valueColumnName, DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration));
}
@Override
public MetricsValues readMetricsValues(final MetricsCondition condition,
final String valueColumnName,
final Duration duration) throws IOException {
MetricsValues result = super.readMetricsValues(condition, valueColumnName,
DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration));
MetricsValues values = new MetricsValues();
values.setValues(Util.sortValues(result.getValues(), getOriginIds(condition, duration),
ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName())));
return values;
}
@Override
public List<MetricsValues> readLabeledMetricsValues(final MetricsCondition condition,
final String valueColumnName,
final List<String> labels,
final Duration duration) throws IOException {
List<MetricsValues> result = super.readLabeledMetricsValues(condition, valueColumnName, labels,
DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration));
return Util.sortValues(result, getOriginIds(condition, duration),
ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName()));
}
@Override
public HeatMap readHeatMap(final MetricsCondition condition,
final String valueColumnName,
final Duration duration) throws IOException {
HeatMap result = super.readHeatMap(condition, valueColumnName,
DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration));
result.fixMissingColumns(getOriginIds(condition, duration),
ValueColumnMetadata.INSTANCE.getDefaultValue(condition.getName()));
return result;
}
@Override
protected void buildShardingCondition(StringBuilder sql, List<Object> parameters, String entityId) {
sql.append(" and ");
sql.append(Metrics.ENTITY_ID + " = ?");
parameters.add(entityId);
}
private List<String> getOriginIds(final MetricsCondition condition, final Duration duration) {
final List<PointOfTime> pointOfTimes = duration.assembleDurationPoints();
List<String> ids = new ArrayList<>(pointOfTimes.size());
final String entityId = condition.getEntity().buildId();
pointOfTimes.forEach(pointOfTime -> {
ids.add(pointOfTime.id(entityId));
});
return ids;
}
}

View File

@ -0,0 +1,91 @@
/*
* 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.shardingsphere.dao;
import java.io.IOException;
import java.util.List;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.type.Call;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TopologyQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.DurationWithinTTL;
public class ShardingTopologyQueryDAO extends H2TopologyQueryDAO {
public ShardingTopologyQueryDAO(JDBCHikariCPClient h2Client) {
super(h2Client);
}
@Override
public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(Duration duration,
List<String> serviceIds) throws IOException {
return super.loadServiceRelationsDetectedAtServerSide(DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration));
}
@Override
public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(Duration duration,
List<String> serviceIds) throws IOException {
return super.loadServiceRelationDetectedAtClientSide(DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration), serviceIds);
}
@Override
public List<Call.CallDetail> loadServiceRelationsDetectedAtServerSide(Duration duration) throws IOException {
return super.loadServiceRelationsDetectedAtServerSide(DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration));
}
@Override
public List<Call.CallDetail> loadServiceRelationDetectedAtClientSide(Duration duration) throws IOException {
return super.loadServiceRelationDetectedAtClientSide(DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration));
}
@Override
public List<Call.CallDetail> loadInstanceRelationDetectedAtServerSide(String clientServiceId,
String serverServiceId,
Duration duration) throws IOException {
return super.loadInstanceRelationDetectedAtServerSide(clientServiceId, serverServiceId,
DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration));
}
@Override
public List<Call.CallDetail> loadInstanceRelationDetectedAtClientSide(String clientServiceId,
String serverServiceId,
Duration duration) throws IOException {
return super.loadInstanceRelationDetectedAtClientSide(clientServiceId, serverServiceId,
DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration));
}
@Override
public List<Call.CallDetail> loadEndpointRelation(Duration duration,
String destEndpointId) throws IOException {
return super.loadEndpointRelation(DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration),
destEndpointId);
}
@Override
public List<Call.CallDetail> loadProcessRelationDetectedAtClientSide(String serviceInstanceId, Duration duration) throws IOException {
return super.loadProcessRelationDetectedAtClientSide(serviceInstanceId,
DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration));
}
@Override
public List<Call.CallDetail> loadProcessRelationDetectedAtServerSide(String serviceInstanceId, Duration duration) throws IOException {
return super.loadProcessRelationDetectedAtServerSide(serviceInstanceId,
DurationWithinTTL.INSTANCE.getMetricDurationWithinTTL(duration));
}
}

View File

@ -0,0 +1,68 @@
/*
* 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.shardingsphere.dao;
import java.io.IOException;
import java.util.List;
import org.apache.skywalking.oap.server.core.analysis.manual.searchtag.Tag;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.query.type.QueryOrder;
import org.apache.skywalking.oap.server.core.query.type.TraceBrief;
import org.apache.skywalking.oap.server.core.query.type.TraceState;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TraceQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.DurationWithinTTL;
public class ShardingTraceQueryDAO extends H2TraceQueryDAO {
public ShardingTraceQueryDAO(ModuleManager manager,
JDBCHikariCPClient h2Client) {
super(manager, h2Client);
}
@Override
public TraceBrief queryBasicTraces(Duration duration,
long minDuration,
long maxDuration,
String serviceId,
String serviceInstanceId,
String endpointId,
String traceId,
int limit,
int from,
TraceState traceState,
QueryOrder queryOrder,
final List<Tag> tags) throws IOException {
return super.queryBasicTraces(
DurationWithinTTL.INSTANCE.getRecordDurationWithinTTL(duration),
minDuration,
maxDuration,
serviceId,
serviceInstanceId,
endpointId,
traceId,
limit,
from,
traceState,
queryOrder,
tags
);
}
}

View File

@ -0,0 +1,53 @@
/*
* 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.shardingsphere.dao;
import java.io.IOException;
import java.util.List;
import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
import org.apache.skywalking.oap.server.core.query.input.Duration;
import org.apache.skywalking.oap.server.core.zipkin.ZipkinSpanRecord;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ZipkinQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.DurationWithinTTL;
import zipkin2.Span;
import zipkin2.storage.QueryRequest;
public class ShardingZipkinQueryDAO extends H2ZipkinQueryDAO {
public ShardingZipkinQueryDAO(final JDBCHikariCPClient h2Client) {
super(h2Client);
}
@Override
public List<List<Span>> getTraces(final QueryRequest request, Duration duration) throws IOException {
return super.getTraces(request,
DurationWithinTTL.INSTANCE.getRecordDurationWithinTTL(duration));
}
@Override
protected void buildShardingCondition(StringBuilder sql, List<Object> parameters, long startTimeMillis, long endTimeMillis) {
sql.append(" and ");
sql.append(ZipkinSpanRecord.INDEX_NAME).append(".").append(ZipkinSpanRecord.TIME_BUCKET + " >= ?");
parameters.add(TimeBucket.getRecordTimeBucket(startTimeMillis));
sql.append(" and ");
sql.append(ZipkinSpanRecord.INDEX_NAME).append(".").append(ZipkinSpanRecord.TIME_BUCKET + " <= ?");
parameters.add(TimeBucket.getRecordTimeBucket(endTimeMillis));
}
}

View File

@ -0,0 +1,147 @@
/*
* 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.shardingsphere.mysql;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.analysis.DownSampling;
import org.apache.skywalking.oap.server.core.storage.StorageException;
import org.apache.skywalking.oap.server.core.storage.model.Model;
import org.apache.skywalking.oap.server.library.client.jdbc.JDBCClientException;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2HistoryDeleteDAO;
import org.joda.time.DateTime;
@Slf4j
public class MySQLShardingHistoryDeleteDAO extends H2HistoryDeleteDAO {
private final JDBCHikariCPClient client;
private final MySQLShardingStorageConfig config;
private final ModuleManager manager;
private final Set<String> dataSources;
private final Map<String, Long> tableLatestSuccess;
public MySQLShardingHistoryDeleteDAO(JDBCHikariCPClient client, MySQLShardingStorageConfig config,
ModuleManager manager) {
super(client);
this.client = client;
this.config = config;
this.manager = manager;
this.dataSources = config.getDataSources();
this.tableLatestSuccess = new HashMap<>();
}
@Override
public void deleteHistory(Model model, String timeBucketColumnName, int ttl) throws IOException {
if (!model.isRecord()) {
if (!DownSampling.Minute.equals(model.getDownsampling())) {
return;
}
}
long deadline = Long.parseLong(DateTime.now().plusDays(-ttl).toString("yyyyMMdd"));
//If it's a sharding table drop expired tables
if (model.getSqlDBModelExtension().isShardingTable()) {
boolean isRuleExecuted = false;
Long latestSuccessDeadline = this.tableLatestSuccess.get(model.getName());
if (latestSuccessDeadline != null && deadline <= latestSuccessDeadline) {
if (log.isDebugEnabled()) {
log.debug("Table = {} already deleted, skip, deadline = {}, ttl = {}", model.getName(), deadline, ttl);
}
return;
}
try {
//refresh sharding rules
isRuleExecuted = ShardingRulesOperator.INSTANCE.createOrUpdateShardingRule(client, model, this.dataSources, ttl);
if (isRuleExecuted) {
MySQLShardingTableInstaller installer = new MySQLShardingTableInstaller(client, manager, config);
installer.createTable(model);
}
} catch (StorageException e) {
throw new IOException(e.getMessage(), e);
}
List<String> realTables = new ArrayList<>();
try (Connection connection = client.getConnection()) {
ResultSet resultSet = connection.getMetaData()
.getTables(connection.getCatalog(), null, model.getName() + "_20%", null);
while (resultSet.next()) {
realTables.add(resultSet.getString("TABLE_NAME"));
}
//delete additional tables
for (String additionalTable : model.getSqlDBModelExtension().getAdditionalTables().keySet()) {
ResultSet additionalTableRS = connection.getMetaData()
.getTables(connection.getCatalog(), null,
additionalTable + "_20%", null);
while (additionalTableRS.next()) {
realTables.add(additionalTableRS.getString("TABLE_NAME"));
}
}
} catch (JDBCClientException | SQLException e) {
throw new IOException(e.getMessage(), e);
}
List<String> prepareDeleteTables = new ArrayList<>();
for (String table : realTables) {
long timeSeries = isolateTimeFromTableName(table);
if (deadline >= timeSeries) {
prepareDeleteTables.add(table);
}
}
if (log.isDebugEnabled()) {
log.debug("Tables to be dropped: {}", prepareDeleteTables);
}
try (Connection connection = client.getConnection()) {
Set<String> dsList = config.getDataSources();
for (String prepareDeleteTable : prepareDeleteTables) {
for (String ds : dsList) {
client.execute(connection, getDropSQL(ds, prepareDeleteTable));
}
}
} catch (JDBCClientException | SQLException e) {
throw new IOException(e.getMessage(), e);
}
this.tableLatestSuccess.put(model.getName(), deadline);
} else {
//Delete rows as previous
super.deleteHistory(model, timeBucketColumnName, ttl);
}
}
private long isolateTimeFromTableName(String tableName) {
return Long.parseLong(tableName.substring(tableName.lastIndexOf("_") + 1));
}
private String getDropSQL(String dataSource, String table) {
String dropSQL = "/* ShardingSphere hint: dataSourceName=" + dataSource + "*/\n" +
"drop table if exists " + table;
return dropSQL;
}
}

View File

@ -0,0 +1,39 @@
/*
* 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.shardingsphere.mysql;
import com.google.common.base.Splitter;
import java.util.HashSet;
import java.util.Set;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.apache.skywalking.oap.server.core.Const;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.mysql.MySQLStorageConfig;
@Setter
public class MySQLShardingStorageConfig extends MySQLStorageConfig {
private String dataSources = Const.EMPTY_STRING;
public Set<String> getDataSources() {
if (StringUtils.isEmpty(this.dataSources)) {
return null;
}
return new HashSet<>(Splitter.on(",").splitToList(this.dataSources));
}
}

View File

@ -0,0 +1,185 @@
/*
* 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.shardingsphere.mysql;
import java.io.IOException;
import java.sql.SQLException;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.config.ConfigService;
import org.apache.skywalking.oap.server.core.storage.IBatchDAO;
import org.apache.skywalking.oap.server.core.storage.IHistoryDeleteDAO;
import org.apache.skywalking.oap.server.core.storage.StorageBuilderFactory;
import org.apache.skywalking.oap.server.core.storage.StorageDAO;
import org.apache.skywalking.oap.server.core.storage.StorageException;
import org.apache.skywalking.oap.server.core.storage.StorageModule;
import org.apache.skywalking.oap.server.core.storage.cache.INetworkAddressAliasDAO;
import org.apache.skywalking.oap.server.core.storage.management.UITemplateManagementDAO;
import org.apache.skywalking.oap.server.core.storage.model.ModelCreator;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingDataDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingScheduleDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IEBPFProfilingTaskDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.ebpf.IServiceLabelDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.trace.IProfileTaskLogQueryDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.trace.IProfileTaskQueryDAO;
import org.apache.skywalking.oap.server.core.storage.profiling.trace.IProfileThreadSnapshotQueryDAO;
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;
import org.apache.skywalking.oap.server.core.storage.query.ITagAutoCompleteQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ITopNRecordsQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ITopologyQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.ITraceQueryDAO;
import org.apache.skywalking.oap.server.core.storage.query.IZipkinQueryDAO;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
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.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.H2EBPFProfilingDataDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2EBPFProfilingScheduleDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2EBPFProfilingTaskDAO;
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.H2NetworkAddressAliasDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ServiceLabelQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileTaskLogQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileTaskQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2ProfileThreadSnapshotQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2StorageDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TagAutoCompleteQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2TopNRecordsQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.h2.dao.H2UITemplateManagementDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.mysql.MySQLAlarmQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.DurationWithinTTL;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.dao.ShardingAggregationQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.dao.ShardingMetricsQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.dao.ShardingTopologyQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.dao.ShardingZipkinQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.mysql.dao.MySQLShardingLogQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.mysql.dao.MySQLShardingTraceQueryDAO;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.mysql.dao.MysqlShardingBrowserLogQueryDAO;
@Slf4j
public class MySQLShardingStorageProvider extends ModuleProvider {
private MySQLShardingStorageConfig config;
private JDBCHikariCPClient mysqlClient;
public MySQLShardingStorageProvider() {
config = new MySQLShardingStorageConfig();
}
@Override
public String name() {
return "mysql-sharding";
}
@Override
public Class<? extends ModuleDefine> module() {
return StorageModule.class;
}
@Override
public ModuleConfig createConfigBeanIfAbsent() {
return config;
}
@Override
public void prepare() throws ServiceNotProvidedException {
this.registerServiceImplementation(StorageBuilderFactory.class, new StorageBuilderFactory.Default());
mysqlClient = new JDBCHikariCPClient(config.getProperties());
this.registerServiceImplementation(IBatchDAO.class, new H2BatchDAO(mysqlClient, config.getMaxSizeOfBatchSql(), config.getAsyncBatchPersistentPoolSize()));
this.registerServiceImplementation(
StorageDAO.class,
new H2StorageDAO(mysqlClient));
this.registerServiceImplementation(
INetworkAddressAliasDAO.class, new H2NetworkAddressAliasDAO(mysqlClient));
this.registerServiceImplementation(ITopologyQueryDAO.class, new ShardingTopologyQueryDAO(mysqlClient));
this.registerServiceImplementation(IMetricsQueryDAO.class, new ShardingMetricsQueryDAO(mysqlClient));
this.registerServiceImplementation(
ITraceQueryDAO.class,
new MySQLShardingTraceQueryDAO(getManager(), mysqlClient)
);
this.registerServiceImplementation(IBrowserLogQueryDAO.class, new MysqlShardingBrowserLogQueryDAO(mysqlClient));
this.registerServiceImplementation(
IMetadataQueryDAO.class, new H2MetadataQueryDAO(mysqlClient, config.getMetadataQueryMaxSize()));
this.registerServiceImplementation(IAggregationQueryDAO.class, new ShardingAggregationQueryDAO(mysqlClient));
this.registerServiceImplementation(IAlarmQueryDAO.class, new MySQLAlarmQueryDAO(mysqlClient, getManager()));
this.registerServiceImplementation(
IHistoryDeleteDAO.class, new H2HistoryDeleteDAO(mysqlClient));
this.registerServiceImplementation(ITopNRecordsQueryDAO.class, new H2TopNRecordsQueryDAO(mysqlClient));
this.registerServiceImplementation(
ILogQueryDAO.class,
new MySQLShardingLogQueryDAO(mysqlClient, getManager()));
this.registerServiceImplementation(IProfileTaskQueryDAO.class, new H2ProfileTaskQueryDAO(mysqlClient));
this.registerServiceImplementation(IProfileTaskLogQueryDAO.class, new H2ProfileTaskLogQueryDAO(mysqlClient));
this.registerServiceImplementation(
IProfileThreadSnapshotQueryDAO.class, new H2ProfileThreadSnapshotQueryDAO(mysqlClient));
this.registerServiceImplementation(UITemplateManagementDAO.class, new H2UITemplateManagementDAO(mysqlClient));
this.registerServiceImplementation(
IHistoryDeleteDAO.class, new MySQLShardingHistoryDeleteDAO(mysqlClient, config, getManager()));
this.registerServiceImplementation(IEventQueryDAO.class, new H2EventQueryDAO(mysqlClient));
this.registerServiceImplementation(IEBPFProfilingTaskDAO.class, new H2EBPFProfilingTaskDAO(mysqlClient));
this.registerServiceImplementation(IEBPFProfilingScheduleDAO.class, new H2EBPFProfilingScheduleDAO(mysqlClient));
this.registerServiceImplementation(IEBPFProfilingDataDAO.class, new H2EBPFProfilingDataDAO(mysqlClient));
this.registerServiceImplementation(IServiceLabelDAO.class, new H2ServiceLabelQueryDAO(mysqlClient));
this.registerServiceImplementation(ITagAutoCompleteQueryDAO.class, new H2TagAutoCompleteQueryDAO(mysqlClient));
this.registerServiceImplementation(IZipkinQueryDAO.class, new ShardingZipkinQueryDAO(mysqlClient));
}
@Override
public void start() throws ServiceNotProvidedException, ModuleStartException {
try {
mysqlClient.connect();
MySQLShardingTableInstaller installer = new MySQLShardingTableInstaller(mysqlClient, getManager(), config);
ShardingRulesOperator.INSTANCE.start(mysqlClient);
getManager().find(CoreModule.NAME).provider().getService(ModelCreator.class).addModelListener(installer);
DurationWithinTTL.INSTANCE.setConfigService(getManager().find(CoreModule.NAME)
.provider()
.getService(ConfigService.class));
} catch (StorageException | SQLException | IOException e) {
throw new ModuleStartException(e.getMessage(), e);
}
}
@Override
public void notifyAfterCompleted() throws ServiceNotProvidedException, ModuleStartException {
}
@Override
public String[] requiredModules() {
return new String[] {CoreModule.NAME};
}
}

View File

@ -0,0 +1,157 @@
/*
* 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.shardingsphere.mysql;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.oap.server.core.CoreModule;
import org.apache.skywalking.oap.server.core.UnexpectedException;
import org.apache.skywalking.oap.server.core.config.ConfigService;
import org.apache.skywalking.oap.server.core.storage.StorageException;
import org.apache.skywalking.oap.server.core.storage.model.Model;
import org.apache.skywalking.oap.server.core.storage.model.ModelColumn;
import org.apache.skywalking.oap.server.core.storage.model.SQLDatabaseExtension;
import org.apache.skywalking.oap.server.library.client.Client;
import org.apache.skywalking.oap.server.library.client.jdbc.JDBCClientException;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.SQLBuilder;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.TableMetaInfo;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.mysql.MySQLTableInstaller;
@Slf4j
public class MySQLShardingTableInstaller extends MySQLTableInstaller {
private final ConfigService configService;
private final Set<String> dataSources;
public MySQLShardingTableInstaller(Client client,
ModuleManager moduleManager,
MySQLShardingStorageConfig config) {
super(client, moduleManager);
this.configService = moduleManager.find(CoreModule.NAME).provider().getService(ConfigService.class);
this.dataSources = config.getDataSources();
}
@Override
protected boolean isExists(Model model) throws StorageException {
boolean isRuleExecuted = false;
boolean isTableExist = false;
if (configService == null) {
throw new UnexpectedException("ConfigService can not be null, should set ConfigService first.");
}
int ttl = model.isRecord() ? configService.getRecordDataTTL() : configService.getMetricsDataTTL();
TableMetaInfo.addModel(model);
JDBCHikariCPClient h2Client = (JDBCHikariCPClient) client;
try (Connection conn = h2Client.getConnection()) {
try (ResultSet rset = conn.getMetaData().getTables(conn.getCatalog(), null, model.getName(), null)) {
if (rset.next()) {
isTableExist = true;
}
}
} catch (SQLException | JDBCClientException e) {
throw new StorageException(e.getMessage(), e);
}
if (model.getSqlDBModelExtension().isShardingTable()) {
isRuleExecuted = ShardingRulesOperator.INSTANCE.createOrUpdateShardingRule(h2Client, model, this.dataSources, ttl);
}
return isTableExist && !isRuleExecuted;
}
@Override
protected void createTable(Model model) throws StorageException {
//todo: init
super.createTable(model);
}
@Override
protected void createTable(JDBCHikariCPClient client,
Connection connection,
String tableName,
List<ModelColumn> columns,
boolean additionalTable) throws JDBCClientException {
SQLBuilder tableCreateSQL = new SQLBuilder("CREATE TABLE IF NOT EXISTS " + tableName + " (");
tableCreateSQL.append(ID_COLUMN).append(" VARCHAR(512) ");
if (!additionalTable) {
tableCreateSQL.appendLine("PRIMARY KEY, ");
} else {
tableCreateSQL.appendLine(", ");
}
for (int i = 0; i < columns.size(); i++) {
ModelColumn column = columns.get(i);
tableCreateSQL.appendLine(
getColumn(column) + (i != columns.size() ? "," : ""));
}
int indexSeq = 0;
//Add indexes
List<String> columnList = columns.stream().map(column -> column.getColumnName().getStorageName()).collect(
Collectors.toList());
for (int i = 0; i < columns.size(); i++) {
ModelColumn column = columns.get(i);
for (final SQLDatabaseExtension.MultiColumnsIndex index : column.getSqlDatabaseExtension()
.getIndices()) {
final String[] multiColumns = index.getColumns();
//Create MultiColumnsIndex on the additional table only when it contains all need columns.
if (additionalTable && !columnList.containsAll(Arrays.asList(multiColumns))) {
continue;
}
tableCreateSQL.append("KEY K")
.append(String.valueOf(indexSeq++));
tableCreateSQL.append(" (");
for (int j = 0; j < multiColumns.length; j++) {
tableCreateSQL.append(multiColumns[j]);
if (j < multiColumns.length - 1) {
tableCreateSQL.append(",");
}
}
tableCreateSQL.appendLine("),");
}
if (column.shouldIndex() && column.getLength() < 513) {
tableCreateSQL.append("KEY K")
.append(String.valueOf(indexSeq++));
tableCreateSQL.append(" (").append(column.getColumnName().getStorageName()).append(")");
tableCreateSQL.appendLine(i != columns.size() - 1 ? "," : "");
}
}
tableCreateSQL.appendLine(")");
if (log.isDebugEnabled()) {
log.debug("creating table: " + tableCreateSQL.toStringInNewLine());
}
client.execute(connection, tableCreateSQL.toString());
}
@Override
protected void createTableIndexes(JDBCHikariCPClient client,
Connection connection,
String tableName,
List<ModelColumn> columns,
boolean additionalTable) throws JDBCClientException {
// Do nothing, indexes have been created inside create tables.
}
}

View File

@ -0,0 +1,284 @@
/*
* 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.shardingsphere.mysql;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.skywalking.oap.server.core.UnexpectedException;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.core.storage.StorageException;
import org.apache.skywalking.oap.server.core.storage.model.Model;
import org.apache.skywalking.oap.server.core.storage.model.SQLDatabaseModelExtension;
import org.apache.skywalking.oap.server.library.client.jdbc.JDBCClientException;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.SQLBuilder;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.ShardingRule;
import org.joda.time.DateTime;
import org.joda.time.Days;
public enum ShardingRulesOperator {
INSTANCE;
private final Map<String, ShardingRule> modelShardingRules = new HashMap<>();
private static final String TIME_RELATIVE_ID_SHARDING_EXPRESSION =
"${long time_bucket = Long.parseLong(id.substring(0,id.indexOf('_')));" +
"if (10000000L < time_bucket && time_bucket < 99999999L) {return time_bucket;};" +
"if (1000000000L < time_bucket && time_bucket < 9999999999L) {return time_bucket.intdiv(100);};" +
"if (100000000000L < time_bucket && time_bucket < 999999999999L) {return time_bucket.intdiv(100*100);};" +
"if (10000000000000L < time_bucket && time_bucket < 99999999999999L) {return time_bucket.intdiv(100*100*100);};" +
"}";
private static final String TIME_SEC_RANGE_SHARDING_EXPRESSION =
"\"datetime-pattern\"=\"yyyyMMddHHmmss\"," +
"\"datetime-interval-unit\"=\"days\"," +
"\"datetime-interval-amount\"=\"1\"," +
"\"sharding-suffix-pattern\"=\"yyyyMMdd\"," +
"\"datetime-lower\"=\"20220101000000\"," +
"\"datetime-upper\"=\"20991201000000\"";
private static final String TIME_MIN_RANGE_SHARDING_EXPRESSION =
"\"datetime-pattern\"=\"yyyyMMddHHmm\"," +
"\"datetime-interval-unit\"=\"days\"," +
"\"datetime-interval-amount\"=\"1\"," +
"\"sharding-suffix-pattern\"=\"yyyyMMdd\"," +
"\"datetime-lower\"=\"202201010000\"," +
"\"datetime-upper\"=\"209912010000\"";
private static final String TIME_BUCKET_SHARDING_EXPRESSION =
"${" +
"if (10000000L < time_bucket && time_bucket < 99999999L) {return time_bucket;};" +
"if (1000000000L < time_bucket && time_bucket < 9999999999L) {return time_bucket.intdiv(100);};" +
"if (100000000000L < time_bucket && time_bucket < 999999999999L) {return time_bucket.intdiv(100*100);};" +
"if (10000000000000L < time_bucket && time_bucket < 99999999999999L) {return time_bucket.intdiv(100*100*100);};" +
"}";
public void start(JDBCHikariCPClient client) throws IOException, SQLException, StorageException {
initShardingRules(client);
}
boolean createOrUpdateShardingRule(JDBCHikariCPClient client, Model model, Set<String> dataSources, int ttl) throws StorageException {
boolean isExecuted;
ShardingRule.ShardingRuleBuilder builder = ShardingRule.builder();
builder.table(model.getName());
String tableName = model.getName();
SQLDatabaseModelExtension.Sharding sharding = model.getSqlDBModelExtension().getSharding().orElseThrow(
() -> new UnexpectedException("Sharding should not be empty."));
isExecuted = executeShardingRule(
buildShardingRule(builder, tableName, dataSources, sharding.getShardingAlgorithm(),
sharding.getTableShardingColumn(),
sharding.getDataSourceShardingColumn(),
ttl,
DateTime.now()
),
client,
tableName
);
// additional tables
for (String additionalTable : model.getSqlDBModelExtension().getAdditionalTables().keySet()) {
ShardingRule.ShardingRuleBuilder additionalBuilder = ShardingRule.builder();
additionalBuilder.table(additionalTable);
isExecuted = executeShardingRule(
buildShardingRule(additionalBuilder, additionalTable, dataSources, sharding.getShardingAlgorithm(),
sharding.getTableShardingColumn(),
sharding.getDataSourceShardingColumn(), ttl, DateTime.now()
), client, additionalTable
);
}
return isExecuted;
}
private void initShardingRules(JDBCHikariCPClient client) throws IOException {
SQLBuilder sql = new SQLBuilder("SHOW SHARDING TABLE RULES");
try (Connection connection = client.getConnection()) {
ResultSet resultSet = client.executeQuery(connection, sql.toString());
while (resultSet.next()) {
ShardingRule.ShardingRuleBuilder builder = ShardingRule.builder();
builder.table(resultSet.getString("TABLE"));
builder.actualDataNodes(resultSet.getString("ACTUAL_DATA_NODES"));
builder.actualDataSources(resultSet.getString("ACTUAL_DATA_SOURCES"));
// todo: shardingsphere-5.1.2 response DATABASE_STRATEGY and TABLE_STRATEGY type "inline" but should "standard"
builder.databaseStrategyType("standard");
builder.databaseShardingColumn(resultSet.getString("DATABASE_SHARDING_COLUMN"));
builder.databaseShardingAlgorithmType(resultSet.getString("DATABASE_SHARDING_ALGORITHM_TYPE"));
builder.databaseShardingAlgorithmProps(resultSet.getString("DATABASE_SHARDING_ALGORITHM_PROPS"));
// todo: shardingsphere-5.1.2 response DATABASE_STRATEGY and TABLE_STRATEGY type "inline" but should "standard"
builder.tableStrategyType("standard");
builder.tableShardingColumn(resultSet.getString("TABLE_SHARDING_COLUMN"));
builder.tableShardingAlgorithmType(resultSet.getString("TABLE_SHARDING_ALGORITHM_TYPE"));
builder.tableShardingAlgorithmProps(resultSet.getString("TABLE_SHARDING_ALGORITHM_PROPS"));
builder.keyGenerateColumn(resultSet.getString("KEY_GENERATE_COLUMN"));
builder.keyGeneratorType(resultSet.getString("KEY_GENERATOR_TYPE"));
builder.keyGeneratorProps(resultSet.getString("KEY_GENERATOR_PROPS"));
ShardingRule shardingRule = builder.build();
modelShardingRules.put(shardingRule.getTable(), shardingRule);
}
} catch (JDBCClientException | SQLException e) {
throw new IOException(e.getMessage(), e);
}
}
private void registerShardingRule(String tableName, ShardingRule rule) {
modelShardingRules.put(tableName, rule);
}
private ShardingRule.ShardingRuleBuilder buildShardingRule(ShardingRule.ShardingRuleBuilder builder,
String tableName,
Set<String> dataSources,
ShardingAlgorithm shardingAlgorithm,
String tableShardingColumn,
String dsShardingColumn,
int ttl,
DateTime currentDate) {
buildDataNodes(builder, tableName, dataSources, ttl, currentDate);
buildDatabaseStrategy(builder, dsShardingColumn, dataSources.size());
switch (shardingAlgorithm) {
case TIME_SEC_RANGE_SHARDING_ALGORITHM:
buildTimeRangeTableStrategy(builder, tableShardingColumn, TIME_SEC_RANGE_SHARDING_EXPRESSION);
break;
case TIME_MIN_RANGE_SHARDING_ALGORITHM:
buildTimeRangeTableStrategy(builder, tableShardingColumn, TIME_MIN_RANGE_SHARDING_EXPRESSION);
break;
case TIME_RELATIVE_ID_SHARDING_ALGORITHM:
buildExpressionTableStrategy(builder, tableName, tableShardingColumn,
TIME_RELATIVE_ID_SHARDING_EXPRESSION);
break;
case TIME_BUCKET_SHARDING_ALGORITHM:
buildExpressionTableStrategy(builder, tableName, tableShardingColumn, TIME_BUCKET_SHARDING_EXPRESSION);
break;
default:
throw new UnexpectedException("Unsupported sharding algorithm " + shardingAlgorithm);
}
return builder;
}
private void buildDataNodes(ShardingRule.ShardingRuleBuilder builder,
String tableName,
Set<String> dataSources,
int ttl,
DateTime currentDate) {
DateTime startDateTime = currentDate.plusDays(1 - ttl);
DateTime endDate = currentDate.plusDays(1);
int days = Days.daysBetween(startDateTime, endDate).getDays();
List<DateTime> timeRanges = new ArrayList<>();
StringBuilder nodesBuilder = new StringBuilder();
for (int i = 0; i <= days; i++) {
timeRanges.add(startDateTime.plusDays(i));
}
dataSources.forEach(dataSource -> {
timeRanges.forEach(dateTime -> {
nodesBuilder.append("\"")
.append(dataSource)
.append(".")
.append(tableName)
.append("_")
.append(dateTime.toString("yyyyMMdd"))
.append("\"")
.append(",");
});
});
builder.actualDataNodes(nodesBuilder.substring(0, nodesBuilder.length() - 1));
}
private void buildDatabaseStrategy(ShardingRule.ShardingRuleBuilder builder,
String shardingColumn,
int dsCount) {
StringBuilder propsBuilder = new StringBuilder();
propsBuilder.append("\"algorithm-expression\"=\"ds_${")
.append(shardingColumn)
.append(".hashCode()&Integer.MAX_VALUE%")
.append(dsCount)
.append("}\"");
builder.databaseStrategyType("\"standard\"")
.databaseShardingColumn(shardingColumn)
.databaseShardingAlgorithmType("\"inline\"")
.databaseShardingAlgorithmProps(propsBuilder.toString());
}
private void buildTimeRangeTableStrategy(ShardingRule.ShardingRuleBuilder builder,
String tableShardingColumn, String algorithmExpression) {
builder.tableStrategyType("\"standard\"")
.tableShardingColumn(tableShardingColumn)
.tableShardingAlgorithmType("\"interval\"")
.tableShardingAlgorithmProps(algorithmExpression);
}
private void buildExpressionTableStrategy(ShardingRule.ShardingRuleBuilder builder,
String tableName,
String tableShardingColumn,
String algorithmExpression
) {
StringBuilder propsBuilder = new StringBuilder();
propsBuilder.append("\"allow-range-query-with-inline-sharding\"=\"true\",")
.append("\"algorithm-expression\"=\"")
.append(tableName)
.append("_")
.append(algorithmExpression)
.append("\"");
builder.tableStrategyType("\"standard\"")
.tableShardingColumn(tableShardingColumn)
.tableShardingAlgorithmType("\"inline\"")
.tableShardingAlgorithmProps(propsBuilder.toString());
}
private boolean executeShardingRule(ShardingRule.ShardingRuleBuilder builder,
JDBCHikariCPClient client,
String tableName) throws StorageException {
ShardingRule existRule = modelShardingRules.get(tableName);
ShardingRule shardingRule;
String shardingRuleSQL;
if (existRule == null) {
builder.operation("CREATE");
shardingRule = builder.build();
shardingRuleSQL = shardingRule.toShardingRuleSQL();
} else {
builder.operation("ALTER");
existRule.setOperation("ALTER");
shardingRule = builder.build();
shardingRuleSQL = shardingRule.toShardingRuleSQL();
if (existRule.toShardingRuleSQL().equals(shardingRuleSQL.replaceAll("\"", ""))) {
return false;
}
}
try (Connection connection = client.getConnection()) {
SQLBuilder ruleSQL = new SQLBuilder(shardingRuleSQL);
client.execute(connection, ruleSQL.toString());
registerShardingRule(tableName, shardingRule);
} catch (JDBCClientException | SQLException e) {
throw new StorageException(e.getMessage(), e);
}
return true;
}
}

View File

@ -0,0 +1,35 @@
/*
* 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.shardingsphere.mysql.dao;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.dao.ShardingLogQueryDAO;
public class MySQLShardingLogQueryDAO extends ShardingLogQueryDAO {
public MySQLShardingLogQueryDAO(final JDBCHikariCPClient h2Client, final ModuleManager manager) {
super(h2Client, manager);
}
@Override
protected void buildLimit(StringBuilder sql, int from, int limit) {
sql.append(" LIMIT ").append(from).append(", ").append(limit);
}
}

View File

@ -0,0 +1,36 @@
/*
* 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.shardingsphere.mysql.dao;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.dao.ShardingTraceQueryDAO;
public class MySQLShardingTraceQueryDAO extends ShardingTraceQueryDAO {
public MySQLShardingTraceQueryDAO(ModuleManager manager,
JDBCHikariCPClient h2Client) {
super(manager, h2Client);
}
@Override
protected void buildLimit(StringBuilder sql, int from, int limit) {
sql.append(" LIMIT ").append(from).append(", ").append(limit);
}
}

View File

@ -0,0 +1,32 @@
/*
* 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.shardingsphere.mysql.dao;
import org.apache.skywalking.oap.server.library.client.jdbc.hikaricp.JDBCHikariCPClient;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.dao.ShardingBrowserLogQueryDAO;
public class MysqlShardingBrowserLogQueryDAO extends ShardingBrowserLogQueryDAO {
public MysqlShardingBrowserLogQueryDAO(final JDBCHikariCPClient h2Client) {
super(h2Client);
}
@Override
protected void buildLimit(StringBuilder sql, int from, int limit) {
sql.append(" limit ").append(from).append(", ").append(limit);
}
}

View File

@ -0,0 +1,19 @@
#
# 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.storage.plugin.jdbc.shardingsphere.mysql.MySQLShardingStorageProvider

View File

@ -0,0 +1,129 @@
/*
* 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.shardingsphere.mysql;
import org.apache.skywalking.oap.server.core.config.ConfigService;
import org.apache.skywalking.oap.server.core.query.enumeration.Step;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.DurationWithinTTL;
import org.joda.time.DateTime;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.powermock.api.mockito.PowerMockito;
import static org.powermock.api.mockito.PowerMockito.when;
public class DurationWithinTTLTest {
private final int recordDataTTL = 3;
@Before
public void init() {
ConfigService configService = PowerMockito.mock(ConfigService.class);
when(configService.getRecordDataTTL()).thenReturn(recordDataTTL);
DurationWithinTTL.INSTANCE.setConfigService(configService);
}
@Test
public void testGetTrimmedRecordStartTime() {
String expectedDay = new DateTime().toString("yyyy-MM-dd");
String inputDay = new DateTime().toString("yyyy-MM-dd");
Assert.assertEquals(expectedDay, DurationWithinTTL.INSTANCE.getTrimmedRecordStartTime(Step.DAY, inputDay));
String expectedDayOutTTL = new DateTime().plusDays(1 - recordDataTTL).toString("yyyy-MM-dd");
String inputDayOutTTL = new DateTime().plusDays(-recordDataTTL).toString("yyyy-MM-dd");
Assert.assertEquals(
expectedDayOutTTL, DurationWithinTTL.INSTANCE.getTrimmedRecordStartTime(Step.DAY, inputDayOutTTL));
String expectedHour = new DateTime().toString("yyyy-MM-dd HH");
String inputHour = new DateTime().toString("yyyy-MM-dd HH");
Assert.assertEquals(expectedHour, DurationWithinTTL.INSTANCE.getTrimmedRecordStartTime(Step.HOUR, inputHour));
String inputHourOutTTL = new DateTime().plusDays(-recordDataTTL).toString("yyyy-MM-dd HH");
Assert.assertEquals(
expectedDayOutTTL + " 00",
DurationWithinTTL.INSTANCE.getTrimmedRecordStartTime(Step.HOUR, inputHourOutTTL)
);
String expectedMin = new DateTime().toString("yyyy-MM-dd HHmm");
String inputMin = new DateTime().toString("yyyy-MM-dd HHmm");
Assert.assertEquals(expectedMin, DurationWithinTTL.INSTANCE.getTrimmedRecordStartTime(Step.MINUTE, inputMin));
String inputMinOutTTL = new DateTime().plusDays(-recordDataTTL).toString("yyyy-MM-dd HHmm");
Assert.assertEquals(
expectedDayOutTTL + " 0000",
DurationWithinTTL.INSTANCE.getTrimmedRecordStartTime(Step.MINUTE, inputMinOutTTL)
);
String inputSec = new DateTime().toString("yyyy-MM-dd HHmmss");
String expectedSec = new DateTime().toString("yyyy-MM-dd HHmmss");
Assert.assertEquals(expectedSec, DurationWithinTTL.INSTANCE.getTrimmedRecordStartTime(Step.SECOND, inputSec));
String inputSecOutTTL = new DateTime().plusDays(-recordDataTTL).toString("yyyy-MM-dd HHmmss");
Assert.assertEquals(
expectedDayOutTTL + " 000000",
DurationWithinTTL.INSTANCE.getTrimmedRecordStartTime(Step.SECOND, inputSecOutTTL)
);
try {
DurationWithinTTL.INSTANCE.getTrimmedRecordStartTime(Step.HOUR, "2022-09-08 30");
Assert.fail("Should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
Assert.assertTrue(true);
}
}
@Test
public void testGetTrimmedMetricEndTime() {
String expectedDay = new DateTime().toString("yyyy-MM-dd");
String inputDay = new DateTime().toString("yyyy-MM-dd");
Assert.assertEquals(expectedDay, DurationWithinTTL.INSTANCE.getTrimmedMetricEndTime(Step.DAY, inputDay));
String expectedDayOutTTL = new DateTime().toString("yyyy-MM-dd");
String inputDayOutTTL = new DateTime().plusDays(1).toString("yyyy-MM-dd");
Assert.assertEquals(
expectedDayOutTTL, DurationWithinTTL.INSTANCE.getTrimmedMetricEndTime(Step.DAY, inputDayOutTTL));
String expectedHour = new DateTime().toString("yyyy-MM-dd HH");
String inputHour = new DateTime().toString("yyyy-MM-dd HH");
Assert.assertEquals(expectedHour, DurationWithinTTL.INSTANCE.getTrimmedMetricEndTime(Step.HOUR, inputHour));
String inputHourOutTTL = new DateTime().plusDays(1).toString("yyyy-MM-dd HH");
Assert.assertEquals(
expectedDayOutTTL + " 23",
DurationWithinTTL.INSTANCE.getTrimmedMetricEndTime(Step.HOUR, inputHourOutTTL)
);
String expectedMin = new DateTime().toString("yyyy-MM-dd HHmm");
String inputMin = new DateTime().toString("yyyy-MM-dd HHmm");
Assert.assertEquals(expectedMin, DurationWithinTTL.INSTANCE.getTrimmedMetricEndTime(Step.MINUTE, inputMin));
String inputMinOutTTL = new DateTime().plusDays(1).toString("yyyy-MM-dd HHmm");
Assert.assertEquals(
expectedDayOutTTL + " 2359",
DurationWithinTTL.INSTANCE.getTrimmedMetricEndTime(Step.MINUTE, inputMinOutTTL)
);
String inputSec = new DateTime().toString("yyyy-MM-dd HHmmss");
String expectedSec = new DateTime().toString("yyyy-MM-dd HHmmss");
Assert.assertEquals(expectedSec, DurationWithinTTL.INSTANCE.getTrimmedMetricEndTime(Step.SECOND, inputSec));
String inputSecOutTTL = new DateTime().plusDays(1).toString("yyyy-MM-dd HHmmss");
Assert.assertEquals(
expectedDayOutTTL + " 235959",
DurationWithinTTL.INSTANCE.getTrimmedMetricEndTime(Step.SECOND, inputSecOutTTL)
);
try {
DurationWithinTTL.INSTANCE.getTrimmedMetricEndTime(Step.HOUR, "2022-09-08 30");
Assert.fail("Should throw IllegalArgumentException");
} catch (IllegalArgumentException e) {
Assert.assertTrue(true);
}
}
}

View File

@ -0,0 +1,102 @@
/*
* 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.shardingsphere.mysql;
import java.util.Arrays;
import java.util.HashSet;
import org.apache.skywalking.oap.server.core.storage.ShardingAlgorithm;
import org.apache.skywalking.oap.server.storage.plugin.jdbc.shardingsphere.ShardingRule;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.powermock.reflect.Whitebox;
public class ShardingRulesTest {
private DateTime currentDate;
@Before
public void init() {
currentDate = DateTimeFormat.forPattern("yyyyMMdd").parseDateTime("20220919");
}
@Test
public void buildTimeRangeShardingRuleTest() throws Exception {
ShardingRulesOperator rulesOperator = ShardingRulesOperator.INSTANCE;
ShardingRule.ShardingRuleBuilder builder = ShardingRule.builder();
builder.table("Test_table");
builder.operation("CREATE");
Whitebox.invokeMethod(rulesOperator, "buildShardingRule",
builder,
"Test_table",
new HashSet<>(Arrays.asList("ds_0", "ds_1")),
ShardingAlgorithm.TIME_SEC_RANGE_SHARDING_ALGORITHM,
"time_bucket",
"service_id",
3,
currentDate);
String rule = builder.build().toShardingRuleSQL();
String expectedRule = "CREATE SHARDING TABLE RULE Test_table(" + System.lineSeparator() +
"DATANODES(\"ds_1.Test_table_20220917\",\"ds_1.Test_table_20220918\",\"ds_1.Test_table_20220919\",\"ds_1.Test_table_20220920\",\"ds_0.Test_table_20220917\",\"ds_0.Test_table_20220918\",\"ds_0.Test_table_20220919\",\"ds_0.Test_table_20220920\")," + System.lineSeparator() +
"DATABASE_STRATEGY(TYPE=\"standard\"," + System.lineSeparator() +
"SHARDING_COLUMN=service_id," + System.lineSeparator() +
"SHARDING_ALGORITHM(TYPE(NAME=\"inline\"," + System.lineSeparator() +
"PROPERTIES(\"algorithm-expression\"=\"ds_${service_id.hashCode()&Integer.MAX_VALUE%2}\"))))," + System.lineSeparator() +
"TABLE_STRATEGY(TYPE=\"standard\"," + System.lineSeparator() +
"SHARDING_COLUMN=time_bucket," + System.lineSeparator() +
"SHARDING_ALGORITHM(TYPE(NAME=\"interval\"," + System.lineSeparator() +
"PROPERTIES(\"datetime-pattern\"=\"yyyyMMddHHmmss\",\"datetime-interval-unit\"=\"days\",\"datetime-interval-amount\"=\"1\",\"sharding-suffix-pattern\"=\"yyyyMMdd\",\"datetime-lower\"=\"20220101000000\",\"datetime-upper\"=\"20991201000000\")))))";
Assert.assertEquals(expectedRule, rule);
}
@Test
public void buildTimeRelativeIDShardingRuleTest() throws Exception {
ShardingRulesOperator rulesOperator = ShardingRulesOperator.INSTANCE;
ShardingRule.ShardingRuleBuilder builder = ShardingRule.builder();
builder.table("Test_table");
builder.operation("CREATE");
Whitebox.invokeMethod(rulesOperator, "buildShardingRule",
builder,
"Test_table",
new HashSet<>(Arrays.asList("ds_0", "ds_1")),
ShardingAlgorithm.TIME_RELATIVE_ID_SHARDING_ALGORITHM,
"id",
"entity_id",
3,
currentDate);
String rule = builder.build().toShardingRuleSQL();
String expectedRule = "CREATE SHARDING TABLE RULE Test_table(" + System.lineSeparator() +
"DATANODES(\"ds_1.Test_table_20220917\",\"ds_1.Test_table_20220918\",\"ds_1.Test_table_20220919\",\"ds_1.Test_table_20220920\",\"ds_0.Test_table_20220917\",\"ds_0.Test_table_20220918\",\"ds_0.Test_table_20220919\",\"ds_0.Test_table_20220920\")," + System.lineSeparator() +
"DATABASE_STRATEGY(TYPE=\"standard\"," + System.lineSeparator() +
"SHARDING_COLUMN=entity_id," + System.lineSeparator() +
"SHARDING_ALGORITHM(TYPE(NAME=\"inline\"," + System.lineSeparator() +
"PROPERTIES(\"algorithm-expression\"=\"ds_${entity_id.hashCode()&Integer.MAX_VALUE%2}\"))))," + System.lineSeparator() +
"TABLE_STRATEGY(TYPE=\"standard\"," + System.lineSeparator() +
"SHARDING_COLUMN=id," + System.lineSeparator() +
"SHARDING_ALGORITHM(TYPE(NAME=\"inline\"," + System.lineSeparator() +
"PROPERTIES(\"allow-range-query-with-inline-sharding\"=\"true\",\"algorithm-expression\"=\"Test_table_${long time_bucket = Long.parseLong(id.substring(0,id.indexOf('_')));" +
"if (10000000L < time_bucket && time_bucket < 99999999L) {return time_bucket;};" +
"if (1000000000L < time_bucket && time_bucket < 9999999999L) {return time_bucket.intdiv(100);};" +
"if (100000000000L < time_bucket && time_bucket < 999999999999L) {return time_bucket.intdiv(100*100);};" +
"if (10000000000000L < time_bucket && time_bucket < 99999999999999L) {return time_bucket.intdiv(100*100*100);};" +
"}\")))))";
Assert.assertEquals(expectedRule, rule);
}
}

View File

@ -39,7 +39,7 @@ services:
environment:
SW_STORAGE: mysql
SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
ports:
- 12800
depends_on:

View File

@ -30,7 +30,7 @@ services:
context: ./
dockerfile: docker/Dockerfile.provider
args:
- SW_AGENT_PYTHON_COMMIT=c8479000eb729cc86509222fd48b942edcaaca74
- SW_AGENT_PYTHON_COMMIT=${SW_AGENT_PYTHON_COMMIT}
command: [ 'python3', '/entrypoint.py' ]
networks:
- e2e

View File

@ -49,7 +49,7 @@ services:
context: ./../
dockerfile: docker/Dockerfile.provider
args:
- SW_AGENT_PYTHON_COMMIT=c8479000eb729cc86509222fd48b942edcaaca74
- SW_AGENT_PYTHON_COMMIT=${SW_AGENT_PYTHON_COMMIT}
command: [ 'python3', '/entrypoint.py' ]
networks:
- e2e
@ -133,4 +133,4 @@ services:
condition: service_started
networks:
e2e:
e2e:

View File

@ -50,7 +50,7 @@ services:
context: ./../../
dockerfile: docker/Dockerfile.provider
args:
- SW_AGENT_PYTHON_COMMIT=c8479000eb729cc86509222fd48b942edcaaca74
- SW_AGENT_PYTHON_COMMIT=${SW_AGENT_PYTHON_COMMIT}
command: [ 'python3', '/entrypoint.py' ]
networks:
- e2e

View File

@ -0,0 +1,163 @@
# 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:
sharding-proxy:
extends:
file: ../../../../script/shardingsphere-proxy/base-compose.yml
service: sharding-proxy
networks:
- e2e
expose:
- 3307
depends_on:
mysql-1:
condition: service_healthy
mysql-2:
condition: service_healthy
mysql-1: &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
mysql-2:
<<: *mysql
oap:
extends:
file: ../../../../script/docker-compose/base-compose.yml
service: oap
environment:
SW_STORAGE: mysql-sharding
SW_JDBC_URL: jdbc:mysql://sharding-proxy:3307/swtest
SW_JDBC_SHARDING_DATA_SOURCES: ds_0,ds_1
SW_CORE_METRICS_DATA_TTL: 2
SW_CORE_RECORD_DATA_TTL: 2
SW_OTEL_RECEIVER_ENABLED_OTEL_RULES: ""
SW_METER_ANALYZER_ACTIVE_FILES: ""
ports:
- 12800
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
networks:
- e2e
depends_on:
sharding-proxy:
condition: service_healthy
provider:
build:
context: ./../../
dockerfile: docker/Dockerfile.provider
args:
- SW_AGENT_PYTHON_COMMIT=${SW_AGENT_PYTHON_COMMIT}
command: [ 'python3', '/entrypoint.py' ]
networks:
- e2e
expose:
- 9091
environment:
SW_AGENT_COLLECTOR_BACKEND_SERVICES: oap:11800
SW_AGENT_LOGGING_LEVEL: DEBUG
volumes:
- ./../../docker/provider.py:/entrypoint.py
depends_on:
oap:
condition: service_healthy
healthcheck:
test: [ "CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9091" ]
interval: 5s
timeout: 60s
retries: 120
testui:
build:
context: ./../../
dockerfile: docker/Dockerfile.test-ui
args:
- SW_AGENT_CLIENT_JS_TEST_COMMIT=${SW_AGENT_CLIENT_JS_TEST_COMMIT}
- SW_AGENT_CLIENT_JS_COMMIT=${SW_AGENT_CLIENT_JS_COMMIT}
networks:
- e2e
ports:
- 80
depends_on:
provider:
condition: service_healthy
oap:
condition: service_healthy
selenium-hub:
image: selenium/hub:4.0.0-alpha-7-prerelease-20201009
networks:
- e2e
expose:
- 4444
depends_on:
testui:
condition: service_started
provider:
condition: service_healthy
chrome:
image: selenium/node-chrome:4.0.0-alpha-7-prerelease-20201009
networks:
- e2e
volumes:
- /dev/shm:/dev/shm
depends_on:
selenium-hub:
condition: service_started
testui:
condition: service_started
provider:
condition: service_healthy
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
generate-traffic:
build:
context: ./../../
dockerfile: docker/Dockerfile.generate-traffic
networks:
- e2e
restart: always
depends_on:
selenium-hub:
condition: service_started
chrome:
condition: service_started
provider:
condition: service_healthy
testui:
condition: service_started
networks:
e2e:

View File

@ -0,0 +1,40 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
setup:
env: compose
file: docker-compose.yml
timeout: 20m
init-system-environment: ../../../../script/env
steps:
- name: set PATH
command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
- name: install yq
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
- name: install swctl
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
verify:
# verify with retry strategy
retry:
# max retry count
count: 20
# the interval between two retries, in millisecond.
interval: 3s
cases:
- includes:
- ../../browser-cases.yaml

View File

@ -41,7 +41,7 @@ services:
depends_on:
mysql:
condition: service_healthy
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
ports:
- 11800
- 12800

View File

@ -41,7 +41,7 @@ services:
SW_JDBC_URL: jdbc:mysql://mysql:3306/swtest
ports:
- 12800
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
networks:
- e2e
depends_on:

View File

@ -0,0 +1,88 @@
# 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:
sharding-proxy:
extends:
file: ../../../../script/shardingsphere-proxy/base-compose.yml
service: sharding-proxy
networks:
- e2e
expose:
- 3307
depends_on:
mysql-1:
condition: service_healthy
mysql-2:
condition: service_healthy
mysql-1: &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
mysql-2:
<<: *mysql
oap:
extends:
file: ../../log-base-compose.yml
service: oap
environment:
SW_STORAGE: mysql-sharding
SW_JDBC_URL: jdbc:mysql://sharding-proxy:3307/swtest
SW_JDBC_SHARDING_DATA_SOURCES: ds_0,ds_1
SW_CORE_METRICS_DATA_TTL: 2
SW_CORE_RECORD_DATA_TTL: 2
SW_OTEL_RECEIVER_ENABLED_OTEL_RULES: ""
SW_METER_ANALYZER_ACTIVE_FILES: ""
SW_ENVOY_METRIC: "-"
ports:
- 12800
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
networks:
- e2e
depends_on:
sharding-proxy:
condition: service_healthy
provider:
extends:
file: ../../../../script/docker-compose/base-compose.yml
service: provider
depends_on:
oap:
condition: service_healthy
ports:
- 9090
networks:
- e2e
networks:
e2e:

View File

@ -0,0 +1,47 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
setup:
env: compose
file: docker-compose.yml
timeout: 20m
init-system-environment: ../../../../script/env
steps:
- name: set PATH
command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
- name: install yq
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
- name: install swctl
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
trigger:
action: http
interval: 3s
times: 10
url: http://${provider_host}:${provider_9090}/logs/trigger
method: GET
verify:
# verify with retry strategy
retry:
# max retry count
count: 20
# the interval between two retries, in millisecond.
interval: 10s
cases:
- includes:
- ../../log-cases.yaml

View File

@ -22,7 +22,7 @@ services:
service: oap
ports:
- 12800
entrypoint: ['sh', '-c', '/download-mysql.sh && chmod 777 /skywalking/docker-entrypoint.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && chmod 777 /skywalking/docker-entrypoint.sh && /skywalking/docker-entrypoint.sh']
networks:
- e2e
environment:
@ -103,4 +103,4 @@ services:
oap:
condition: service_healthy
networks:
e2e:
e2e:

View File

@ -40,7 +40,7 @@ services:
- e2e
environment:
SW_STORAGE: mysql
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
ports:
- 12800
depends_on:
@ -65,4 +65,4 @@ services:
condition: service_healthy
networks:
e2e:
e2e:

View File

@ -41,7 +41,7 @@ services:
SW_STORAGE: tidb
SW_JDBC_URL: "jdbc:mysql://tidb:4000/test"
SW_DATA_SOURCE_PASSWORD: ""
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
depends_on:
tidb:
condition: service_healthy
@ -66,4 +66,4 @@ services:
condition: service_healthy
networks:
e2e:
e2e:

View File

@ -51,7 +51,7 @@ services:
depends_on:
mysql:
condition: service_healthy
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
ports:
- 12800

View File

@ -49,7 +49,7 @@ services:
SW_STORAGE: tidb
SW_JDBC_URL: "jdbc:mysql://tidb:4000/test"
SW_DATA_SOURCE_PASSWORD: ""
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
depends_on:
tidb:
condition: service_healthy

View File

@ -41,7 +41,7 @@ services:
SW_JDBC_URL: jdbc:mysql://mysql:3306/swtest
ports:
- 12800
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
networks:
- e2e
depends_on:

View File

@ -0,0 +1,101 @@
# 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:
sharding-proxy:
extends:
file: ../../../../script/shardingsphere-proxy/base-compose.yml
service: sharding-proxy
networks:
- e2e
expose:
- 3307
depends_on:
mysql-1:
condition: service_healthy
mysql-2:
condition: service_healthy
mysql-1: &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
mysql-2:
<<: *mysql
oap:
extends:
file: ../../../../script/docker-compose/base-compose.yml
service: oap
environment:
SW_STORAGE: mysql-sharding
SW_JDBC_URL: jdbc:mysql://sharding-proxy:3307/swtest
SW_JDBC_SHARDING_DATA_SOURCES: ds_0,ds_1
SW_CORE_METRICS_DATA_TTL: 2
SW_CORE_RECORD_DATA_TTL: 2
SW_OTEL_RECEIVER_ENABLED_OTEL_RULES: ""
SW_METER_ANALYZER_ACTIVE_FILES: ""
SW_LOG_LAL_FILES: ""
SW_ENVOY_METRIC: "-"
ports:
- 12800
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
networks:
- e2e
depends_on:
sharding-proxy:
condition: service_healthy
provider:
extends:
file: ../../../../script/docker-compose/base-compose.yml
service: provider
depends_on:
oap:
condition: service_healthy
ports:
- 9090
networks:
- e2e
consumer:
extends:
file: ../../../../script/docker-compose/base-compose.yml
service: consumer
ports:
- 9092
depends_on:
oap:
condition: service_healthy
provider:
condition: service_healthy
networks:
e2e:

View File

@ -0,0 +1,50 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
setup:
env: compose
file: docker-compose.yml
timeout: 20m
init-system-environment: ../../../../script/env
steps:
- name: set PATH
command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
- name: install yq
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
- name: install swctl
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
trigger:
action: http
interval: 3s
times: 10
url: http://${consumer_host}:${consumer_9092}/users
method: POST
body: '{"id":"123","name":"skywalking"}'
headers:
"Content-Type": "application/json"
verify:
# verify with retry strategy
retry:
# max retry count
count: 20
# the interval between two retries, in millisecond.
interval: 10s
cases:
- includes:
- ../../storage-cases.yaml

View File

@ -41,7 +41,7 @@ services:
SW_DATA_SOURCE_PASSWORD: ""
ports:
- 12800
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
networks:
- e2e
depends_on:

View File

@ -41,7 +41,7 @@ services:
SW_CORE_METRICS_DATA_TTL: 7
SW_JDBC_URL: "jdbc:mysql://tidb:4000/test"
SW_DATA_SOURCE_PASSWORD: ""
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
depends_on:
tidb:
condition: service_healthy

View File

@ -45,7 +45,7 @@ services:
- 9411
ports:
- 9412
entrypoint: ['sh', '-c', '/download-mysql.sh && /skywalking/docker-entrypoint.sh']
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
networks:
- e2e
depends_on:

View File

@ -0,0 +1,100 @@
# 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:
sharding-proxy:
extends:
file: ../../../../script/shardingsphere-proxy/base-compose.yml
service: sharding-proxy
networks:
- e2e
expose:
- 3307
depends_on:
mysql-1:
condition: service_healthy
mysql-2:
condition: service_healthy
mysql-1: &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
mysql-2:
<<: *mysql
oap:
extends:
file: ../../../../script/docker-compose/base-compose.yml
service: oap
environment:
SW_STORAGE: mysql-sharding
SW_JDBC_URL: jdbc:mysql://sharding-proxy:3307/swtest
SW_JDBC_SHARDING_DATA_SOURCES: ds_0,ds_1
SW_CORE_METRICS_DATA_TTL: 2
SW_CORE_RECORD_DATA_TTL: 2
SW_OTEL_RECEIVER_ENABLED_OTEL_RULES: ""
SW_METER_ANALYZER_ACTIVE_FILES: ""
SW_LOG_LAL_FILES: ""
SW_ENVOY_METRIC: "-"
SW_QUERY_ZIPKIN: default
SW_RECEIVER_ZIPKIN: default
expose:
- 9411
ports:
- 9412
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
networks:
- e2e
depends_on:
sharding-proxy:
condition: service_healthy
frontend:
extends:
file: ../../docker-compose-brave.yml
service: frontend
depends_on:
backend:
condition: service_healthy
oap:
condition: service_healthy
ports:
- 8081
backend:
extends:
file: ../../docker-compose-brave.yml
service: backend
depends_on:
oap:
condition: service_healthy
networks:
e2e:

View File

@ -0,0 +1,47 @@
# 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.
# This file is used to show how to write configuration files and can be used to test.
setup:
env: compose
file: docker-compose.yml
timeout: 20m
init-system-environment: ../../../../script/env
steps:
- name: set PATH
command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
- name: install yq
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
- name: install swctl
command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
trigger:
action: http
interval: 3s
times: 10
url: http://${frontend_host}:${frontend_8081}
method: POST
verify:
# verify with retry strategy
retry:
# max retry count
count: 20
# the interval between two retries, in millisecond.
interval: 10s
cases:
- includes:
- ../../zipkin-cases.yaml

View File

@ -17,7 +17,7 @@
set -ex
SW_HOME=/skywalking
LIB_HOME=$1
MYSQL_URL="https://repo.maven.apache.org/maven2/mysql/mysql-connector-java/8.0.13/mysql-connector-java-8.0.13.jar"
MYSQL_DRIVER="mysql-connector-java-8.0.13.jar"
@ -26,7 +26,7 @@ if ! command -v curl &> /dev/null; then
apt update -y && apt install -y curl
fi
if ! curl -Lo "${SW_HOME}/oap-libs/${MYSQL_DRIVER}" ${MYSQL_URL}; then
if ! curl -Lo "${LIB_HOME}/${MYSQL_DRIVER}" ${MYSQL_URL}; then
echo "Fail to download ${MYSQL_DRIVER}."
exit 1
fi

View File

@ -0,0 +1,36 @@
# 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:
sharding-proxy:
image: apache/shardingsphere-proxy:5.1.2
volumes:
- ./../prepare/setup-oap/download-mysql.sh:/opt/shardingsphere-proxy/download-mysql.sh
- ./conf:/opt/shardingsphere-proxy/conf
networks:
- e2e
expose:
- 3307
entrypoint: ['sh', '-c', '/opt/shardingsphere-proxy/download-mysql.sh /opt/shardingsphere-proxy/ext-lib && /opt/shardingsphere-proxy/bin/start.sh 3307 && tail -f /opt/shardingsphere-proxy/logs/stdout.log']
healthcheck:
test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/3307"]
interval: 5s
timeout: 60s
retries: 120
networks:
e2e:

View File

@ -0,0 +1,45 @@
#
# 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.
#
######################################################################################################
#
# Here you can configure the rules for the proxy.
# This example is configuration of sharding rule.
#
######################################################################################################
#
databaseName: swtest
dataSources:
ds_0:
url: jdbc:mysql://mysql-1:3306/swtest?allowPublicKeyRetrieval=true
username: root
password: root@1234
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
ds_1:
url: jdbc:mysql://mysql-2:3306/swtest?allowPublicKeyRetrieval=true
username: root
password: root@1234
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1

Some files were not shown because too many files have changed in this diff Show More