Extending Elasticsearch - Writing plugins, fast and easy!

A presentation at JUG Essen in June 2019 in Essen, Germany by Alexander Reelsen

Slide 1

Slide 1

Extending Elasticsearch Writing plugins, fast and easy! Alexander Reelsen @spinscale alex@elastic.co

Slide 2

Slide 2

Elasticsearch in 10 seconds Search Engine (FTS, Analytics, Geo), real-time Distributed, scalable, highly available, resilient Interface: HTTP & JSON Centrepiece of the Elastic Stack (Kibana, Logstash, Beats, APM, ML, App/Site/Enterprise Search) Uneducated guess: Tens of thousands of clusters worldwide, hundreds of thousands of instances

Slide 3

Slide 3

Agenda Overview Building Testing Releasing Extension points

Slide 4

Slide 4

Overview Requirements, gotchas and some details

Slide 5

Slide 5

Overview Plugins are zip files own jars/dependencies loaded with its own classloader own security permissions

Slide 6

Slide 6

Security Manager? Permissions? But why?! Sandbox your java application Prevent certain calls by your application Policy file grants permissions FilePermission (read, write) SocketPermission (connect, listen, accept) URLPermission, PropertyPermission, …

Slide 7

Slide 7

Security Manager? Permissions? But why?! Each plugin needs to be packaged with a policy that grants certain operations

Slide 8

Slide 8

Building gradle clean assemble

Slide 9

Slide 9

Overview A plugin needs to be released for an Elasticsearch patch release Use the gradle plugin! Batteries included, lots of them Integration tests, license checks, checkstyle, notice files

Slide 10

Slide 10

Testing gradle clean check

Slide 11

Slide 11

Overview Unit tests: ESTestCase Integration tests: YAML Download ES, install plugin, start ES, run tests against HTTP

Slide 12

Slide 12

ESTestCase Randomized testing Logger Thread leak detector Deprecation warnings detection Test method names have to begin with void test…() assertBusy/awaitBusy

Slide 13

Slide 13

Extension points class MyPlugin extends Plugin

Slide 14

Slide 14

Overview ActionPlugin: Implement own actions, REST endpoints AnalysisPlugin: Add custom parts to analysis chain ClusterPlugin: Implement own shard allocation logic DiscoveryPlugin: Add (often API based) host discovery IngestPlugin: Custom ingest processors MapperPlugin: Custom mapping data types NetworkPlugin: Network implementations (i.e. netty replacement) RepositoryPlugin: Snapshot/restore repository implementations ScriptPlugin: Script Engines, Script Contexts SearchPlugin: Queries, Highlighter, Suggester, Aggregations, Rescoring, Search Extensions ReloadablePlugin: Ensure a plugin can reload its state

Slide 15

Slide 15

Overview main class: org.elasticsearch.plugins.Plugin settings registration & filter custom cluster state metadata cluster state listener index modules (search listener, index event listener)

Slide 16

Slide 16

Plugin Loading [INFO ][o.e.p.PluginsService] [node] loaded module [lang-mustache]

Slide 17

Slide 17

Overview PluginService check for modules & plugins directory check jar hell check version create classloader reload lucene SPI load Plugin class instantiate Plugin class

Slide 18

Slide 18

Show me the code!

Slide 19

Slide 19

Ingest lang-detect processor PUT _ingest/pipeline/langdetect-pipeline { “processors”: [ { “langdetect” : { “field” : “my_field”, “target_field” : “language” } } ] }

Slide 20

Slide 20

Ingest lang-detect processor PUT /my-index/my-type/1?pipeline=langdetect-pipeline { “my_field” : “This is hopefully an english text, that will be detected.” } GET /my-index/my-type/1 { “my_field” : “This is hopefully an english text, that will be detected.”, “language”: “en” }

Slide 21

Slide 21

Custom query parser Ecommerce use-case clean data non expert searches

Slide 22

Slide 22

Custom query parser nike running hoodie xl

Slide 23

Slide 23

Custom query parser nike running hoodie xl

Slide 24

Slide 24

Custom query parser brand } } nike running hoodie xl size

Slide 25

Slide 25

Custom query parser PUT my_products { “settings”: { “index.queryparser.values” : { “brands” : [ “nike”, “adidas”, “puma”, “salomon” ], “size” : [ “m”, “xl”, “l”, “s”, “xs”, “xxs”, “xxl” ] } } }

Slide 26

Slide 26

Custom query parser GET my_products/_search { “query”: { “custom” : { “title”: “nike running hoodie XL” } } }

Slide 27

Slide 27

DEMO

Slide 28

Slide 28

Summary When is your plugin ready again?

Slide 29

Slide 29

Summary Writing own plugins is not that hard Testing plugins is incredibly easy with gradle Release via github or sonatype

Slide 30

Slide 30

Thanks for listening! Questions? Alexander Reelsen @spinscale alex@elastic.co

Slide 31

Slide 31

Resources https://github.com/elastic/elasticsearch/ https://github.com/elastic/elasticsearch/tree/7.1/plugins/examples https://github.com/spinscale/elasticsearch-ingest-opennlp https://github.com/spinscale/elasticsearch-ingest-langdetect https://github.com/spinscale/cookiecutter-elasticsearch-ingest-processor

Slide 32

Slide 32

Thanks for listening! Questions? Alexander Reelsen @spinscale alex@elastic.co