in oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/model/StorageModels.java [157:302]
private void retrieval(final Class<?> clazz,
final String modelName,
final List<ModelColumn> modelColumns,
final int scopeId,
SeriesIDChecker seriesIDChecker,
ShardingKeyChecker shardingKeyChecker,
final SQLDatabaseModelExtension sqlDBModelExtension,
final BanyanDBModelExtension banyanDBModelExtension) {
if (log.isDebugEnabled()) {
log.debug("Analysis {} to generate Model.", clazz.getName());
}
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Column.class)) {
if (field.isAnnotationPresent(SQLDatabase.AdditionalEntity.class)) {
if (!Record.class.isAssignableFrom(clazz)) {
throw new IllegalStateException(
"Model [" + modelName + "] is not a Record, @SQLDatabase.AdditionalEntity only supports Record.");
}
}
Column column = field.getAnnotation(Column.class);
// Use the column#length as the default column length, as read the system env as the override mechanism.
// Log the error but don't block the startup sequence.
int columnLength = column.length();
// SQL Database extension
SQLDatabaseExtension sqlDatabaseExtension = new SQLDatabaseExtension();
List<SQLDatabase.CompositeIndex> indexDefinitions = new ArrayList<>();
if (field.isAnnotationPresent(SQLDatabase.CompositeIndex.class)) {
indexDefinitions.add(field.getAnnotation(SQLDatabase.CompositeIndex.class));
}
if (field.isAnnotationPresent(SQLDatabase.CompositeIndices.class)) {
Collections.addAll(
indexDefinitions, field.getAnnotation(SQLDatabase.CompositeIndices.class).value());
}
indexDefinitions.forEach(indexDefinition -> {
sqlDatabaseExtension.appendIndex(new SQLDatabaseExtension.MultiColumnsIndex(
column.name(),
indexDefinition.withColumns()
));
});
// ElasticSearch extension
final var elasticSearchAnalyzer = field.getAnnotation(ElasticSearch.MatchQuery.class);
final var elasticSearchColumn = field.getAnnotation(ElasticSearch.Column.class);
final var keywordColumn = field.getAnnotation(ElasticSearch.Keyword.class);
final var routingColumn = field.getAnnotation(ElasticSearch.Routing.class);
final var enableDocValues = field.getAnnotation(ElasticSearch.EnableDocValues.class);
final var elasticSearchExtension = new ElasticSearchExtension(
elasticSearchAnalyzer == null ? null : elasticSearchAnalyzer.analyzer(),
elasticSearchColumn == null ? null : elasticSearchColumn.legacyName(),
keywordColumn != null,
routingColumn != null,
enableDocValues != null
);
// BanyanDB extension
final BanyanDB.SeriesID banyanDBSeriesID = field.getAnnotation(
BanyanDB.SeriesID.class);
final BanyanDB.ShardingKey banyanDBShardingKey = field.getAnnotation(
BanyanDB.ShardingKey.class);
final BanyanDB.NoIndexing banyanDBNoIndex = field.getAnnotation(
BanyanDB.NoIndexing.class);
final BanyanDB.IndexRule banyanDBIndexRule = field.getAnnotation(
BanyanDB.IndexRule.class);
final BanyanDB.MeasureField banyanDBMeasureField = field.getAnnotation(
BanyanDB.MeasureField.class);
final BanyanDB.TopNAggregation topNAggregation = field.getAnnotation(
BanyanDB.TopNAggregation.class);
final BanyanDB.MatchQuery analyzer = field.getAnnotation(
BanyanDB.MatchQuery.class);
final BanyanDB.EnableSort enableSort = field.getAnnotation(
BanyanDB.EnableSort.class);
final boolean shouldIndex = (banyanDBNoIndex == null) && !column.storageOnly();
BanyanDBExtension banyanDBExtension = new BanyanDBExtension(
banyanDBSeriesID == null ? -1 : banyanDBSeriesID.index(),
banyanDBShardingKey == null ? -1 : banyanDBShardingKey.index(),
shouldIndex,
banyanDBIndexRule == null ? BanyanDB.IndexRule.IndexType.INVERTED : banyanDBIndexRule.indexType(),
banyanDBMeasureField != null,
analyzer == null ? null : analyzer.analyzer(),
enableSort != null
);
if (topNAggregation != null) {
BanyanDBModelExtension.TopN topN = new BanyanDBModelExtension.TopN();
topN.setLruSize(topNAggregation.lruSize());
topN.setCountersNumber(topNAggregation.countersNumber());
topN.setGroupByTagNames(Collections.singletonList(column.name()));
banyanDBModelExtension.setTopN(topN);
}
final ModelColumn modelColumn = new ModelColumn(
new ColumnName(column),
field.getType(),
field.getGenericType(),
column.storageOnly(),
column.indexOnly(),
column.dataType().isValue(),
columnLength,
sqlDatabaseExtension,
elasticSearchExtension,
banyanDBExtension
);
if (banyanDBExtension.isSeriesID()) {
seriesIDChecker.accept(modelName, modelColumn);
}
if (banyanDBExtension.isShardingKey()) {
shardingKeyChecker.accept(modelName, modelColumn);
}
if (field.isAnnotationPresent(SQLDatabase.AdditionalEntity.class)) {
final var additionalEntity = field.getAnnotation(SQLDatabase.AdditionalEntity.class);
final var additionalTableNames = additionalEntity.additionalTables();
for (final var tableName : additionalTableNames) {
sqlDBModelExtension.appendAdditionalTable(tableName, modelColumn);
}
if (!additionalEntity.reserveOriginalColumns()) {
sqlDBModelExtension.appendExcludeColumns(modelColumn);
}
}
modelColumns.add(modelColumn);
if (log.isDebugEnabled()) {
log.debug("The field named [{}] with the [{}] type", column.name(), field.getType());
}
if (column.dataType().isValue()) {
ValueColumnMetadata.INSTANCE.putIfAbsent(
modelName, column.name(),
column.dataType(), column.defaultValue(), scopeId, column.multiIntValues());
}
}
}
if (Objects.nonNull(clazz.getSuperclass())) {
retrieval(
clazz.getSuperclass(), modelName, modelColumns, scopeId, seriesIDChecker, shardingKeyChecker,
sqlDBModelExtension, banyanDBModelExtension
);
}
}