forked from elastic/built-docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinput-new-plugin.html
1150 lines (1088 loc) · 52.6 KB
/
input-new-plugin.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="UTF-8">
<title>How to write a Logstash input plugin | Logstash Reference [8.6] | Elastic</title>
<meta class="elastic" name="content" content="How to write a Logstash input plugin | Logstash Reference [8.6]">
<link rel="home" href="index.html" title="Logstash Reference [8.6]"/>
<link rel="up" href="contributing-to-logstash.html" title="Contributing to Logstash"/>
<link rel="prev" href="contributing-to-logstash.html" title="Contributing to Logstash"/>
<link rel="next" href="codec-new-plugin.html" title="How to write a Logstash codec plugin"/>
<meta class="elastic" name="product_version" content="8.6"/>
<meta class="elastic" name="product_name" content="Logstash"/>
<meta class="elastic" name="website_area" content="documentation"/>
<meta name="DC.type" content="Learn/Docs/Logstash/Reference/8.6"/>
<meta name="DC.subject" content="Logstash"/>
<meta name="DC.identifier" content="8.6"/>
<meta name="robots" content="noindex,nofollow"/>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.optimizely.com/js/18132920325.js"></script>
<link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png">
<link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="/android-chrome-192x192.png" sizes="192x192">
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
<link rel="manifest" href="/manifest.json">
<meta name="apple-mobile-web-app-title" content="Elastic">
<meta name="application-name" content="Elastic">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/mstile-144x144.png">
<meta name="theme-color" content="#ffffff">
<meta name="naver-site-verification" content="936882c1853b701b3cef3721758d80535413dbfd" />
<meta name="yandex-verification" content="d8a47e95d0972434" />
<meta name="localized" content="true" />
<meta name="st:robots" content="follow,index" />
<meta property="og:image" content="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt280217a63b82a734/6202d3378b1f312528798412/elastic-logo.svg" />
<meta property="og:image:width" content="500" />
<meta property="og:image:height" content="172" />
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link rel="apple-touch-icon-precomposed" sizes="64x64" href="/favicon_64x64_16bit.png">
<link rel="apple-touch-icon-precomposed" sizes="32x32" href="/favicon_32x32.png">
<link rel="apple-touch-icon-precomposed" sizes="16x16" href="/favicon_16x16.png">
<!-- Give IE8 a fighting chance -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<link rel="stylesheet" type="text/css" href="/guide/static/styles.css" />
</head>
<!--© 2015-2022 Elasticsearch B.V. -->
<!-- All Elastic documentation is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License. -->
<!-- http://creativecommons.org/licenses/by-nc-nd/4.0/ -->
<body>
<!-- Google Tag Manager -->
<script>dataLayer = [];</script><noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-58RLH5" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= '//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-58RLH5');</script>
<!-- End Google Tag Manager -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-12395217-16"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-12395217-16');
</script>
<!-- Google Tag Manager for GA4 -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-KNJMG2M');</script>
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-KNJMG2M" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager for GA4-->
<div id='elastic-nav' style="display:none;"></div>
<script src='https://www.elastic.co/elastic-nav.js'></script>
<div class="main-container">
<section id="content" >
<div class="content-wrapper">
<section id="guide" lang="en">
<div class="container-fluid">
<div class="row pb-3">
<div class="col-12 order-2 col-md-4 order-md-1 col-lg-3 h-almost-full-md sticky-top-md" id="left_col">
<!-- The TOC is appended here -->
</div>
<div class="col-12 order-1 col-md-8 order-md-2 col-lg-7 order-lg-2 guide-section" id="middle_col">
<!-- start body -->
<div class="page_header">
<strong>IMPORTANT</strong>: No additional bug fixes or documentation updates
will be released for this version. For the latest information, see the
<a href="../current/index.html">current release documentation</a>.
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="/guide/">Elastic Docs</a></span>
<span class="chevron-right">›</span><span class="breadcrumb-link"><a href="index.html">Logstash Reference [8.6]</a></span>
<span class="chevron-right">›</span><span class="breadcrumb-link"><a href="contributing-to-logstash.html">Contributing to Logstash</a></span>
</div>
<div class="navheader">
<span class="prev">
<a href="contributing-to-logstash.html">« Contributing to Logstash</a>
</span>
<span class="next">
<a href="codec-new-plugin.html">How to write a Logstash codec plugin »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title"><a id="input-new-plugin"></a>How to write a Logstash input plugin</h2>
</div></div></div>
<p>To develop a new input for Logstash, build a self-contained Ruby gem
whose source code lives in its own GitHub repository. The Ruby gem can then be
hosted and shared on RubyGems.org. You can use the example input
implementation as a starting point. (If you’re unfamiliar with
Ruby, you can find an excellent quickstart guide at
<a href="https://www.ruby-lang.org/en/documentation/quickstart/" class="ulink" target="_top">https://www.ruby-lang.org/en/documentation/quickstart/</a>.)</p>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_get_started"></a>Get started</h3>
</div></div></div>
<p>Let’s step through creating an input plugin using the <a href="https://github.com/logstash-plugins/logstash-input-example/" class="ulink" target="_top">example input plugin</a>.</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_create_a_github_repo_for_your_new_plugin"></a>Create a GitHub repo for your new plugin</h4>
</div></div></div>
<p>Each Logstash plugin lives in its own GitHub repository. To create a new repository for your plugin:</p>
<div class="olist orderedlist">
<ol class="orderedlist">
<li class="listitem">
Log in to GitHub.
</li>
<li class="listitem">
Click the <span class="strong strong"><strong>Repositories</strong></span> tab. You’ll see a list of other repositories you’ve forked or contributed to.
</li>
<li class="listitem">
Click the green <span class="strong strong"><strong>New</strong></span> button in the upper right.
</li>
<li class="listitem">
<p>Specify the following settings for your new repo:</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<span class="strong strong"><strong>Repository name</strong></span> — a unique name of the form <code class="literal">logstash-input-pluginname</code>.
</li>
<li class="listitem">
<span class="strong strong"><strong>Public or Private</strong></span> — your choice, but the repository must be Public if you want to submit it as an official plugin.
</li>
<li class="listitem">
<span class="strong strong"><strong>Initialize this repository with a README</strong></span> — enables you to immediately clone the repository to your computer.
</li>
</ul>
</div>
</li>
<li class="listitem">
Click <span class="strong strong"><strong>Create Repository</strong></span>.
</li>
</ol>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_use_the_plugin_generator_tool"></a>Use the plugin generator tool</h4>
</div></div></div>
<p>You can create your own Logstash plugin in seconds! The <code class="literal">generate</code> subcommand of <code class="literal">bin/logstash-plugin</code> creates the foundation
for a new Logstash plugin with templatized files. It creates the correct directory structure, gemspec files, and dependencies so you
can start adding custom code to process data with Logstash.</p>
<p>For more information, see <a class="xref" href="plugin-generator.html" title="Generating plugins">Generating plugins</a></p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_copy_the_input_code"></a>Copy the input code</h4>
</div></div></div>
<p>Alternatively, you can use the examples repo we host on github.com</p>
<div class="olist orderedlist">
<ol class="orderedlist">
<li class="listitem">
<p><span class="strong strong"><strong>Clone your plugin.</strong></span> Replace <code class="literal">GITUSERNAME</code> with your github username, and
<code class="literal">MYPLUGINNAME</code> with your plugin name.</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<p><code class="literal">git clone https://github.com/GITUSERNAME/logstash-</code><code class="literal">input-MYPLUGINNAME.git</code></p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
alternately, via ssh: <code class="literal">git clone [email protected]:GITUSERNAME/logstash</code><code class="literal">-input-MYPLUGINNAME.git</code>
</li>
</ul>
</div>
</li>
<li class="listitem">
<code class="literal">cd logstash-input-MYPLUGINNAME</code>
</li>
</ul>
</div>
</li>
<li class="listitem">
<p><span class="strong strong"><strong>Clone the input plugin example and copy it to your plugin branch.</strong></span></p>
<p>You don’t want to include the example .git directory or its contents, so delete
it before you copy the example.</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">cd /tmp</code>
</li>
<li class="listitem">
<code class="literal">git clone https://github.com/logstash-plugins/logstash</code><code class="literal">-input-example.git</code>
</li>
<li class="listitem">
<code class="literal">cd logstash-input-example</code>
</li>
<li class="listitem">
<code class="literal">rm -rf .git</code>
</li>
<li class="listitem">
<code class="literal">cp -R * /path/to/logstash-input-mypluginname/</code>
</li>
</ul>
</div>
</li>
<li class="listitem">
<p><span class="strong strong"><strong>Rename the following files to match the name of your plugin.</strong></span></p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">logstash-input-example.gemspec</code>
</li>
<li class="listitem">
<code class="literal">example.rb</code>
</li>
<li class="listitem">
<p><code class="literal">example_spec.rb</code></p>
<div class="pre_wrapper lang-txt">
<pre class="programlisting prettyprint lang-txt">cd /path/to/logstash-input-mypluginname
mv logstash-input-example.gemspec logstash-input-mypluginname.gemspec
mv lib/logstash/inputs/example.rb lib/logstash/inputs/mypluginname.rb
mv spec/inputs/example_spec.rb spec/inputs/mypluginname_spec.rb</pre>
</div>
</li>
</ul>
</div>
</li>
</ol>
</div>
<p>Your file structure should look like this:</p>
<div class="pre_wrapper lang-txt">
<pre class="programlisting prettyprint lang-txt">$ tree logstash-input-mypluginname
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── lib
│ └── logstash
│ └── inputs
│ └── mypluginname.rb
├── logstash-input-mypluginname.gemspec
└── spec
└── inputs
└── mypluginname_spec.rb</pre>
</div>
<p>For more information about the Ruby gem file structure and an excellent
walkthrough of the Ruby gem creation process, see
<a href="http://timelessrepo.com/making-ruby-gems" class="ulink" target="_top">http://timelessrepo.com/making-ruby-gems</a></p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_see_what_your_plugin_looks_like"></a>See what your plugin looks like</h4>
</div></div></div>
<p>Before we dive into the details, open up the plugin file in your favorite text editor
and take a look.</p>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby">require "logstash/inputs/base"
require "logstash/namespace"
require "stud/interval"
require "socket" # for Socket.gethostname
# Add any asciidoc formatted documentation here
# Generate a repeating message.
#
# This plugin is intended only as an example.
class LogStash::Inputs::Example < LogStash::Inputs::Base
config_name "example"
# If undefined, Logstash will complain, even if codec is unused.
default :codec, "plain"
# The message string to use in the event.
config :message, :validate => :string, :default => "Hello World!"
# Set how frequently messages should be sent.
#
# The default, `1`, means send a message every second.
config :interval, :validate => :number, :default => 1
public
def register
@host = Socket.gethostname
end # def register
def run(queue)
Stud.interval(@interval) do
event = LogStash::Event.new("message" => @message, "host" => @host)
decorate(event)
queue << event
end # loop
end # def run
end # class LogStash::Inputs::Example</pre>
</div>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_coding_input_plugins"></a>Coding input plugins</h3>
</div></div></div>
<p>Now let’s take a line-by-line look at the example plugin.</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_require_statements"></a><code class="literal">require</code> Statements</h4>
</div></div></div>
<p>Logstash input plugins require parent classes defined in
<code class="literal">logstash/inputs/base</code> and logstash/namespace:</p>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby">require "logstash/inputs/base"
require "logstash/namespace"</pre>
</div>
<p>Of course, the plugin you build may depend on other code, or even gems. Just put
them here along with these Logstash dependencies.</p>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_plugin_body"></a>Plugin Body</h3>
</div></div></div>
<p>Let’s go through the various elements of the plugin itself.</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_class_declaration"></a><code class="literal">class</code> Declaration</h4>
</div></div></div>
<p>The input plugin class should be a subclass of
<code class="literal">LogStash::Inputs::Base</code>:</p>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby">class LogStash::Inputs::Example < LogStash::Inputs::Base</pre>
</div>
<p>The class name should closely mirror the plugin name, for example:</p>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby">LogStash::Inputs::Example</pre>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_config_name"></a><code class="literal">config_name</code></h4>
</div></div></div>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby"> config_name "example"</pre>
</div>
<p>This is the name your plugin will call inside the input configuration
block.</p>
<p>If you set <code class="literal">config_name "example"</code> in your plugin code,
the corresponding Logstash configuration block would need to look like this:</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">input {
example {...}
}</pre>
</div>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_configuration_parameters"></a>Configuration Parameters</h3>
</div></div></div>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby"> config :variable_name, :validate => :variable_type, :default => "Default value", :required => boolean, :deprecated => boolean, :obsolete => string</pre>
</div>
<p>The configuration, or <code class="literal">config</code> section allows you to define as many (or as few)
parameters as are needed to enable Logstash to process events.</p>
<p>There are several configuration attributes:</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">:validate</code> - allows you to enforce passing a particular data type to Logstash
for this configuration option, such as <code class="literal">:string</code>, <code class="literal">:password</code>, <code class="literal">:boolean</code>,
<code class="literal">:number</code>, <code class="literal">:array</code>, <code class="literal">:hash</code>, <code class="literal">:path</code> (a file-system path), <code class="literal">uri</code>, <code class="literal">:codec</code> (since
1.2.0), <code class="literal">:bytes</code>. Note that this also works as a coercion
in that if I specify "true" for boolean (even though technically a string), it
will become a valid boolean in the config. This coercion works for the
<code class="literal">:number</code> type as well where "1.2" becomes a float and "22" is an integer.
</li>
<li class="listitem">
<code class="literal">:default</code> - lets you specify a default value for a parameter
</li>
<li class="listitem">
<code class="literal">:required</code> - whether or not this parameter is mandatory (a Boolean <code class="literal">true</code> or
</li>
<li class="listitem">
<code class="literal">:list</code> - whether or not this value should be a list of values. Will typecheck the list members, and convert scalars to one element lists. Note that this mostly obviates the array type, though if you need lists of complex objects that will be more suitable.
<code class="literal">false</code>)
</li>
<li class="listitem">
<code class="literal">:deprecated</code> - informational (also a Boolean <code class="literal">true</code> or <code class="literal">false</code>)
</li>
<li class="listitem">
<code class="literal">:obsolete</code> - used to declare that a given setting has been removed and is no longer functioning. The idea is to provide an informed upgrade path to users who are still using a now-removed setting.
</li>
</ul>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_plugin_methods"></a>Plugin Methods</h3>
</div></div></div>
<p>Logstash inputs must implement two main methods: <code class="literal">register</code> and <code class="literal">run</code>.</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_register_method"></a><code class="literal">register</code> Method</h4>
</div></div></div>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby"> public
def register
end # def register</pre>
</div>
<p>The Logstash <code class="literal">register</code> method is like an <code class="literal">initialize</code> method. It was originally
created to enforce having <code class="literal">super</code> called, preventing headaches for newbies.
(Note: It may go away in favor of <code class="literal">initialize</code>, in conjunction with some
enforced testing to ensure <code class="literal">super</code> is called.)</p>
<p><code class="literal">public</code> means the method can be called anywhere, not just within the class.
This is the default behavior for methods in Ruby, but it is specified explicitly
here anyway.</p>
<p>You can also assign instance variables here (variables prepended by <code class="literal">@</code>).
Configuration variables are now in scope as instance variables, like <code class="literal">@message</code></p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_run_method"></a><code class="literal">run</code> Method</h4>
</div></div></div>
<p>The example input plugin has the following <code class="literal">run</code> Method:</p>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby"> def run(queue)
Stud.interval(@interval) do
event = LogStash::Event.new("message" => @message, "host" => @host)
decorate(event)
queue << event
end # loop
end # def run</pre>
</div>
<p>The <code class="literal">run</code> method is where a stream of data from an input becomes an event.</p>
<p>The stream can be plain or generated as with the
<a href="https://github.com/logstash-plugins/logstash-input-heartbeat/blob/main/lib/logstash/inputs/heartbeat.rb#L43-L61" class="ulink" target="_top">heartbeat</a>
input plugin. In these cases, though no codec is used,
<a href="https://github.com/logstash-plugins/logstash-input-heartbeat/blob/main/lib/logstash/inputs/heartbeat.rb#L17" class="ulink" target="_top">a default codec</a>
must be set in the code to avoid errors.</p>
<p>Here’s another example <code class="literal">run</code> method:</p>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby"> def run(queue)
while true
begin
# Based on some testing, there is no way to interrupt an IO.sysread nor
# IO.select call in JRuby.
data = $stdin.sysread(16384)
@codec.decode(data) do |event|
decorate(event)
event.set("host", @host) if !event.include?("host")
queue << event
end
rescue IOError, EOFError, LogStash::ShutdownSignal
# stdin closed or a requested shutdown
break
end
end # while true
finished
end # def run</pre>
</div>
<p>In this example, the <code class="literal">data</code> is being sent to the codec defined in the
configuration block to <code class="literal">decode</code> the data stream and return an event.</p>
<p>In both examples, the resulting <code class="literal">event</code> is passed to the <code class="literal">decorate</code> method:</p>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby"> decorate(event)</pre>
</div>
<p>This applies any tags you might have set in the input configuration block. For
example, <code class="literal">tags => ["tag1", "tag2"]</code>.</p>
<p>Also in both examples, the <code class="literal">event</code>, after being "decorated," is appended to the
queue:</p>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby"> queue << event</pre>
</div>
<p>This inserts the event into the pipeline.</p>
<div class="tip admon">
<div class="icon"></div>
<div class="admon_content">
<p>Because input plugins can range from simple to complex, it is helpful to see
more examples of how they have been created:</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<a href="https://github.com/logstash-plugins/logstash-input-syslog/blob/main/lib/logstash/inputs/syslog.rb" class="ulink" target="_top">syslog</a>
</li>
<li class="listitem">
<a href="https://github.com/logstash-plugins/logstash-input-zeromq/blob/main/lib/logstash/inputs/zeromq.rb" class="ulink" target="_top">zeromq</a>
</li>
<li class="listitem">
<a href="https://github.com/logstash-plugins/logstash-input-stdin/blob/main/lib/logstash/inputs/stdin.rb" class="ulink" target="_top">stdin</a>
</li>
<li class="listitem">
<a href="https://github.com/logstash-plugins/logstash-input-tcp/blob/main/lib/logstash/inputs/tcp.rb" class="ulink" target="_top">tcp</a>
</li>
</ul>
</div>
<p>There are many more more examples in the <a href="https://github.com/logstash-plugins?query=logstash-input" class="ulink" target="_top">logstash-plugin github repository</a>.</p>
</div>
</div>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_building_the_plugin"></a>Building the Plugin</h3>
</div></div></div>
<p>At this point in the process you have coded your plugin and are ready to build
a Ruby Gem from it. The following information will help you complete the process.</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_external_dependencies"></a>External dependencies</h4>
</div></div></div>
<p>A <code class="literal">require</code> statement in Ruby is used to include necessary code. In some cases
your plugin may require additional files. For example, the collectd plugin
<a href="https://github.com/logstash-plugins/logstash-codec-collectd/blob/main/lib/logstash/codecs/collectd.rb#L148" class="ulink" target="_top">uses</a>
the <code class="literal">types.db</code> file provided by collectd. In the main directory of your plugin,
a file called <code class="literal">vendor.json</code> is where these files are described.</p>
<p>The <code class="literal">vendor.json</code> file contains an array of JSON objects, each describing a file
dependency. This example comes from the
<a href="https://github.com/logstash-plugins/logstash-codec-collectd/blob/main/vendor.json" class="ulink" target="_top">collectd</a>
codec plugin:</p>
<div class="pre_wrapper lang-txt">
<pre class="programlisting prettyprint lang-txt">[{
"sha1": "a90fe6cc53b76b7bdd56dc57950d90787cb9c96e",
"url": "http://collectd.org/files/collectd-5.4.0.tar.gz",
"files": [ "/src/types.db" ]
}]</pre>
</div>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">sha1</code> is the sha1 signature used to verify the integrity of the file
referenced by <code class="literal">url</code>.
</li>
<li class="listitem">
<code class="literal">url</code> is the address from where Logstash will download the file.
</li>
<li class="listitem">
<code class="literal">files</code> is an optional array of files to extract from the downloaded file.
Note that while tar archives can use absolute or relative paths, treat them as
absolute in this array. If <code class="literal">files</code> is not present, all files will be
uncompressed and extracted into the vendor directory.
</li>
</ul>
</div>
<p>Another example of the <code class="literal">vendor.json</code> file is the
<a href="https://github.com/logstash-plugins/logstash-filter-geoip/blob/main/vendor.json" class="ulink" target="_top"><code class="literal">geoip</code> filter</a></p>
<p>The process used to download these dependencies is to call <code class="literal">rake vendor</code>. This
will be discussed further in the testing section of this document.</p>
<p>Another kind of external dependency is on jar files. This will be described
in the "Add a <code class="literal">gemspec</code> file" section.</p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_deprecated_features"></a>Deprecated features</h4>
</div></div></div>
<p>As a plugin evolves, an option or feature may no longer serve the
intended purpose, and the developer may want to <em>deprecate</em> its usage.
Deprecation warns users about the option’s status, so they aren’t caught by
surprise when it is removed in a later release.</p>
<p>Logstash 7.6 introduced a <em>deprecation logger</em> to make handling those situations
easier. You can use the
<a href="https://github.com/logstash-plugins/logstash-mixin-deprecation_logger_support" class="ulink" target="_top">adapter</a>
to ensure that your plugin can use the deprecation logger while still supporting
older versions of Logstash. See the
<a href="https://github.com/logstash-plugins/logstash-mixin-deprecation_logger_support/blob/main/README.md" class="ulink" target="_top">readme</a>
for more information and for instructions on using the adapter.</p>
<p>Deprecations are noted in the <code class="literal">logstash-deprecation.log</code> file in the
<code class="literal">log</code> directory.</p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_add_a_gemfile"></a>Add a Gemfile</h4>
</div></div></div>
<p>Gemfiles allow Ruby’s Bundler to maintain the dependencies for your plugin.
Currently, all we’ll need is the Logstash gem, for testing, but if you require
other gems, you should add them in here.</p>
<div class="tip admon">
<div class="icon"></div>
<div class="admon_content">
<p>See <a href="http://bundler.io/gemfile.html" class="ulink" target="_top">Bundler’s Gemfile page</a> for more details.</p>
</div>
</div>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby">source 'https://rubygems.org'
gemspec
gem "logstash", :github => "elastic/logstash", :branch => "8.6"</pre>
</div>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_add_a_gemspec_file"></a>Add a <code class="literal">gemspec</code> file</h3>
</div></div></div>
<p>Gemspecs define the Ruby gem which will be built and contain your plugin.</p>
<div class="tip admon">
<div class="icon"></div>
<div class="admon_content">
<p>More information can be found on the
<a href="http://guides.rubygems.org/specification-reference/" class="ulink" target="_top">Rubygems Specification page</a>.</p>
</div>
</div>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby">Gem::Specification.new do |s|
s.name = 'logstash-input-example'
s.version = '0.1.0'
s.licenses = ['Apache License (2.0)']
s.summary = "This input does x, y, z in Logstash"
s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
s.authors = ["Elastic"]
s.email = '[email protected]'
s.homepage = "http://www.elastic.co/guide/en/logstash/current/index.html"
s.require_paths = ["lib"]
# Files
s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
# Tests
s.test_files = s.files.grep(%r{^(test|spec|features)/})
# Special flag to let us know this is actually a logstash plugin
s.metadata = { "logstash_plugin" => "true", "logstash_group" => "input" }
# Gem dependencies
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
s.add_development_dependency 'logstash-devutils'
end</pre>
</div>
<p>It is appropriate to change these values to fit your plugin. In particular,
<code class="literal">s.name</code> and <code class="literal">s.summary</code> should reflect your plugin’s name and behavior.</p>
<p><code class="literal">s.licenses</code> and <code class="literal">s.version</code> are also important and will come into play when
you are ready to publish your plugin.</p>
<p>Logstash and all its plugins are licensed under
<a href="https://github.com/elastic/logstash/blob/main/LICENSE.txt" class="ulink" target="_top">Apache License, version 2 ("ALv2")</a>.
If you make your plugin publicly available via <a href="http://rubygems.org" class="ulink" target="_top">RubyGems.org</a>,
please make sure to have this line in your gemspec:</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">s.licenses = ['Apache License (2.0)']</code>
</li>
</ul>
</div>
<p>The gem version, designated by <code class="literal">s.version</code>, helps track changes to plugins over
time. You should use <a href="http://semver.org/" class="ulink" target="_top">semver versioning</a> strategy for version numbers.</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_runtime_and_development_dependencies"></a>Runtime and Development Dependencies</h4>
</div></div></div>
<p>At the bottom of the <code class="literal">gemspec</code> file is a section with a comment:
<code class="literal">Gem dependencies</code>. This is where any other needed gems must be mentioned. If
a gem is necessary for your plugin to function, it is a runtime dependency. If
a gem are only used for testing, then it would be a development dependency.</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>You can also have versioning requirements for your dependencies—​including other
Logstash plugins:</p>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby"> # Gem dependencies
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
s.add_development_dependency 'logstash-devutils'</pre>
</div>
<p>This gemspec has a runtime dependency on the logstash-core-plugin-api and requires that
it have a version number greater than or equal to version 1.60 and less than or equal to version 2.99.</p>
</div>
</div>
<div class="important admon">
<div class="icon"></div>
<div class="admon_content">
<p>All plugins have a runtime dependency on the <code class="literal">logstash-core-plugin-api</code> gem, and
a development dependency on <code class="literal">logstash-devutils</code>.</p>
</div>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_jar_dependencies"></a>Jar dependencies</h4>
</div></div></div>
<p>In some cases, such as the
<a href="https://github.com/logstash-plugins/logstash-output-elasticsearch/blob/main/logstash-output-elasticsearch.gemspec#L22-L23" class="ulink" target="_top">Elasticsearch output plugin</a>,
your code may depend on a jar file. In cases such as this, the dependency is
added in the gemspec file in this manner:</p>
<div class="pre_wrapper lang-ruby">
<pre class="programlisting prettyprint lang-ruby"> # Jar dependencies
s.requirements << "jar 'org.elasticsearch:elasticsearch', '5.0.0'"
s.add_runtime_dependency 'jar-dependencies'</pre>
</div>
<p>With these both defined, the install process will search for the required jar
file at <a href="http://mvnrepository.com" class="ulink" target="_top">http://mvnrepository.com</a> and download the specified version.</p>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_document_your_plugin"></a>Document your plugin</h3>
</div></div></div>
<p>Documentation is an important part of your plugin. All plugin documentation is
rendered and placed in the
<a href="/guide/en/logstash/8.6" class="ulink" target="_top">Logstash Reference</a> and the <a href="/guide/en/logstash-versioned-plugins/current" class="ulink" target="_top">Versioned plugin docs</a>.</p>
<p>See <a class="xref" href="plugin-doc.html" title="Document your plugin">Document your plugin</a> for tips and guidelines.</p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_add_tests"></a>Add Tests</h3>
</div></div></div>
<p>Logstash loves tests. Lots of tests. If you’re using your new input
plugin in a production environment, you’ll want to have some tests to ensure you
are not breaking any existing functionality.</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>A full exposition on RSpec is outside the scope of this document. Learn
more about RSpec at <a href="http://rspec.info" class="ulink" target="_top">http://rspec.info</a></p>
</div>
</div>
<p>For help learning about tests and testing, look in the
<code class="literal">spec/inputs/</code> directory of several other similar
plugins.</p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_clone_and_test"></a>Clone and test!</h3>
</div></div></div>
<p>Now let’s start with a fresh clone of the plugin, build it and run the tests.</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<p><span class="strong strong"><strong>Clone your plugin into a temporary location</strong></span> Replace <code class="literal">GITUSERNAME</code> with
your github username, and <code class="literal">MYPLUGINNAME</code> with your plugin name.</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<p><code class="literal">git clone https://github.com/GITUSERNAME/logstash-</code><code class="literal">input-MYPLUGINNAME.git</code></p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
alternately, via ssh: <code class="literal">git clone [email protected]:GITUSERNAME/logstash-</code><code class="literal">input-MYPLUGINNAME.git</code>
</li>
</ul>
</div>
</li>
<li class="listitem">
<code class="literal">cd logstash-input-MYPLUGINNAME</code>
</li>
</ul>
</div>
</li>
</ul>
</div>
<p>Then, you’ll need to install your plugins dependencies with bundler:</p>
<pre class="screen">bundle install</pre>
<div class="important admon">
<div class="icon"></div>
<div class="admon_content">
<p>If your plugin has an external file dependency described in <code class="literal">vendor.json</code>, you
must download that dependency before running or testing. You can do this by
running:</p>
<pre class="screen">rake vendor</pre>
</div>
</div>
<p>And finally, run the tests:</p>
<pre class="screen">bundle exec rspec</pre>
<p>You should see a success message, which looks something like this:</p>
<pre class="screen">Finished in 0.034 seconds
1 example, 0 failures</pre>
<p>Hooray! You’re almost there! (Unless you saw failures…​ you should fix those
first).</p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_building_and_testing"></a>Building and Testing</h3>
</div></div></div>
<p>Now you’re ready to build your (well-tested) plugin into a Ruby gem.</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_build"></a>Build</h4>
</div></div></div>
<p>You already have all the necessary ingredients, so let’s go ahead and run the
build command:</p>
<div class="pre_wrapper lang-sh">
<pre class="programlisting prettyprint lang-sh">gem build logstash-input-example.gemspec</pre>
</div>
<p>That’s it! Your gem should be built and be in the same path with the name</p>
<div class="pre_wrapper lang-sh">
<pre class="programlisting prettyprint lang-sh">logstash-input-mypluginname-0.1.0.gem</pre>
</div>
<p>The <code class="literal">s.version</code> number from your gemspec file will provide the gem version, in
this case, <code class="literal">0.1.0</code>.</p>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_test_installation"></a>Test installation</h4>
</div></div></div>
<p>You should test install your plugin into a clean installation of Logstash.
Download the latest version from the
<a href="/downloads/logstash/" class="ulink" target="_top">Logstash downloads page</a>.</p>
<div class="olist orderedlist">
<ol class="orderedlist">
<li class="listitem">
<p>Untar and cd in to the directory:</p>
<div class="pre_wrapper lang-sh">
<pre class="programlisting prettyprint lang-sh">curl -O https://download.elastic.co/logstash/logstash/logstash-8.6.2.tar.gz
tar xzvf logstash-8.6.2.tar.gz
cd logstash-8.6.2</pre>
</div>
</li>
<li class="listitem">
<p>Using the plugin tool, we can install the gem we just built.</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<p>Replace <code class="literal">/my/logstash/plugins</code> with the correct path to the gem for your
environment, and <code class="literal">0.1.0</code> with the correct version number from the gemspec file.</p>
<div class="pre_wrapper lang-sh">
<pre class="programlisting prettyprint lang-sh">bin/logstash-plugin install /my/logstash/plugins/logstash-input-example/logstash-input-example-0.1.0.gem</pre>
</div>
</li>
<li class="listitem">
<p>After running this, you should see feedback from Logstash that it was
successfully installed:</p>
<div class="pre_wrapper lang-sh">
<pre class="programlisting prettyprint lang-sh">validating /my/logstash/plugins/logstash-input-example/logstash-input-example-0.1.0.gem >= 0
Valid logstash plugin. Continuing...
Successfully installed 'logstash-input-example' with version '0.1.0'</pre>
</div>
<div class="tip admon">
<div class="icon"></div>
<div class="admon_content">
<p>You can also use the Logstash plugin tool to determine which plugins are
currently available:</p>
<div class="pre_wrapper lang-sh">
<pre class="programlisting prettyprint lang-sh">bin/logstash-plugin list</pre>
</div>
<p>Depending on what you have installed, you might see a short or long list of
plugins: inputs, codecs, filters and outputs.</p>
</div>
</div>
</li>
</ul>
</div>
</li>
<li class="listitem">
<p>Now try running Logstash with a simple configuration passed in via the
command-line, using the <code class="literal">-e</code> flag.</p>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>Your results will depend on what your input plugin is designed to do.</p>
</div>
</div>
</li>
</ol>
</div>
<div class="pre_wrapper lang-sh">
<pre class="programlisting prettyprint lang-sh">bin/logstash -e 'input { example{} } output {stdout { codec => rubydebug }}'</pre>
</div>
<p>The example input plugin will send the contents of <code class="literal">message</code> (with a
default message of "Hello World!") every second.</p>
<div class="pre_wrapper lang-sh">
<pre class="programlisting prettyprint lang-sh">{
"message" => "Hello World!",
"@version" => "1",
"@timestamp" => "2015-01-27T19:17:18.932Z",
"host" => "cadenza"
}</pre>
</div>
<p>Feel free to experiment and test this by changing the <code class="literal">message</code> and <code class="literal">interval</code> parameters:</p>
<div class="pre_wrapper lang-sh">
<pre class="programlisting prettyprint lang-sh">bin/logstash -e 'input { example{ message => "A different message" interval => 5 } } output {stdout { codec => rubydebug }}'</pre>
</div>
<p>Congratulations! You’ve built, deployed and successfully run a Logstash
input.</p>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title"><a id="_submitting_your_plugin_to_rubygems_org_and_logstash_plugins"></a>Submitting your plugin to <a href="http://rubygems.org" class="ulink" target="_top">RubyGems.org</a> and <a href="https://github.com/logstash-plugins" class="ulink" target="_top">logstash-plugins</a></h3>
</div></div></div>
<p>Logstash uses <a href="http://rubygems.org" class="ulink" target="_top">RubyGems.org</a> as its repository for all plugin
artifacts. Once you have developed your new plugin, you can make it available to
Logstash users by simply publishing it to RubyGems.org.</p>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_licensing"></a>Licensing</h4>
</div></div></div>
<p>Logstash and all its plugins are licensed under
<a href="https://github.com/elasticsearch/logstash/blob/main/LICENSE" class="ulink" target="_top">Apache License, version 2 ("ALv2")</a>.
If you make your plugin publicly available via <a href="http://rubygems.org" class="ulink" target="_top">RubyGems.org</a>,
please make sure to have this line in your gemspec:</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">s.licenses = ['Apache License (2.0)']</code>
</li>
</ul>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h4 class="title"><a id="_publishing_to_rubygems_org"></a>Publishing to <a href="http://rubygems.org" class="ulink" target="_top">RubyGems.org</a></h4>
</div></div></div>
<p>To begin, you’ll need an account on RubyGems.org</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<a href="https://rubygems.org/sign_up" class="ulink" target="_top">Sign-up for a RubyGems account</a>.
</li>
</ul>
</div>
<p>After creating an account,
<a href="http://guides.rubygems.org/rubygems-org-api/#api-authorization" class="ulink" target="_top">obtain</a> an API
key from RubyGems.org. By default, RubyGems uses the file <code class="literal">~/.gem/credentials</code>
to store your API key. These credentials will be used to publish the gem.
Replace <code class="literal">username</code> and <code class="literal">password</code> with the credentials you created at
RubyGems.org:</p>
<div class="pre_wrapper lang-sh">
<pre class="programlisting prettyprint lang-sh">curl -u username:password https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials
chmod 0600 ~/.gem/credentials</pre>
</div>
<p>Before proceeding, make sure you have the right version in your gemspec file
and commit your changes.</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="literal">s.version = '0.1.0'</code>
</li>
</ul>
</div>
<p>To publish version 0.1.0 of your new logstash gem:</p>
<div class="pre_wrapper lang-sh">
<pre class="programlisting prettyprint lang-sh">bundle install
bundle exec rake vendor
bundle exec rspec
bundle exec rake publish_gem</pre>
</div>
<div class="note admon">
<div class="icon"></div>
<div class="admon_content">
<p>Executing <code class="literal">rake publish_gem</code>:</p>
<div class="olist orderedlist">
<ol class="orderedlist">
<li class="listitem">
Reads the version from the gemspec file (<code class="literal">s.version = '0.1.0'</code>)
</li>
<li class="listitem">
Checks in your local repository if a tag exists for that version. If the tag