@@ -49,15 +49,16 @@ final class LogsdbIndexModeSettingsProvider implements IndexSettingProvider {
4949 static final String LOGS_PATTERN = "logs-*-*" ;
5050 private static final Set <String > MAPPING_INCLUDES = Set .of ("_doc._source.*" , "_doc.properties.host**" , "_doc.subobjects" );
5151
52- private final SyntheticSourceLicenseService syntheticSourceLicenseService ;
52+ private final LogsdbLicenseService licenseService ;
5353 private final SetOnce <CheckedFunction <IndexMetadata , MapperService , IOException >> mapperServiceFactory = new SetOnce <>();
5454 private final SetOnce <Supplier <IndexVersion >> createdIndexVersion = new SetOnce <>();
5555 private final SetOnce <Boolean > supportFallbackToStoredSource = new SetOnce <>();
56+ private final SetOnce <Boolean > supportFallbackLogsdbRouting = new SetOnce <>();
5657
5758 private volatile boolean isLogsdbEnabled ;
5859
59- LogsdbIndexModeSettingsProvider (SyntheticSourceLicenseService syntheticSourceLicenseService , final Settings settings ) {
60- this .syntheticSourceLicenseService = syntheticSourceLicenseService ;
60+ LogsdbIndexModeSettingsProvider (LogsdbLicenseService licenseService , final Settings settings ) {
61+ this .licenseService = licenseService ;
6162 this .isLogsdbEnabled = CLUSTER_LOGSDB_ENABLED .get (settings );
6263 }
6364
@@ -68,11 +69,13 @@ void updateClusterIndexModeLogsdbEnabled(boolean isLogsdbEnabled) {
6869 void init (
6970 CheckedFunction <IndexMetadata , MapperService , IOException > factory ,
7071 Supplier <IndexVersion > indexVersion ,
71- boolean supportFallbackToStoredSource
72+ boolean supportFallbackToStoredSource ,
73+ boolean supportFallbackLogsdbRouting
7274 ) {
7375 this .mapperServiceFactory .set (factory );
7476 this .createdIndexVersion .set (indexVersion );
7577 this .supportFallbackToStoredSource .set (supportFallbackToStoredSource );
78+ this .supportFallbackLogsdbRouting .set (supportFallbackLogsdbRouting );
7679 }
7780
7881 @ Override
@@ -93,6 +96,7 @@ public Settings getAdditionalIndexSettings(
9396 ) {
9497 Settings .Builder settingsBuilder = null ;
9598 boolean isLogsDB = templateIndexMode == IndexMode .LOGSDB ;
99+ boolean isTemplateValidation = "validate-index-name" .equals (indexName );
96100
97101 // Inject logsdb index mode, based on the logs pattern.
98102 if (isLogsdbEnabled
@@ -110,76 +114,74 @@ && matchesLogsPattern(dataStreamName)) {
110114 if (mappingHints .hasSyntheticSourceUsage && supportFallbackToStoredSource .get ()) {
111115 // This index name is used when validating component and index templates, we should skip this check in that case.
112116 // (See MetadataIndexTemplateService#validateIndexTemplateV2(...) method)
113- boolean isTemplateValidation = "validate-index-name" .equals (indexName );
114117 boolean legacyLicensedUsageOfSyntheticSourceAllowed = isLegacyLicensedUsageOfSyntheticSourceAllowed (
115118 templateIndexMode ,
116119 indexName ,
117120 dataStreamName
118121 );
119- if (syntheticSourceLicenseService .fallbackToStoredSource (isTemplateValidation , legacyLicensedUsageOfSyntheticSourceAllowed )) {
122+ if (licenseService .fallbackToStoredSource (isTemplateValidation , legacyLicensedUsageOfSyntheticSourceAllowed )) {
120123 LOGGER .debug ("creation of index [{}] with synthetic source without it being allowed" , indexName );
121- if ( settingsBuilder == null ) {
122- settingsBuilder = Settings . builder ();
123- }
124- settingsBuilder . put ( IndexSettings . INDEX_MAPPER_SOURCE_MODE_SETTING . getKey (), SourceFieldMapper . Mode . STORED . toString () );
124+ settingsBuilder = getBuilder ( settingsBuilder ). put (
125+ IndexSettings . INDEX_MAPPER_SOURCE_MODE_SETTING . getKey (),
126+ SourceFieldMapper . Mode . STORED . toString ()
127+ );
125128 }
126129 }
127130
128131 if (isLogsDB ) {
129132 // Inject sorting on [host.name], in addition to [@timestamp].
130133 if (mappingHints .sortOnHostName ) {
131- if (settingsBuilder == null ) {
132- settingsBuilder = Settings .builder ();
133- }
134134 if (mappingHints .addHostNameField ) {
135135 // Inject keyword field [host.name] too.
136- settingsBuilder .put (IndexSettings .LOGSDB_ADD_HOST_NAME_FIELD .getKey (), true );
136+ settingsBuilder = getBuilder ( settingsBuilder ) .put (IndexSettings .LOGSDB_ADD_HOST_NAME_FIELD .getKey (), true );
137137 }
138- settingsBuilder .put (IndexSettings .LOGSDB_SORT_ON_HOST_NAME .getKey (), true );
138+ settingsBuilder = getBuilder ( settingsBuilder ) .put (IndexSettings .LOGSDB_SORT_ON_HOST_NAME .getKey (), true );
139139 }
140140
141141 // Inject routing path matching sort fields.
142142 if (settings .getAsBoolean (IndexSettings .LOGSDB_ROUTE_ON_SORT_FIELDS .getKey (), false )) {
143- List <String > sortFields = new ArrayList <>(settings .getAsList (IndexSortConfig .INDEX_SORT_FIELD_SETTING .getKey ()));
144- sortFields .removeIf (s -> s .equals (DataStreamTimestampFieldMapper .DEFAULT_PATH ));
145- if (sortFields .size () < 2 ) {
146- throw new IllegalStateException (
147- String .format (
148- Locale .ROOT ,
149- "data stream [%s] in logsdb mode and with [%s] index setting has only %d sort fields "
150- + "(excluding timestamp), needs at least 2" ,
151- dataStreamName ,
152- IndexSettings .LOGSDB_ROUTE_ON_SORT_FIELDS .getKey (),
153- sortFields .size ()
154- )
155- );
156- }
157- if (settings .hasValue (IndexMetadata .INDEX_ROUTING_PATH .getKey ())) {
158- List <String > routingPaths = settings .getAsList (IndexMetadata .INDEX_ROUTING_PATH .getKey ());
159- if (routingPaths .equals (sortFields ) == false ) {
143+ if (supportFallbackLogsdbRouting .get () == false || licenseService .allowLogsdbRoutingOnSortField (isTemplateValidation )) {
144+ List <String > sortFields = new ArrayList <>(settings .getAsList (IndexSortConfig .INDEX_SORT_FIELD_SETTING .getKey ()));
145+ sortFields .removeIf (s -> s .equals (DataStreamTimestampFieldMapper .DEFAULT_PATH ));
146+ if (sortFields .size () < 2 ) {
160147 throw new IllegalStateException (
161148 String .format (
162149 Locale .ROOT ,
163- "data stream [%s] in logsdb mode and with [%s] index setting has mismatching sort "
164- + "and routing fields, [index.routing_path:%s], [index.sort.fields:%s] " ,
150+ "data stream [%s] in logsdb mode and with [%s] index setting has only %d sort fields "
151+ + "(excluding timestamp), needs at least 2 " ,
165152 dataStreamName ,
166153 IndexSettings .LOGSDB_ROUTE_ON_SORT_FIELDS .getKey (),
167- routingPaths ,
168- sortFields
154+ sortFields .size ()
169155 )
170156 );
171157 }
172- } else {
173- if (settingsBuilder == null ) {
174- settingsBuilder = Settings .builder ();
158+ if (settings .hasValue (IndexMetadata .INDEX_ROUTING_PATH .getKey ())) {
159+ List <String > routingPaths = settings .getAsList (IndexMetadata .INDEX_ROUTING_PATH .getKey ());
160+ if (routingPaths .equals (sortFields ) == false ) {
161+ throw new IllegalStateException (
162+ String .format (
163+ Locale .ROOT ,
164+ "data stream [%s] in logsdb mode and with [%s] index setting has mismatching sort "
165+ + "and routing fields, [index.routing_path:%s], [index.sort.fields:%s]" ,
166+ dataStreamName ,
167+ IndexSettings .LOGSDB_ROUTE_ON_SORT_FIELDS .getKey (),
168+ routingPaths ,
169+ sortFields
170+ )
171+ );
172+ }
173+ } else {
174+ settingsBuilder = getBuilder (settingsBuilder ).putList (INDEX_ROUTING_PATH .getKey (), sortFields );
175175 }
176- settingsBuilder .putList (INDEX_ROUTING_PATH .getKey (), sortFields );
176+ } else {
177+ // Routing on sort fields is not allowed, reset the corresponding index setting.
178+ LOGGER .debug ("creation of index [{}] with logsdb mode and routing on sort fields without it being allowed" , indexName );
179+ settingsBuilder = getBuilder (settingsBuilder ).put (IndexSettings .LOGSDB_ROUTE_ON_SORT_FIELDS .getKey (), false );
177180 }
178181 }
179182 }
180183
181184 return settingsBuilder == null ? Settings .EMPTY : settingsBuilder .build ();
182-
183185 }
184186
185187 record MappingHints (boolean hasSyntheticSourceUsage , boolean sortOnHostName , boolean addHostNameField ) {
@@ -194,6 +196,14 @@ private static IndexMode resolveIndexMode(final String mode) {
194196 return mode != null ? Enum .valueOf (IndexMode .class , mode .toUpperCase (Locale .ROOT )) : null ;
195197 }
196198
199+ // Returned value needs to be reassigned to the passed arg, to track the created builder.
200+ private static Settings .Builder getBuilder (Settings .Builder builder ) {
201+ if (builder == null ) {
202+ return Settings .builder ();
203+ }
204+ return builder ;
205+ }
206+
197207 MappingHints getMappingHints (
198208 String indexName ,
199209 IndexMode templateIndexMode ,
@@ -260,8 +270,8 @@ MappingHints getMappingHints(
260270 || mapperService .mappingLookup ().getMapping ().getRoot ().subobjects () == ObjectMapper .Subobjects .DISABLED ));
261271 boolean sortOnHostName = IndexSettings .LOGSDB_SORT_ON_HOST_NAME .get (indexTemplateAndCreateRequestSettings )
262272 || addHostNameField
263- || (( hostName instanceof NumberFieldMapper nfm && nfm .fieldType ().hasDocValues ())
264- || (hostName instanceof KeywordFieldMapper kfm && kfm .fieldType ().hasDocValues () ));
273+ || (hostName instanceof NumberFieldMapper nfm && nfm .fieldType ().hasDocValues ())
274+ || (hostName instanceof KeywordFieldMapper kfm && kfm .fieldType ().hasDocValues ());
265275 return new MappingHints (hasSyntheticSourceUsage , sortOnHostName , addHostNameField );
266276 }
267277 } catch (AssertionError | Exception e ) {
0 commit comments