kibana-sinatra 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/lib/kibana/assets/app/app.js +4 -2
  4. data/lib/kibana/assets/app/components/kbn.js +114 -0
  5. data/lib/kibana/assets/app/components/require.config.js +5 -1
  6. data/lib/kibana/assets/app/controllers/dash.js +30 -2
  7. data/lib/kibana/assets/app/controllers/row.js +33 -0
  8. data/lib/kibana/assets/app/dashboards/blank.json +0 -11
  9. data/lib/kibana/assets/app/dashboards/default.json +0 -11
  10. data/lib/kibana/assets/app/dashboards/guided.json +0 -11
  11. data/lib/kibana/assets/app/dashboards/logstash.json +0 -6
  12. data/lib/kibana/assets/app/dashboards/noted.json +0 -11
  13. data/lib/kibana/assets/app/directives/addPanel.js +1 -1
  14. data/lib/kibana/assets/app/directives/kibanaPanel.js +3 -2
  15. data/lib/kibana/assets/app/directives/kibanaSimplePanel.js +3 -3
  16. data/lib/kibana/assets/app/panels/bettermap/module.js +52 -17
  17. data/lib/kibana/assets/app/panels/column/module.js +18 -8
  18. data/lib/kibana/assets/app/panels/histogram/editor.html +3 -0
  19. data/lib/kibana/assets/app/panels/histogram/module.html +1 -1
  20. data/lib/kibana/assets/app/panels/histogram/module.js +179 -49
  21. data/lib/kibana/assets/app/panels/histogram/styleEditor.html +4 -0
  22. data/lib/kibana/assets/app/panels/hits/module.js +46 -18
  23. data/lib/kibana/assets/app/panels/map/module.js +40 -21
  24. data/lib/kibana/assets/app/panels/pie/module.html +3 -0
  25. data/lib/kibana/assets/app/panels/pie/module.js +62 -25
  26. data/lib/kibana/assets/app/panels/sparklines/module.js +42 -35
  27. data/lib/kibana/assets/app/panels/table/editor.html +2 -2
  28. data/lib/kibana/assets/app/panels/table/module.html +24 -19
  29. data/lib/kibana/assets/app/panels/table/module.js +80 -29
  30. data/lib/kibana/assets/app/panels/terms/module.html +3 -0
  31. data/lib/kibana/assets/app/panels/terms/module.js +65 -17
  32. data/lib/kibana/assets/app/panels/text/module.js +21 -9
  33. data/lib/kibana/assets/app/panels/trends/module.js +34 -13
  34. data/lib/kibana/assets/app/partials/dasheditor.html +1 -1
  35. data/lib/kibana/assets/app/services/dashboard.js +14 -14
  36. data/lib/kibana/assets/app/services/fields.js +11 -8
  37. data/lib/kibana/assets/app/services/filterSrv.js +27 -17
  38. data/lib/kibana/assets/app/services/querySrv.js +14 -15
  39. data/lib/kibana/assets/css/bootstrap.dark.min.css +1 -1
  40. data/lib/kibana/assets/css/bootstrap.light.min.css +1 -1
  41. data/lib/kibana/assets/index.html +1 -1
  42. data/lib/kibana/assets/vendor/angular/angular-strap.js +6 -3
  43. data/lib/kibana/assets/vendor/angular/bindonce.js +269 -0
  44. data/lib/kibana/assets/vendor/bootstrap/less/overrides.less +6 -0
  45. data/lib/kibana/assets/vendor/elasticjs/elastic-angular-client.js +37 -24
  46. data/lib/kibana/assets/vendor/elasticjs/elastic.js +4694 -2419
  47. data/lib/kibana/assets/vendor/jquery/jquery.flot.byte.js +107 -0
  48. data/lib/kibana/sinatra/version.rb +1 -1
  49. data/lib/kibana/views/config.erb +19 -16
  50. metadata +4 -2
@@ -32,10 +32,10 @@ function (angular, _) {
32
32
  function loadController(name) {
33
33
  elem.addClass("ng-cloak");
34
34
  // load the panels module file, then render it in the dom.
35
-
35
+ var nameAsPath = name.replace(".", "/");
36
36
  $scope.require([
37
37
  'jquery',
38
- 'text!panels/'+name+'/module.html'
38
+ 'text!panels/'+nameAsPath+'/module.html'
39
39
  ], function ($, moduleTemplate) {
40
40
  var $module = $(moduleTemplate);
41
41
  // top level controllers
@@ -46,7 +46,7 @@ function (angular, _) {
46
46
  if ($controllers.length) {
47
47
  $controllers.first().prepend(panelLoading);
48
48
  $scope.require([
49
- 'panels/'+name+'/module'
49
+ 'panels/'+nameAsPath+'/module'
50
50
  ], function() {
51
51
  loadModule($module);
52
52
  });
@@ -1,13 +1,21 @@
1
- /*
2
-
3
- ## Better maps
4
-
5
- ### Parameters
6
- * size :: How many results to show, more results = slower
7
- * field :: field containing a 2 element array in the format [lon,lat]
8
- * tooltip :: field to extract the tool tip value from
9
- * spyable :: Show the 'eye' icon that reveals the last ES query
10
- */
1
+ /** @scratch /panels/5
2
+ * include::panels/bettermap.asciidoc[]
3
+ */
4
+
5
+ /** @scratch /panels/bettermap/0
6
+ * == Bettermap
7
+ * Status: *Experimental*
8
+ *
9
+ * Bettermap is called bettermap for lack of a better name. Bettermap uses geographic coordinates to
10
+ * create clusters of markers on map and shade them orange, yellow and green depending on the
11
+ * density of the cluster.
12
+ *
13
+ * To drill down, click on a cluster. The map will be zoomed and the cluster broken into smaller cluster.
14
+ * When it no longer makes visual sense to cluster, individual markers will be displayed. Hover over
15
+ * a marker to see the tooltip value/
16
+ *
17
+ * IMPORTANT: bettermap requires an internet connection to download its map panels.
18
+ */
11
19
  define([
12
20
  'angular',
13
21
  'app',
@@ -51,21 +59,43 @@ function (angular, app, _, L, localRequire) {
51
59
 
52
60
  // Set and populate defaults
53
61
  var _d = {
62
+ /** @scratch /panels/bettermap/3
63
+ * === Parameters
64
+ *
65
+ * field:: The field that contains the coordinates, in geojson format. GeoJSON is
66
+ * +[longitude,latitude]+ in an array. This is different from most implementations, which use
67
+ * latitude, longitude.
68
+ */
69
+ field : null,
70
+ /** @scratch /panels/bettermap/5
71
+ * size:: The number of documents to use when drawing the map
72
+ */
73
+ size : 1000,
74
+ /** @scratch /panels/bettermap/5
75
+ * spyable:: Should the `inspect` icon be shown?
76
+ */
77
+ spyable : true,
78
+ /** @scratch /panels/bettermap/5
79
+ * tooltip:: Which field to use for the tooltip when hovering over a marker
80
+ */
81
+ tooltip : "_id",
82
+ /** @scratch /panels/bettermap/5
83
+ * ==== Queries
84
+ * queries object:: This object describes the queries to use on this panel.
85
+ * queries.mode::: Of the queries available, which to use. Options: +all, pinned, unpinned, selected+
86
+ * queries.ids::: In +selected+ mode, which query ids are selected.
87
+ */
54
88
  queries : {
55
89
  mode : 'all',
56
90
  ids : []
57
91
  },
58
- size : 1000,
59
- spyable : true,
60
- tooltip : "_id",
61
- field : null
62
92
  };
63
93
 
64
94
  _.defaults($scope.panel,_d);
65
- $scope.requireContext = localRequire;
66
95
 
67
96
  // inorder to use relative paths in require calls, require needs a context to run. Without
68
97
  // setting this property the paths would be relative to the app not this context/file.
98
+ $scope.requireContext = localRequire;
69
99
 
70
100
  $scope.init = function() {
71
101
  $scope.$on('refresh',function(){
@@ -204,6 +234,7 @@ function (angular, app, _, L, localRequire) {
204
234
  zoom: 10
205
235
  });
206
236
 
237
+ // This could be made configurable?
207
238
  L.tileLayer('http://{s}.tile.cloudmade.com/57cbb6ca8cac418dbb1a402586df4528/22677/256/{z}/{x}/{y}.png', {
208
239
  maxZoom: 18,
209
240
  minZoom: 2
@@ -213,14 +244,18 @@ function (angular, app, _, L, localRequire) {
213
244
  layerGroup.clearLayers();
214
245
  }
215
246
 
247
+ var markerList = [];
248
+
216
249
  _.each(scope.data, function(p) {
217
250
  if(!_.isUndefined(p.tooltip) && p.tooltip !== '') {
218
- layerGroup.addLayer(L.marker(p.coordinates).bindLabel(p.tooltip));
251
+ markerList.push(L.marker(p.coordinates).bindLabel(p.tooltip));
219
252
  } else {
220
- layerGroup.addLayer(L.marker(p.coordinates));
253
+ markerList.push(L.marker(p.coordinates));
221
254
  }
222
255
  });
223
256
 
257
+ layerGroup.addLayers(markerList);
258
+
224
259
  layerGroup.addTo(map);
225
260
 
226
261
  map.fitBounds(_.pluck(scope.data,'coordinates'));
@@ -1,11 +1,16 @@
1
- /*
2
-
3
- ## Column
4
-
5
- ### Parameters
6
- * panels :: an array of panel objects. All of their spans should be set to 12
7
-
8
- */
1
+ /** @scratch /panels/5
2
+ * include::panels/column.asciidoc[]
3
+ */
4
+
5
+ /** @scratch /panels/column/0
6
+ * == Column
7
+ * Status: *Stable*
8
+ *
9
+ * A pseudo panel that lets you add other panels to be arranged in a column with defined heights.
10
+ * While the column panel is stable, it does have many limitations, including the inability to drag
11
+ * and drop panels within its borders. It may be removed in a future release.
12
+ *
13
+ */
9
14
  define([
10
15
  'angular',
11
16
  'app',
@@ -28,6 +33,11 @@ function (angular, app, _, config) {
28
33
 
29
34
  // Set and populate defaults
30
35
  var _d = {
36
+ /** @scratch /panels/column/3
37
+ * === Parameters
38
+ *
39
+ * panel:: An array of panel objects
40
+ */
31
41
  panels : []
32
42
  };
33
43
  _.defaults($scope.panel,_d);
@@ -16,6 +16,9 @@
16
16
  <label class="small">Scale</label>
17
17
  <input type="text" class="input-mini" ng-model="panel.scale">
18
18
  </div>
19
+ <div class="editor-option">
20
+ <label class="small">Seconds <tip>Normalize intervals to per-second</tip></label><input type="checkbox" ng-model="panel.scaleSeconds" ng-checked="panel.scaleSeconds">
21
+ </div>
19
22
  <div class="editor-option">
20
23
  <label class="small">Derivative <tip>Plot the change per interval in the series</tip></label><input type="checkbox" ng-model="panel.derivative" ng-checked="panel.derivative" ng-change="set_refresh(true)">
21
24
  </div>
@@ -51,7 +51,7 @@
51
51
  <span ng-show="panel.legend_counts"> ({{series.hits}})</span>
52
52
  </span>
53
53
  </span>
54
- <span ng-show="panel.legend" class="small"><span ng-show="panel.derivative">change in </span><span class="strong" ng-show="panel.value_field && panel.mode != 'count'">{{panel.value_field}}</span> {{panel.mode}} per <strong>{{panel.interval}}</strong> | (<strong>{{hits}}</strong> hits)</span>
54
+ <span ng-show="panel.legend" class="small"><span ng-show="panel.derivative">change in </span><span class="strong" ng-show="panel.value_field && panel.mode != 'count'">{{panel.value_field}}</span> {{panel.mode}} per <strong ng-hide="panel.scaleSeconds">{{panel.interval}}</strong><strong ng-show="panel.scaleSeconds">1s</strong> | (<strong>{{hits}}</strong> hits)</span>
55
55
  </div>
56
56
  <form class="form-inline bordered histogram-options" ng-show="options">
57
57
  <span>
@@ -1,32 +1,16 @@
1
- /*
2
-
3
- ## Histogram
4
-
5
- ### Parameters
6
- * auto_int :: Auto calculate data point interval?
7
- * resolution :: If auto_int is enables, shoot for this many data points, rounding to
8
- sane intervals
9
- * interval :: Datapoint interval in elasticsearch date math format (eg 1d, 1w, 1y, 5y)
10
- * fill :: Only applies to line charts. Level of area shading from 0-10
11
- * linewidth :: Only applies to line charts. How thick the line should be in pixels
12
- While the editor only exposes 0-10, this can be any numeric value.
13
- Set to 0 and you'll get something like a scatter plot
14
- * timezone :: This isn't totally functional yet. Currently only supports browser and utc.
15
- browser will adjust the x-axis labels to match the timezone of the user's
16
- browser
17
- * spyable :: Dislay the 'eye' icon that show the last elasticsearch query
18
- * zoomlinks :: Show the zoom links?
19
- * bars :: Show bars in the chart
20
- * stack :: Stack multiple queries. This generally a crappy way to represent things.
21
- You probably should just use a line chart without stacking
22
- * points :: Should circles at the data points on the chart
23
- * lines :: Line chart? Sweet.
24
- * legend :: Show the legend?
25
- * x-axis :: Show x-axis labels and grid lines
26
- * y-axis :: Show y-axis labels and grid lines
27
- * interactive :: Allow drag to select time range
28
-
29
- */
1
+ /** @scratch /panels/5
2
+ * include::panels/histogram.asciidoc[]
3
+ */
4
+
5
+ /** @scratch /panels/histogram/0
6
+ * == Histogram
7
+ * Status: *Stable*
8
+ *
9
+ * The histogram panel allow for the display of time charts. It includes several modes and tranformations
10
+ * to display event counts, mean, min, max and total of numeric fields, and derivatives of counter
11
+ * fields.
12
+ *
13
+ */
30
14
  define([
31
15
  'angular',
32
16
  'app',
@@ -35,11 +19,11 @@ define([
35
19
  'kbn',
36
20
  'moment',
37
21
  './timeSeries',
38
-
39
22
  'jquery.flot',
40
23
  'jquery.flot.events',
41
24
  'jquery.flot.selection',
42
25
  'jquery.flot.time',
26
+ 'jquery.flot.byte',
43
27
  'jquery.flot.stack',
44
28
  'jquery.flot.stackpercent'
45
29
  ],
@@ -78,12 +62,66 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
78
62
 
79
63
  // Set and populate defaults
80
64
  var _d = {
65
+ /** @scratch /panels/histogram/3
66
+ * === Parameters
67
+ * ==== Axis options
68
+ * mode:: Value to use for the y-axis. For all modes other than count, +value_field+ must be
69
+ * defined. Possible values: count, mean, max, min, total.
70
+ */
81
71
  mode : 'count',
72
+ /** @scratch /panels/histogram/3
73
+ * time_field:: x-axis field. This must be defined as a date type in Elasticsearch.
74
+ */
82
75
  time_field : '@timestamp',
83
- queries : {
84
- mode : 'all',
85
- ids : []
76
+ /** @scratch /panels/histogram/3
77
+ * value_field:: y-axis field if +mode+ is set to mean, max, min or total. Must be numeric.
78
+ */
79
+ value_field : null,
80
+ /** @scratch /panels/histogram/3
81
+ * x-axis:: Show the x-axis
82
+ */
83
+ 'x-axis' : true,
84
+ /** @scratch /panels/histogram/3
85
+ * y-axis:: Show the y-axis
86
+ */
87
+ 'y-axis' : true,
88
+ /** @scratch /panels/histogram/3
89
+ * scale:: Scale the y-axis by this factor
90
+ */
91
+ scale : 1,
92
+ /** @scratch /panels/histogram/3
93
+ * y_format:: 'none','bytes','short '
94
+ */
95
+ y_format : 'none',
96
+ /** @scratch /panels/histogram/5
97
+ * grid object:: Min and max y-axis values
98
+ * grid.min::: Minimum y-axis value
99
+ * grid.max::: Maximum y-axis value
100
+ */
101
+ grid : {
102
+ max: null,
103
+ min: 0
104
+ },
105
+ /** @scratch /panels/histogram/5
106
+ * ==== Queries
107
+ * queries object:: This object describes the queries to use on this panel.
108
+ * queries.mode::: Of the queries available, which to use. Options: +all, pinned, unpinned, selected+
109
+ * queries.ids::: In +selected+ mode, which query ids are selected.
110
+ */
111
+ queries : {
112
+ mode : 'all',
113
+ ids : []
86
114
  },
115
+ /** @scratch /panels/histogram/3
116
+ * ==== Annotations
117
+ * annotate object:: A query can be specified, the results of which will be displayed as markers on
118
+ * the chart. For example, for noting code deploys.
119
+ * annotate.enable::: Should annotations, aka markers, be shown?
120
+ * annotate.query::: Lucene query_string syntax query to use for markers.
121
+ * annotate.size::: Max number of markers to show
122
+ * annotate.field::: Field from documents to show
123
+ * annotate.sort::: Sort array in format [field,order], For example [`@timestamp',`desc']
124
+ */
87
125
  annotate : {
88
126
  enable : false,
89
127
  query : "*",
@@ -91,39 +129,106 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
91
129
  field : '_type',
92
130
  sort : ['_score','desc']
93
131
  },
94
- value_field : null,
132
+ /** @scratch /panels/histogram/3
133
+ * ==== Interval options
134
+ * auto_int:: Automatically scale intervals?
135
+ */
95
136
  auto_int : true,
137
+ /** @scratch /panels/histogram/3
138
+ * resolution:: If auto_int is true, shoot for this many bars.
139
+ */
96
140
  resolution : 100,
141
+ /** @scratch /panels/histogram/3
142
+ * interval:: If auto_int is set to false, use this as the interval.
143
+ */
97
144
  interval : '5m',
145
+ /** @scratch /panels/histogram/3
146
+ * interval:: Array of possible intervals in the *View* selector. Example [`auto',`1s',`5m',`3h']
147
+ */
98
148
  intervals : ['auto','1s','1m','5m','10m','30m','1h','3h','12h','1d','1w','1y'],
149
+ /** @scratch /panels/histogram/3
150
+ * ==== Drawing options
151
+ * lines:: Show line chart
152
+ */
153
+ lines : false,
154
+ /** @scratch /panels/histogram/3
155
+ * fill:: Area fill factor for line charts, 1-10
156
+ */
99
157
  fill : 0,
158
+ /** @scratch /panels/histogram/3
159
+ * linewidth:: Weight of lines in pixels
160
+ */
100
161
  linewidth : 3,
162
+ /** @scratch /panels/histogram/3
163
+ * points:: Show points on chart
164
+ */
165
+ points : false,
166
+ /** @scratch /panels/histogram/3
167
+ * pointradius:: Size of points in pixels
168
+ */
101
169
  pointradius : 5,
102
- timezone : 'browser', // browser, utc or a standard timezone
103
- spyable : true,
104
- zoomlinks : true,
170
+ /** @scratch /panels/histogram/3
171
+ * bars:: Show bars on chart
172
+ */
105
173
  bars : true,
174
+ /** @scratch /panels/histogram/3
175
+ * stack:: Stack multiple series
176
+ */
106
177
  stack : true,
107
- points : false,
108
- lines : false,
178
+ /** @scratch /panels/histogram/3
179
+ * spyable:: Show inspect icon
180
+ */
181
+ spyable : true,
182
+ /** @scratch /panels/histogram/3
183
+ * zoomlinks:: Show `Zoom Out' link
184
+ */
185
+ zoomlinks : true,
186
+ /** @scratch /panels/histogram/3
187
+ * options:: Show quick view options section
188
+ */
189
+ options : true,
190
+ /** @scratch /panels/histogram/3
191
+ * legend:: Display the legond
192
+ */
109
193
  legend : true,
194
+ /** @scratch /panels/histogram/3
195
+ * show_query:: If no alias is set, should the query be displayed?
196
+ */
110
197
  show_query : true,
198
+ /** @scratch /panels/histogram/3
199
+ * interactive:: Enable click-and-drag to zoom functionality
200
+ */
201
+ interactive : true,
202
+ /** @scratch /panels/histogram/3
203
+ * legend_counts:: Show counts in legend
204
+ */
111
205
  legend_counts : true,
112
- 'x-axis' : true,
113
- 'y-axis' : true,
206
+ /** @scratch /panels/histogram/3
207
+ * ==== Transformations
208
+ * timezone:: Correct for browser timezone?. Valid values: browser, utc
209
+ */
210
+ timezone : 'browser', // browser or utc
211
+ /** @scratch /panels/histogram/3
212
+ * percentage:: Show the y-axis as a percentage of the axis total. Only makes sense for multiple
213
+ * queries
214
+ */
114
215
  percentage : false,
216
+ /** @scratch /panels/histogram/3
217
+ * zerofill:: Improves the accuracy of line charts at a small performance cost.
218
+ */
115
219
  zerofill : true,
116
- interactive : true,
117
- options : true,
220
+ /** @scratch /panels/histogram/3
221
+ * derivative:: Show each point on the x-axis as the change from the previous point
222
+ */
118
223
  derivative : false,
119
- scale : 1,
224
+ /** @scratch /panels/histogram/3
225
+ * tooltip object::
226
+ * tooltip.value_type::: Individual or cumulative controls how tooltips are display on stacked charts
227
+ * tooltip.query_as_alias::: If no alias is set, should the query be displayed?
228
+ */
120
229
  tooltip : {
121
230
  value_type: 'cumulative',
122
231
  query_as_alias: true
123
- },
124
- grid : {
125
- max: null,
126
- min: 0
127
232
  }
128
233
  };
129
234
 
@@ -439,6 +544,12 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
439
544
  });
440
545
  };
441
546
 
547
+ var scaleSeconds = function(series,interval) {
548
+ return _.map(series,function(p) {
549
+ return [p[0],p[1]/kbn.interval_to_seconds(interval)];
550
+ });
551
+ };
552
+
442
553
  var derivative = function(series) {
443
554
  return _.map(series, function(p,i) {
444
555
  var _v;
@@ -501,7 +612,7 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
501
612
  yaxis: {
502
613
  show: scope.panel['y-axis'],
503
614
  min: scope.panel.grid.min,
504
- max: scope.panel.percentage && scope.panel.stack ? 100 : scope.panel.grid.max,
615
+ max: scope.panel.percentage && scope.panel.stack ? 100 : scope.panel.grid.max
505
616
  },
506
617
  xaxis: {
507
618
  timezone: scope.panel.timezone,
@@ -521,6 +632,16 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
521
632
  }
522
633
  };
523
634
 
635
+ if(scope.panel.y_format === 'bytes') {
636
+ options.yaxis.mode = "byte";
637
+ }
638
+
639
+ if(scope.panel.y_format === 'short') {
640
+ options.yaxis.tickFormatter = function(val) {
641
+ return kbn.shortFormat(val,0);
642
+ };
643
+ }
644
+
524
645
  if(scope.panel.annotate.enable) {
525
646
  options.events = {
526
647
  levels: 1,
@@ -566,6 +687,9 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
566
687
  if(scope.panel.scale !== 1) {
567
688
  _d = scale(_d,scope.panel.scale);
568
689
  }
690
+ if(scope.panel.scaleSeconds) {
691
+ _d = scaleSeconds(_d,scope.panel.interval);
692
+ }
569
693
  scope.data[i].data = _d;
570
694
  }
571
695
 
@@ -606,6 +730,12 @@ function (angular, app, $, _, kbn, moment, timeSeries) {
606
730
  value = (scope.panel.stack && scope.panel.tooltip.value_type === 'individual') ?
607
731
  item.datapoint[1] - item.datapoint[2] :
608
732
  item.datapoint[1];
733
+ if(scope.panel.y_format === 'bytes') {
734
+ value = kbn.byteFormat(value,2);
735
+ }
736
+ if(scope.panel.y_format === 'short') {
737
+ value = kbn.shortFormat(value,2);
738
+ }
609
739
  timestamp = scope.panel.timezone === 'browser' ?
610
740
  moment(item.datapoint[0]).format('YYYY-MM-DD HH:mm:ss') :
611
741
  moment.utc(item.datapoint[0]).format('YYYY-MM-DD HH:mm:ss');