|
| 1 | +# Elasticsearch Cursor Rules |
| 2 | + |
| 3 | +You are an AI assistant helping with Elasticsearch development. Follow these specific guidelines for the Elasticsearch codebase. |
| 4 | + |
| 5 | +## Project Structure and Organization |
| 6 | + |
| 7 | +### Main Directories |
| 8 | +- `server/`: Core Elasticsearch server components |
| 9 | +- `libs/`: Internal libraries (not general purpose) |
| 10 | +- `modules/`: Default-shipped features requiring special permissions or dependencies |
| 11 | +- `plugins/`: Officially supported plugins for subset of users |
| 12 | +- `x-pack/`: Commercially licensed code with Elastic License |
| 13 | +- `test/`: Test framework and fixtures |
| 14 | +- `qa/`: Multi-module tests, version compatibility tests, integration tests |
| 15 | +- `docs/`: Project documentation |
| 16 | +- `distribution/`: Build artifacts and packages |
| 17 | + |
| 18 | +### Module Structure |
| 19 | +- Modules are in `modules/` directory, each with their own `build.gradle` |
| 20 | +- Plugins are in `plugins/` directory |
| 21 | +- Use `esplugin` configuration in build.gradle for ES plugins |
| 22 | +- Group modules under `org.elasticsearch.plugin` |
| 23 | + |
| 24 | +## Java Coding Standards |
| 25 | + |
| 26 | +### Formatting (Spotless/Eclipse) |
| 27 | +- **Indentation**: 4 spaces (never tabs) |
| 28 | +- **Line width**: 140 characters |
| 29 | +- **Documentation code blocks**: Max 76 characters (between `// tag::NAME` and `// end::NAME`) |
| 30 | +- Use `./gradlew spotlessApply` to format code |
| 31 | +- Use `./gradlew spotlessJavaCheck` to check formatting |
| 32 | + |
| 33 | +### Imports and Dependencies |
| 34 | +- **Forbidden**: Wildcard imports (`import foo.bar.baz.*`) - will cause build failure |
| 35 | +- Prefer specific imports |
| 36 | +- Use project dependencies like `project(":server")` for internal modules |
| 37 | + |
| 38 | +### Code Style |
| 39 | +- **Boolean expressions**: Use `foo == false` instead of `!foo` for readability |
| 40 | +- Avoid `foo == true`, just use `if (foo)` |
| 41 | +- Use `@SuppressWarnings` sparingly and with minimal scope |
| 42 | +- Use `Types.forciblyCast` utility only as last resort for type coercion |
| 43 | + |
| 44 | +### License Headers |
| 45 | +For server/libs/modules (non-x-pack): |
| 46 | +```java |
| 47 | +/* |
| 48 | + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one |
| 49 | + * or more contributor license agreements. Licensed under the "Elastic License |
| 50 | + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side |
| 51 | + * Public License v 1"; you may not use this file except in compliance with, at |
| 52 | + * your election, the "Elastic License 2.0", the "GNU Affero General Public |
| 53 | + * License v3.0 only", or the "Server Side Public License, v 1". |
| 54 | + */ |
| 55 | +``` |
| 56 | + |
| 57 | +For x-pack: |
| 58 | +```java |
| 59 | +/* |
| 60 | + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one |
| 61 | + * or more contributor license agreements. Licensed under the Elastic License |
| 62 | + * 2.0; you may not use this file except in compliance with the Elastic License |
| 63 | + * 2.0. |
| 64 | + */ |
| 65 | +``` |
| 66 | + |
| 67 | +## Package Naming Conventions |
| 68 | + |
| 69 | +### Plugin APIs |
| 70 | +- Root package: `org.elasticsearch.plugin` |
| 71 | +- Specialized APIs: `org.elasticsearch.plugin.analysis` |
| 72 | +- Internal packages: `org.elasticsearch.plugin.analysis.internal` |
| 73 | + |
| 74 | +### General Guidelines |
| 75 | +- Follow existing package structures in the codebase |
| 76 | +- Keep internal implementation details in `internal` subpackages |
| 77 | +- Use consistent naming across similar components |
| 78 | + |
| 79 | +## Testing Framework and Conventions |
| 80 | + |
| 81 | +### Test Base Classes (Prefer in this order) |
| 82 | +1. **Unit Tests**: `ESTestCase` - Base class for all tests, prefer for pure unit testing |
| 83 | +2. **Single Node**: `ESSingleNodeTestCase` - Lightweight single node cluster |
| 84 | +3. **Integration**: `ESRestTestCase` - REST API integration tests (preferred for integration) |
| 85 | +4. **Internal Integration**: `ESIntegTestCase` - Internal state verification (use sparingly) |
| 86 | +5. **YAML Tests**: `ESClientYamlSuiteTestCase` - For YAML-based REST tests |
| 87 | + |
| 88 | +### Test Guidelines |
| 89 | +- **Prefer unit tests** over integration tests when possible |
| 90 | +- Use REST tests for integration testing in realistic setups |
| 91 | +- Write tests that are easy to reproduce and understand |
| 92 | +- Use randomized testing for parameters that don't affect behavior |
| 93 | +- **Don't use randomization for coverage** - write explicit tests for different code paths |
| 94 | + |
| 95 | +### Test Commands |
| 96 | +- Run all tests: `./gradlew check` |
| 97 | +- Run specific test: `./gradlew :server:test --tests org.elasticsearch.package.ClassName` |
| 98 | +- Run with seed: `./gradlew test -Dtests.seed=DEADBEEF` |
| 99 | +- Debug tests: `./gradlew :server:test --debug-jvm` |
| 100 | +- REST tests: `./gradlew :rest-api-spec:yamlRestTest` |
| 101 | + |
| 102 | +### FIPS Mode Testing |
| 103 | +Use this pattern to skip tests in FIPS mode: |
| 104 | +```java |
| 105 | +assumeFalse("Justification why this cannot be run in FIPS mode", inFipsJvm()); |
| 106 | +``` |
| 107 | + |
| 108 | +## Documentation and Javadoc |
| 109 | + |
| 110 | +### Javadoc Requirements |
| 111 | +- **Always add Javadoc to new code** |
| 112 | +- **New classes and interfaces** must have class-level Javadoc |
| 113 | +- **Public methods** must have Javadoc |
| 114 | +- **Abstract methods** must have Javadoc |
| 115 | +- Document the "why", not the "how" |
| 116 | +- Don't document trivial/obvious functionality |
| 117 | +- Use `@link` for references, prefer over `@see` |
| 118 | +- Add examples when reasonably possible |
| 119 | + |
| 120 | +### Package Documentation |
| 121 | +- Add `package-info.java` for new packages with explanation |
| 122 | +- Reference parent packages when appropriate |
| 123 | +- Document purpose, caveats, and usage examples |
| 124 | + |
| 125 | +## Gradle Build System |
| 126 | + |
| 127 | +### Dependencies |
| 128 | +- `implementation`: Internal dependencies not exposed to dependent projects |
| 129 | +- `api`: External API dependencies |
| 130 | +- `compileOnly`: Provided at runtime (e.g., server for plugins) |
| 131 | +- `testImplementation`: Test-only dependencies |
| 132 | + |
| 133 | +### Plugin Development |
| 134 | +```gradle |
| 135 | +apply plugin: 'elasticsearch.internal-es-plugin' |
| 136 | + |
| 137 | +esplugin { |
| 138 | + name = project.name |
| 139 | +} |
| 140 | +``` |
| 141 | + |
| 142 | +## REST API Conventions |
| 143 | + |
| 144 | +### URL Design |
| 145 | +- **Use singular nouns** (not plurals): `/_ingest/pipeline/{id}` not `/_ingest/pipelines/{id}` |
| 146 | +- Follow existing patterns in the codebase |
| 147 | +- Maintain consistency with established endpoints |
| 148 | + |
| 149 | +## Logging Guidelines |
| 150 | + |
| 151 | +### Logger Setup |
| 152 | +```java |
| 153 | +private static final Logger logger = LogManager.getLogger(ClassName.class); |
| 154 | +``` |
| 155 | + |
| 156 | +### Logging Levels |
| 157 | +- **TRACE**: Very verbose, development debugging |
| 158 | +- **DEBUG**: Production debugging, limited volume |
| 159 | +- **INFO**: Important events, user-facing terminology, factual language |
| 160 | +- **WARN**: Problems requiring investigation, actionable items |
| 161 | +- **ERROR**: Critical failures, very rare usage |
| 162 | + |
| 163 | +### Log Message Format |
| 164 | +```java |
| 165 | +logger.debug("operation failed [{}] times in [{}]ms", failureCount, elapsedMillis); |
| 166 | +logger.debug(() -> "expensive computation [" + expensiveMethod() + "]"); |
| 167 | +``` |
| 168 | + |
| 169 | +## Performance and Security |
| 170 | + |
| 171 | +### Performance Considerations |
| 172 | +- Use appropriate data structures |
| 173 | +- Consider memory usage in high-throughput paths |
| 174 | +- Profile performance-critical changes with Rally |
| 175 | +- Document unexpected performance characteristics in Javadoc |
| 176 | + |
| 177 | +### Security |
| 178 | +- Validate all inputs |
| 179 | +- Use appropriate authentication/authorization |
| 180 | +- Follow security best practices for REST endpoints |
| 181 | +- Consider FIPS 140-2 compliance requirements |
| 182 | + |
| 183 | +## Build and Development Workflow |
| 184 | + |
| 185 | +### Running Elasticsearch |
| 186 | +- Development: `./gradlew run` |
| 187 | +- With debug: `./gradlew run --debug-jvm` |
| 188 | +- Different distribution: `./gradlew run -Drun.distribution=oss` |
| 189 | +- Multiple nodes: Configure `numberOfNodes` in build script |
| 190 | + |
| 191 | +### Common Commands |
| 192 | +- Format code: `./gradlew spotlessApply` |
| 193 | +- Check formatting: `./gradlew spotlessJavaCheck` |
| 194 | +- Run precommit: `./gradlew precommit` |
| 195 | +- Build distributions: `./gradlew assemble` |
| 196 | +- Clean: `./gradlew clean` |
| 197 | + |
| 198 | +## Metrics and Monitoring |
| 199 | + |
| 200 | +### Naming Guidelines |
| 201 | +- Use hierarchical naming with dots as separators: `es.indices.docs.deleted.total` |
| 202 | +- Elements in lowercase with underscores: `blob_cache` |
| 203 | +- Start with `es` root prefix |
| 204 | +- Follow existing prefixes and naming patterns |
| 205 | +- Build names that make sense when truncated at any segment |
| 206 | + |
| 207 | +## Version Compatibility |
| 208 | + |
| 209 | +### BWC Testing |
| 210 | +- Test against compatible versions |
| 211 | +- Use `./gradlew bwcTest` for backward compatibility tests |
| 212 | +- Consider version compatibility when making changes |
| 213 | +- Update version constants appropriately |
| 214 | + |
| 215 | +## Error Handling |
| 216 | + |
| 217 | +### Exception Handling |
| 218 | +- Provide meaningful error messages |
| 219 | +- Log appropriate context for debugging |
| 220 | +- Use specific exception types |
| 221 | +- Handle errors gracefully in user-facing code |
| 222 | +- Include relevant metadata in log messages |
| 223 | + |
| 224 | +Remember to follow the existing patterns in the codebase and maintain consistency with established conventions. When in doubt, look for similar implementations in the existing code for guidance. |
0 commit comments