{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-guides/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["tabs","tab"]},"type":"markdown"},"seo":{"title":"Real-Time Server","description":"Accelerate E&P application development and protect your innovation by consuming our Data and Domain APIs / Platform APIs.","lang":"en-US","meta":[{"name":"robots","content":"noindex"}],"llmstxt":{"hide":true,"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"real-time-server","__idx":0},"children":["Real-Time Server"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The GeoToolkit doesn't have the standard implementation of middle-tier architecture and the communication between the client and the server solution does not preclude the use of server-side technologies such as PHP, ASP.NET, JSP, Python or others. This tutorial shows how to implement client-server communication to display real-time data.",{"$$mdtype":"Tag","name":"br","attributes":{},"children":[]},"See the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/WellLog/DataAndTemplates/RealTimeData/realtime"},"children":["Real-time Data"]}," tutorial."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"show-communication-between-widget-and-server","__idx":1},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/WellLog/DataAndTemplates/RealTimeServer/realTimeServer#communication"},"children":["#"]}," Show Communication Between Widget and Server"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This example contains simple server implementation written on ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["nodejs"]}," and client code, which requests real-time as well as historical data from the server. To run application, perform the following steps."]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Install ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"http://nodejs.org/"},"children":["nodejs"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["In terminal, ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["cd"]}," to server (examples/vue/tutorials/src/code/WellLog/DataAndTemplates/RealTimeServer/realtimedemoserver) folder"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Run ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["npm install"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Run ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["npm start"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Type in your browser ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"http://localhost:3003/"},"children":["http://localhost:3003/"]},"to verify that server is running"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"http-communication","__idx":2},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/WellLog/DataAndTemplates/RealTimeServer/realTimeServer#realtime"},"children":["#"]}," HTTP communication"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This example shows implementation of real-time data using HTTP requests to the server. The server supports three requests:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Get ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"http://localhost:3003/limits"},"children":["limits"]}," of data"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Get [real-time data points](http://localhost:3003/logdata?low=1357802231800&high=1357802312000&time=1357802312000&mnemonics"," ","%5B%5D=cali&mnemonics%5B%5D=gr&historical=false)"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Get [historical data points](http://localhost:3003/logdata?low=1357799613762.264&high=1357799693962.264&mnemonics"," ","%5B%5D=cali&mnemonics%5B%5D=gr&historical=true)"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The client data source extends ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["geotoolkit/data/DataSource"]}," and requests real time data, sending the last data point received, or historical data, when widget has been scrolled or panned."]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"main","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"import { HeaderType } from \"@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts\";\nimport { TrackType } from \"@int/geotoolkit/welllog/TrackType.ts\";\nimport { Events as AbstractScrollEvents } from \"@int/geotoolkit/controls/tools/scroll/AbstractScroll.ts\";\nimport { Events as PanningEvents } from \"@int/geotoolkit/controls/tools/Panning.ts\";\nimport { Range } from \"@int/geotoolkit/util/Range.ts\";\nimport { Timer } from \"@int/geotoolkit/util/Timer.ts\";\nimport { Plot } from \"@int/geotoolkit/plot/Plot.ts\";\nimport { LogData } from \"@int/geotoolkit/welllog/data/LogData.ts\";\nimport { LogCurve } from \"@int/geotoolkit/welllog/LogCurve.ts\";\nimport { KnownColors } from \"@int/geotoolkit/util/ColorUtil.ts\";\nimport { RealtimeData } from \"/src/code/WellLog/DataAndTemplates/RealTimeServer/common/realtimeDemoServerData.ts\";\nimport { createWellLogWidget } from \"/src/code/WellLog/utils/common.ts\";\nconst defaults = {\n  zoomInScale: 5 / 4,\n  zoomOutScale: 4 / 5\n};\nconst REFRESH_TIME = 1e3;\nconst INTERVAL = 1e3;\nconst SCALE_COEFFICIENT = 1 / 200;\nconst INDEX_TRACK_WIDTH = 60;\nconst SERVER_HOST = \"http://localhost:3003\";\nclass HTTPDemo {\n  constructor(options) {\n    this.isConnected = false;\n    this.plot = null;\n    this.scaleFactor = 1;\n    this.timer = null;\n    this.isRunning = false;\n    this.onError = options.onerror;\n    this.widget = this.createWidget();\n    this.plot = new Plot({\n      canvaselement: options.canvas,\n      root: this.widget\n    });\n  }\n  dispose() {\n    if (this.timer) {\n      this.timer.stop();\n    }\n    if (this.plot) {\n      this.plot.dispose();\n    }\n  }\n  createWidget() {\n    const widget = createWellLogWidget({\n      \"indextype\": \"time\",\n      \"indexunit\": \"ms\"\n    });\n    widget.setAxisHeaderType(HeaderType.Simple);\n    this.createTestData((err, source) => {\n      if (err) {\n        this.onError(true);\n        return;\n      }\n      const BindingFunction = {\n        accept: (node) => node instanceof LogCurve,\n        bind: (curve, data) => {\n          if (curve.getDataSource() != null) {\n            curve.getDataSource().clear();\n          }\n          if (data != null && data instanceof RealtimeData) {\n            data.setCurveSource(curve);\n          }\n        }\n      };\n      widget.getDataBinding().add(BindingFunction);\n      widget.setData(source);\n      widget.addTrack(TrackType.IndexTrack).setWidth(INDEX_TRACK_WIDTH);\n      widget.addTrack(TrackType.LinearTrack).addChild([\n        this.createCurve(\"CALI\").setLineStyle(KnownColors.Green).setNormalizationLimits(100, 150)\n      ]);\n      widget.addTrack(TrackType.IndexTrack).setWidth(INDEX_TRACK_WIDTH);\n      widget.addTrack(TrackType.LogTrack).addChild([\n        this.createCurve(\"GR\").setLineStyle(KnownColors.Red).setNormalizationLimits(0, 30)\n      ]);\n      const lowerLimit = widget.getData().getLowerLimit();\n      widget.setDepthLimits(new Range(lowerLimit, lowerLimit));\n      widget.setVisibleDepthLimits(new Range(lowerLimit, lowerLimit));\n      widget.getToolByName(\"TrackPlotVerticalScroll\").on(AbstractScrollEvents.onScrollEnd, this.widgetScrolled.bind(this));\n      widget.getToolByName(\"TrackPanning\").on(PanningEvents.onPanningEnd, this.widgetScrolled.bind(this));\n      widget.scale(SCALE_COEFFICIENT);\n      this.isConnected = true;\n      this.startRealTime();\n    });\n    return widget;\n  }\n  widgetScrolled() {\n    if (this.isRunning) {\n      this.stopRealTime();\n    }\n    const visibleLimits = this.widget.getVisibleDepthLimits();\n    this.widget.getData().getHistorical(visibleLimits, () => {\n    });\n  }\n  createCurve(mnemonic, source) {\n    source = source || this.widget.getData();\n    let d = source.getCurveSource(mnemonic);\n    if (d == null) {\n      d = new LogData(mnemonic);\n    }\n    const curve = new LogCurve(d, true);\n    curve.setId(mnemonic);\n    return curve;\n  }\n  createTestData(cb) {\n    const ds = new RealtimeData();\n    ds.initialize(INTERVAL, (err, dataSource) => {\n      if (err) {\n        return cb(err);\n      }\n      this.timer = new Timer(REFRESH_TIME, () => {\n        const visibleLimits = this.widget.getVisibleDepthLimits();\n        const depthLimits = this.widget.getDepthLimits();\n        if (this.isRunning) {\n          dataSource.getData(depthLimits.getHigh(), visibleLimits, () => {\n            depthLimits.setRange(depthLimits.getLow(), dataSource.getHigherLimit());\n            this.widget.setDepthLimits(depthLimits);\n            this.scrollDownWidget();\n          });\n        }\n      });\n      return cb(null, ds);\n    }, SERVER_HOST);\n  }\n  scrollDownWidget() {\n    const limits = this.widget.getDepthLimits();\n    const high = limits.getHigh();\n    const vdl = this.widget.getTrackContainer().getVisibleDepthLimits();\n    if (vdl.getLow() > 0 && vdl.getHigh() > 0) {\n      this.widget.getTrackContainer().scrollToDepth(high);\n    }\n  }\n  zoomIn() {\n    this.widget.scale(defaults.zoomInScale);\n    this.scaleFactor *= defaults.zoomOutScale;\n    this.scrollDownWidget();\n  }\n  zoomOut() {\n    this.widget.scale(defaults.zoomOutScale);\n    this.scaleFactor /= defaults.zoomOutScale;\n    this.scrollDownWidget();\n  }\n  zoomReset() {\n    this.widget.scale(this.scaleFactor);\n    this.scaleFactor = 1;\n    this.scrollDownWidget();\n  }\n  startRealTime() {\n    this.timer.start();\n    this.isRunning = true;\n  }\n  stopRealTime() {\n    this.timer.stop();\n    this.isRunning = false;\n  }\n  toggleRealTime() {\n    this.isRunning ? this.stopRealTime() : this.startRealTime();\n  }\n  isRealTime() {\n    return this.isRunning;\n  }\n}\nexport { HTTPDemo };\n\ncreateScene();\n\n","lang":"ts"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"css","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"css","header":{"controls":{"copy":{}}},"source":"\n.cg-tooltip-holder {\n  position: relative;\n}\n\n.cg-tooltip {\n  position: absolute;\n  display: block;\n  padding: 2px 12px 3px 7px;\n  overflow: visible !important;\n  font-family: Roboto, Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  background: white !important;\n  opacity: 0.9;\n  color: #333333;\n  border: solid 1px gray;\n  border-radius: 5px;\n  text-align: left;\n  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n  border-radius: 5px;\n  margin: 0 !important;\n  z-index: 10000;\n  max-width: 400px;\n  text-wrap: normal !important;\n  white-space: normal !important;\n}\n/* Default setting for tooltip */\n.cg-tooltip-container {\n  position: absolute;\n  display: block;\n  overflow: visible !important;\n  font-family: Roboto, Helvetica, Arial, sans-serif;\n  font-size: 12px;\n  padding: 3px 7px;\n  background: #f7f7f7;\n  color: #333333;\n  border: 1px solid #938e8e;\n  opacity: 0.8;\n  text-align: left;\n  box-shadow: 3px 3px 10px #888;\n  margin: 0 !important;\n  z-index: 10000;\n  max-width: 400px;\n  text-wrap: normal !important;\n  white-space: normal !important;\n  user-select: none;\n}\n@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n  .cg-tooltip-container {\n    border-radius: 0;\n  }\n}\n/* Default left arrow for tooltip */\n.cg-tooltip-arrow-left::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 0;\n  top: 50%;\n  border: 5px solid transparent;\n  border-left: 0;\n  border-right: 5px solid  #938e8e;\n  transform: translate(calc(-100%), -50%);\n}\n.cg-tooltip-arrow-left::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 0;\n  top: 50%;\n  border: 4px solid transparent;\n  border-left: 0;\n  border-right: 4px solid #f7f7f7;\n  transform: translate(calc(-100%), -50%);\n}\n/* Default top arrow for tooltip */\n.cg-tooltip-arrow-top::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  top: 0;\n  border: 5px solid transparent;\n  border-top: 0;\n  border-bottom: 5px solid #938e8e;\n  transform: translate(-50%, -100%);\n}\n.cg-tooltip-arrow-top::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  top: 0;\n  border: 4px solid transparent;\n  border-top: 0;\n  border-bottom: 4px solid #f7f7f7;\n  transform: translate(-50%, -100%);\n}\n/* Default right arrow for tooltip */\n.cg-tooltip-arrow-right::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  right: 0;\n  top: 50%;\n  border: 5px solid transparent;\n  border-right: 0;\n  border-left: 5px solid #938e8e;\n  transform: translate(100%, -50%);\n}\n.cg-tooltip-arrow-right::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  right: 0;\n  top: 50%;\n  border: 4px solid transparent;\n  border-right: 0;\n  border-left: 4px solid #f7f7f7;\n  transform: translate(100%, -50%);\n}\n/* Default bottom arrow for tooltip */\n.cg-tooltip-arrow-bottom::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  bottom: 0px;\n  border: 5px solid transparent;\n  border-bottom: 0;\n  border-top: 5px solid #938e8e;\n  transform: translate(-50%, 100%);\n  z-index: 10000;\n}\n.cg-tooltip-arrow-bottom::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  bottom: 0;\n  border: 4px solid transparent;\n  border-bottom: 0;\n  border-top: 4px solid #f7f7f7;\n  transform: translate(-50%, 100%);\n  z-index: 10000;\n}\n/* Tooltip item name */\n/* Tooltip item value */\n/* .cg-tooltip-item-value */\n/* Tooltip item value */\n.cg-tooltip-item-unit {\n  text-transform: none;\n}\n\n.cg-tooltip-item-name {\n    text-transform: capitalize;\n    white-space: nowrap;\n    vertical-align: middle;\n    font-size: 13px;\n}\n.cg-tooltip-row {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  white-space: pre-wrap;\n  font-size: 12px;\n  line-height: 100%;\n  margin: 1px 0;\n}\n.cg-tooltip-title {\n  font-size: 13px;\n  height: 14px;\n  text-transform: capitalize;\n}\n.cg-tooltip-title .cg-tooltip-symbol {\n  margin-right: 0 !important;\n}\n.cg-tooltip-title-name {\n  vertical-align: middle;\n}\n.cg-tooltip-row + .cg-tooltip-row {\n  margin-top: 4px;\n}\n.cg-tooltip-row.cg-tooltip-title + .cg-tooltip-row {\n  margin-top: 5px;\n}\n.cg-tooltip-item-value + .cg-tooltip-item-unit {\n    margin-left: 1px;\n}\n/* Tooltip symbol */\n.cg-tooltip-symbol-cell {\n  display: inline-flex;\n  min-width: 13px; /* 10px size + 3px margin */\n}\n.cg-tooltip-symbol {\n  margin-right: 3px;\n  background-color: transparent;\n  display: block;\n}\n.cg-tooltip-symbol > img {\n  display: block;\n}\n.cg-tooltip-list-cell {\n  display: inline-flex;\n}\n.cg-tooltip-list-symbol {\n  display: block;\n  margin-right: 3px;\n  width: 6px;\n  height: 6px;\n  vertical-align: middle;\n  border-radius: 50%;\n  border: 1px solid rgba(0,0,0,.4);\n}\n.cg-tooltip-symbol-legacy {\n  border-radius: 4px;\n  margin-right: 5px;\n  height: 8px;\n  width: 8px;\n  display: inline-block;\n}\n.cg-tooltip-title-legacy {\n  font-weight: 900;\n}\n\n/* Tooltip symbol circle */\n.cg-tooltip-symbol.circle {\n  height: 10px;\n  width: 10px;\n  display: inline-block;\n  border-radius: 50%;\n  border: 1px solid rgba(0,0,0,.4);\n}\n/* Tooltip symbol line */\n.cg-tooltip-symbol.line {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    transform: scale(1.2, 0.2);\n}\n/* Tooltip symbol diamond */\n.cg-tooltip-symbol.diamond {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    transform: rotate(45deg);\n    border-radius: 0px;\n}\n/* Tooltip symbol square */\n.cg-tooltip-symbol.square {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    border-radius: 0px;\n    border: 1px solid rgba(0,0,0,.4);\n}\n\n","lang":"css"},"children":[]}]}]},{"$$mdtype":"Tag","name":"iframe","attributes":{"src":"https://dc2-documentation.s3.amazonaws.com/documentation/slb-docs-test/5.0/examples/vue/tutorials/index.html#/WellLog/DataAndTemplates/RealTimeServer/realTimeServer?section=realtime&extract=true","width":"100%","height":"542.5px","style":{"border":"none"}},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"socketio-communication","__idx":3},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/WellLog/DataAndTemplates/RealTimeServer/realTimeServer#socketio"},"children":["#"]}," Socket.IO Communication"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This example shows implementation of real time data using Sockets. A socket connection is established with server. The client then listens to an event which sends alerts when new data is available on the server. Whenever client decides that it needs the data, it emits an event requesting for data of a specific range."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Events:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["connect"]},": Fired upon a successful connection"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_limits"]},": Fired by client on initialization, request for known limits"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["limits"]},": Fired by server when known limits are sent"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["data_range_changed"]},": Fired by server when new data is available"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["get_real_time_data"]},": Fired by client when data is needed, along with event requested range is sent"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["real_time_data"]},": Fired by server when data requested is sent"]}]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"main","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"import { Plot } from \"@int/geotoolkit/plot/Plot.ts\";\nimport { HeaderType } from \"@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts\";\nimport { TrackType } from \"@int/geotoolkit/welllog/TrackType.ts\";\nimport { Events as AbstractScrollEvents } from \"@int/geotoolkit/controls/tools/scroll/AbstractScroll.ts\";\nimport { Events as PanningEvents } from \"@int/geotoolkit/controls/tools/Panning.ts\";\nimport { Range } from \"@int/geotoolkit/util/Range.ts\";\nimport { KnownColors } from \"@int/geotoolkit/util/ColorUtil.ts\";\nimport { LogData } from \"@int/geotoolkit/welllog/data/LogData.ts\";\nimport { LogCurve } from \"@int/geotoolkit/welllog/LogCurve.ts\";\nimport { SocketData } from \"/src/code/WellLog/DataAndTemplates/RealTimeServer/common/realtimeSocketData.ts\";\nimport { createWellLogWidget } from \"/src/code/WellLog/utils/common.ts\";\nconst defaults = {\n  zoomInScale: 5 / 4,\n  zoomOutScale: 4 / 5\n};\nconst SCALE_COEFFICIENT = 1 / 200;\nconst INDEX_TRACK_WIDTH = 60;\nconst SERVER_HOST = \"http://localhost:3003\";\nclass SocketDemo {\n  constructor(options) {\n    this.scaleFactor = 1;\n    this.widget = this.createWidget();\n    this.plot = new Plot({\n      canvaselement: options.canvas,\n      root: this.widget\n    });\n  }\n  dispose() {\n    const data = this.getData();\n    if (data) {\n      data.stopRealTime();\n    }\n    if (this.plot) {\n      this.plot.dispose();\n    }\n  }\n  getData() {\n    return this.widget != null ? this.widget.getData() : null;\n  }\n  createWidget() {\n    const widget = createWellLogWidget({\n      \"indextype\": \"time\",\n      \"indexunit\": \"ms\"\n    });\n    widget.setAxisHeaderType(HeaderType.Simple);\n    const source = new SocketData(widget);\n    const addDataToWidget = () => {\n      widget.getDataBinding().add(source.getBindingFunction());\n      widget.setData(source);\n      widget.addTrack(TrackType.IndexTrack).setWidth(INDEX_TRACK_WIDTH);\n      widget.addTrack(TrackType.LinearTrack).addChild([\n        this.createCurve(\"CALI\", source).setLineStyle(KnownColors.Green).setNormalizationLimits(100, 150)\n      ]);\n      widget.addTrack(TrackType.IndexTrack).setWidth(INDEX_TRACK_WIDTH);\n      widget.addTrack(TrackType.LogTrack).addChild([\n        this.createCurve(\"GR\", source).setLineStyle(KnownColors.Red).setNormalizationLimits(0, 30)\n      ]);\n      const lowerLimit = widget.getData().getLowerLimit();\n      widget.setDepthLimits(new Range(lowerLimit, lowerLimit));\n      widget.setVisibleDepthLimits(new Range(lowerLimit, lowerLimit));\n      widget.getToolByName(\"TrackPlotVerticalScroll\").on(AbstractScrollEvents.onScrollEnd, this.widgetScrolled.bind(this));\n      widget.getToolByName(\"TrackPanning\").on(PanningEvents.onPanningEnd, this.widgetScrolled.bind(this));\n      widget.scale(SCALE_COEFFICIENT);\n      source.startRealTime();\n    };\n    source.initialize(1e3, addDataToWidget, SERVER_HOST);\n    return widget;\n  }\n  createCurve(mnemonic, source) {\n    source = source || this.getData();\n    let d = source.getCurveSource(mnemonic);\n    if (d == null) {\n      d = new LogData(mnemonic);\n    }\n    const curve = new LogCurve(d, true);\n    curve.setId(mnemonic);\n    return curve;\n  }\n  widgetScrolled() {\n    this.getData().widgetScrolled();\n  }\n  createSocketData() {\n    const socketData = new SocketData(this.widget);\n    socketData.initialize(1e3, () => {\n    }, SERVER_HOST);\n  }\n  scrollDownWidget() {\n    const limits = this.widget.getDepthLimits();\n    const high = limits.getHigh();\n    const vdl = this.widget.getTrackContainer().getVisibleDepthLimits();\n    if (vdl.getLow() > 0 && vdl.getHigh() > 0) {\n      this.widget.getTrackContainer().scrollToDepth(high);\n    }\n  }\n  zoomIn() {\n    this.widget.scale(defaults.zoomInScale);\n    this.scaleFactor *= defaults.zoomOutScale;\n    this.scrollDownWidget();\n  }\n  zoomOut() {\n    this.widget.scale(defaults.zoomOutScale);\n    this.scaleFactor /= defaults.zoomOutScale;\n    this.scrollDownWidget();\n  }\n  zoomReset() {\n    this.widget.scale(this.scaleFactor);\n    this.scaleFactor = 1;\n    this.scrollDownWidget();\n  }\n  startRealTime() {\n    this.getData().setRealTime(true).startRealTime();\n  }\n  stopRealTime() {\n    this.getData().setRealTime(false);\n  }\n  toggleRealTime() {\n    this.isRealTime() ? this.stopRealTime() : this.startRealTime();\n  }\n  isRealTime() {\n    return this.getData().isRunning();\n  }\n}\nexport { SocketDemo };\n\ncreateScene();\n\n","lang":"ts"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"css","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"css","header":{"controls":{"copy":{}}},"source":"\n.cg-tooltip-holder {\n  position: relative;\n}\n\n.cg-tooltip {\n  position: absolute;\n  display: block;\n  padding: 2px 12px 3px 7px;\n  overflow: visible !important;\n  font-family: Roboto, Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  background: white !important;\n  opacity: 0.9;\n  color: #333333;\n  border: solid 1px gray;\n  border-radius: 5px;\n  text-align: left;\n  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n  border-radius: 5px;\n  margin: 0 !important;\n  z-index: 10000;\n  max-width: 400px;\n  text-wrap: normal !important;\n  white-space: normal !important;\n}\n/* Default setting for tooltip */\n.cg-tooltip-container {\n  position: absolute;\n  display: block;\n  overflow: visible !important;\n  font-family: Roboto, Helvetica, Arial, sans-serif;\n  font-size: 12px;\n  padding: 3px 7px;\n  background: #f7f7f7;\n  color: #333333;\n  border: 1px solid #938e8e;\n  opacity: 0.8;\n  text-align: left;\n  box-shadow: 3px 3px 10px #888;\n  margin: 0 !important;\n  z-index: 10000;\n  max-width: 400px;\n  text-wrap: normal !important;\n  white-space: normal !important;\n  user-select: none;\n}\n@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n  .cg-tooltip-container {\n    border-radius: 0;\n  }\n}\n/* Default left arrow for tooltip */\n.cg-tooltip-arrow-left::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 0;\n  top: 50%;\n  border: 5px solid transparent;\n  border-left: 0;\n  border-right: 5px solid  #938e8e;\n  transform: translate(calc(-100%), -50%);\n}\n.cg-tooltip-arrow-left::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 0;\n  top: 50%;\n  border: 4px solid transparent;\n  border-left: 0;\n  border-right: 4px solid #f7f7f7;\n  transform: translate(calc(-100%), -50%);\n}\n/* Default top arrow for tooltip */\n.cg-tooltip-arrow-top::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  top: 0;\n  border: 5px solid transparent;\n  border-top: 0;\n  border-bottom: 5px solid #938e8e;\n  transform: translate(-50%, -100%);\n}\n.cg-tooltip-arrow-top::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  top: 0;\n  border: 4px solid transparent;\n  border-top: 0;\n  border-bottom: 4px solid #f7f7f7;\n  transform: translate(-50%, -100%);\n}\n/* Default right arrow for tooltip */\n.cg-tooltip-arrow-right::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  right: 0;\n  top: 50%;\n  border: 5px solid transparent;\n  border-right: 0;\n  border-left: 5px solid #938e8e;\n  transform: translate(100%, -50%);\n}\n.cg-tooltip-arrow-right::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  right: 0;\n  top: 50%;\n  border: 4px solid transparent;\n  border-right: 0;\n  border-left: 4px solid #f7f7f7;\n  transform: translate(100%, -50%);\n}\n/* Default bottom arrow for tooltip */\n.cg-tooltip-arrow-bottom::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  bottom: 0px;\n  border: 5px solid transparent;\n  border-bottom: 0;\n  border-top: 5px solid #938e8e;\n  transform: translate(-50%, 100%);\n  z-index: 10000;\n}\n.cg-tooltip-arrow-bottom::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  bottom: 0;\n  border: 4px solid transparent;\n  border-bottom: 0;\n  border-top: 4px solid #f7f7f7;\n  transform: translate(-50%, 100%);\n  z-index: 10000;\n}\n/* Tooltip item name */\n/* Tooltip item value */\n/* .cg-tooltip-item-value */\n/* Tooltip item value */\n.cg-tooltip-item-unit {\n  text-transform: none;\n}\n\n.cg-tooltip-item-name {\n    text-transform: capitalize;\n    white-space: nowrap;\n    vertical-align: middle;\n    font-size: 13px;\n}\n.cg-tooltip-row {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  white-space: pre-wrap;\n  font-size: 12px;\n  line-height: 100%;\n  margin: 1px 0;\n}\n.cg-tooltip-title {\n  font-size: 13px;\n  height: 14px;\n  text-transform: capitalize;\n}\n.cg-tooltip-title .cg-tooltip-symbol {\n  margin-right: 0 !important;\n}\n.cg-tooltip-title-name {\n  vertical-align: middle;\n}\n.cg-tooltip-row + .cg-tooltip-row {\n  margin-top: 4px;\n}\n.cg-tooltip-row.cg-tooltip-title + .cg-tooltip-row {\n  margin-top: 5px;\n}\n.cg-tooltip-item-value + .cg-tooltip-item-unit {\n    margin-left: 1px;\n}\n/* Tooltip symbol */\n.cg-tooltip-symbol-cell {\n  display: inline-flex;\n  min-width: 13px; /* 10px size + 3px margin */\n}\n.cg-tooltip-symbol {\n  margin-right: 3px;\n  background-color: transparent;\n  display: block;\n}\n.cg-tooltip-symbol > img {\n  display: block;\n}\n.cg-tooltip-list-cell {\n  display: inline-flex;\n}\n.cg-tooltip-list-symbol {\n  display: block;\n  margin-right: 3px;\n  width: 6px;\n  height: 6px;\n  vertical-align: middle;\n  border-radius: 50%;\n  border: 1px solid rgba(0,0,0,.4);\n}\n.cg-tooltip-symbol-legacy {\n  border-radius: 4px;\n  margin-right: 5px;\n  height: 8px;\n  width: 8px;\n  display: inline-block;\n}\n.cg-tooltip-title-legacy {\n  font-weight: 900;\n}\n\n/* Tooltip symbol circle */\n.cg-tooltip-symbol.circle {\n  height: 10px;\n  width: 10px;\n  display: inline-block;\n  border-radius: 50%;\n  border: 1px solid rgba(0,0,0,.4);\n}\n/* Tooltip symbol line */\n.cg-tooltip-symbol.line {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    transform: scale(1.2, 0.2);\n}\n/* Tooltip symbol diamond */\n.cg-tooltip-symbol.diamond {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    transform: rotate(45deg);\n    border-radius: 0px;\n}\n/* Tooltip symbol square */\n.cg-tooltip-symbol.square {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    border-radius: 0px;\n    border: 1px solid rgba(0,0,0,.4);\n}\n\n","lang":"css"},"children":[]}]}]},{"$$mdtype":"Tag","name":"iframe","attributes":{"src":"https://dc2-documentation.s3.amazonaws.com/documentation/slb-docs-test/5.0/examples/vue/tutorials/index.html#/WellLog/DataAndTemplates/RealTimeServer/realTimeServer?section=socketio&extract=true","width":"100%","height":"542.5px","style":{"border":"none"}},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"log2d-example","__idx":4},"children":[{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#/WellLog/DataAndTemplates/RealTimeServer/realTimeServer#log2d"},"children":["#"]}," Log2D Example"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This example shows implementation of real time data using HTTP requests to server. The server supports three requests:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Get ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"http://localhost:3003/log2d/limits"},"children":["limits"]}," of data"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Get ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"http://localhost:3003/log2d/data?low=971672996800&high=971673077000&time=971672996800&historical=false"},"children":["real-time data points"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Get ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"http://localhost:3003/log2d/data?low=971672875800&high=971672956000&time=&historical=true"},"children":["historical data points"]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The client data source extends ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["geotoolkit/data/DataSource"]}," and requests real time data, sending the last data point received, or historical data, when widget has been scrolled or panned;"]},{"$$mdtype":"Tag","name":"Tabs","attributes":{"size":"medium"},"children":[{"$$mdtype":"Tag","name":"div","attributes":{"label":"main","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"ts","header":{"controls":{"copy":{}}},"source":"import { Plot } from \"@int/geotoolkit/plot/Plot.ts\";\nimport { HeaderType } from \"@int/geotoolkit/welllog/header/LogAxisVisualHeader.ts\";\nimport { TrackType } from \"@int/geotoolkit/welllog/TrackType.ts\";\nimport { Log2DVisual, PlotTypes } from \"@int/geotoolkit/welllog/Log2DVisual.ts\";\nimport { Events as AbstractScrollEvents } from \"@int/geotoolkit/controls/tools/scroll/AbstractScroll.ts\";\nimport { Events as PanningEvents } from \"@int/geotoolkit/controls/tools/Panning.ts\";\nimport { Range } from \"@int/geotoolkit/util/Range.ts\";\nimport { Log2DVisualData } from \"@int/geotoolkit/welllog/data/Log2DVisualData.ts\";\nimport { DefaultColorProvider } from \"@int/geotoolkit/util/DefaultColorProvider.ts\";\nimport { Timer } from \"@int/geotoolkit/util/Timer.ts\";\nimport { KnownColors } from \"@int/geotoolkit/util/ColorUtil.ts\";\nimport { Log2DRealTimeData } from \"/src/code/WellLog/DataAndTemplates/RealTimeServer/common/log2dRealtimeData.ts\";\nimport { createWellLogWidget } from \"/src/code/WellLog/utils/common.ts\";\nconst defaults = {\n  zoomInScale: 5 / 4,\n  zoomOutScale: 4 / 5\n};\nconst SCALE_COEFFICIENT = 1 / 200;\nconst INDEX_TRACK_WIDTH = 60;\nconst REFRESH_TIME = 1e3;\nconst INTERVAL = 1e3;\nclass Log2DDemo {\n  constructor(options) {\n    this.isRunning = false;\n    this.timer = null;\n    this.scaleFactor = 1;\n    this.widget = this.createWidget();\n    this.plot = new Plot({\n      canvaselement: options.canvas,\n      root: this.widget\n    });\n  }\n  dispose() {\n    if (this.timer) {\n      this.timer.stop();\n    }\n    if (this.plot) {\n      this.plot.dispose();\n    }\n  }\n  createWidget() {\n    const widget = createWellLogWidget({\n      \"indextype\": \"time\",\n      \"indexunit\": \"ms\"\n    });\n    widget.setAxisHeaderType(HeaderType.Simple);\n    const onCreateLog2D = (err, dataSource) => {\n      widget.setData(dataSource);\n      widget.addTrack(TrackType.IndexTrack).setWidth(INDEX_TRACK_WIDTH);\n      widget.addTrack(TrackType.LinearTrack).addChild([\n        this.create2DVisual(\"log1\").setPlotType(PlotTypes.Step)\n      ]);\n      widget.getToolByName(\"TrackPlotVerticalScroll\").on(AbstractScrollEvents.onScrollEnd, this.widgetScrolled.bind(this));\n      widget.getToolByName(\"TrackPanning\").on(PanningEvents.onPanningEnd, this.widgetScrolled.bind(this));\n      widget.setDepthLimits(new Range(dataSource.getLowerLimit(), dataSource.getLowerLimit())).setVisibleDepthLimits(new Range(dataSource.getLowerLimit(), dataSource.getLowerLimit() + 1e3)).scale(SCALE_COEFFICIENT);\n      this.startRealTime();\n    };\n    this.createLog2DData(onCreateLog2D);\n    return widget;\n  }\n  create2DVisual(id) {\n    const visual = new Log2DVisual().setId(id).setData(new Log2DVisualData());\n    const widgetData = this.widget.getData();\n    const min = widgetData.getMinValue();\n    const max = widgetData.getMaxValue();\n    const delt = (max - min) / 4;\n    const colors = new DefaultColorProvider().addColor(min, KnownColors.Green).addColor(min + delt, KnownColors.Yellow).addColor(min + 2 * delt, KnownColors.Orange).addColor(max - delt, KnownColors.Blue).addColor(max, KnownColors.Red);\n    visual.setColorProvider(colors);\n    this.widget.getData().bindVisual(visual);\n    return visual;\n  }\n  widgetScrolled() {\n    this.stopRealTime();\n    this.widget.getData().widgetScrolled(this.widget.getVisibleDepthLimits());\n  }\n  scrollDownWidget() {\n    const limits = this.widget.getDepthLimits();\n    const high = limits.getHigh();\n    const vdl = this.widget.getTrackContainer().getVisibleDepthLimits();\n    if (vdl.getLow() > 0 && vdl.getHigh() > 0) {\n      this.widget.getTrackContainer().scrollToDepth(high);\n    }\n  }\n  startRealTime() {\n    this.timer.start();\n    this.isRunning = true;\n  }\n  stopRealTime() {\n    this.timer.stop();\n    this.isRunning = false;\n  }\n  createLog2DData(cb) {\n    const ds = new Log2DRealTimeData();\n    ds.initialize(INTERVAL, (err, dataSource) => {\n      if (err) {\n        return cb(err);\n      }\n      this.timer = new Timer(REFRESH_TIME, () => {\n        const visibleLimits = this.widget.getVisibleDepthLimits();\n        const depthLimits = this.widget.getDepthLimits();\n        if (this.isRunning) {\n          dataSource.getData(visibleLimits, depthLimits.getHigh(), () => {\n            depthLimits.setRange(depthLimits.getLow(), dataSource.getHigherLimit());\n            visibleLimits.setRange(visibleLimits.getLow(), dataSource.getHigherLimit());\n            this.widget.setDepthLimits(depthLimits);\n            this.scrollDownWidget();\n          });\n        }\n      });\n      return cb(null, dataSource);\n    });\n  }\n  zoomIn() {\n    this.widget.scale(defaults.zoomInScale);\n    this.scaleFactor *= defaults.zoomOutScale;\n    this.scrollDownWidget();\n  }\n  zoomOut() {\n    this.widget.scale(defaults.zoomOutScale);\n    this.scaleFactor /= defaults.zoomOutScale;\n    this.scrollDownWidget();\n  }\n  zoomReset() {\n    this.widget.scale(this.scaleFactor);\n    this.scaleFactor = 1;\n    this.scrollDownWidget();\n  }\n  toggleRealTime() {\n    this.isRunning ? this.stopRealTime() : this.startRealTime();\n  }\n  isRealTime() {\n    return this.isRunning;\n  }\n}\nexport { Log2DDemo };\n\ncreateScene();\n\n","lang":"ts"},"children":[]}]},{"$$mdtype":"Tag","name":"div","attributes":{"label":"css","disable":false},"children":[{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"css","header":{"controls":{"copy":{}}},"source":"\n.cg-tooltip-holder {\n  position: relative;\n}\n\n.cg-tooltip {\n  position: absolute;\n  display: block;\n  padding: 2px 12px 3px 7px;\n  overflow: visible !important;\n  font-family: Roboto, Helvetica, Arial, sans-serif;\n  font-size: 13px;\n  background: white !important;\n  opacity: 0.9;\n  color: #333333;\n  border: solid 1px gray;\n  border-radius: 5px;\n  text-align: left;\n  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);\n  border-radius: 5px;\n  margin: 0 !important;\n  z-index: 10000;\n  max-width: 400px;\n  text-wrap: normal !important;\n  white-space: normal !important;\n}\n/* Default setting for tooltip */\n.cg-tooltip-container {\n  position: absolute;\n  display: block;\n  overflow: visible !important;\n  font-family: Roboto, Helvetica, Arial, sans-serif;\n  font-size: 12px;\n  padding: 3px 7px;\n  background: #f7f7f7;\n  color: #333333;\n  border: 1px solid #938e8e;\n  opacity: 0.8;\n  text-align: left;\n  box-shadow: 3px 3px 10px #888;\n  margin: 0 !important;\n  z-index: 10000;\n  max-width: 400px;\n  text-wrap: normal !important;\n  white-space: normal !important;\n  user-select: none;\n}\n@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {\n  .cg-tooltip-container {\n    border-radius: 0;\n  }\n}\n/* Default left arrow for tooltip */\n.cg-tooltip-arrow-left::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 0;\n  top: 50%;\n  border: 5px solid transparent;\n  border-left: 0;\n  border-right: 5px solid  #938e8e;\n  transform: translate(calc(-100%), -50%);\n}\n.cg-tooltip-arrow-left::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 0;\n  top: 50%;\n  border: 4px solid transparent;\n  border-left: 0;\n  border-right: 4px solid #f7f7f7;\n  transform: translate(calc(-100%), -50%);\n}\n/* Default top arrow for tooltip */\n.cg-tooltip-arrow-top::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  top: 0;\n  border: 5px solid transparent;\n  border-top: 0;\n  border-bottom: 5px solid #938e8e;\n  transform: translate(-50%, -100%);\n}\n.cg-tooltip-arrow-top::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  top: 0;\n  border: 4px solid transparent;\n  border-top: 0;\n  border-bottom: 4px solid #f7f7f7;\n  transform: translate(-50%, -100%);\n}\n/* Default right arrow for tooltip */\n.cg-tooltip-arrow-right::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  right: 0;\n  top: 50%;\n  border: 5px solid transparent;\n  border-right: 0;\n  border-left: 5px solid #938e8e;\n  transform: translate(100%, -50%);\n}\n.cg-tooltip-arrow-right::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  right: 0;\n  top: 50%;\n  border: 4px solid transparent;\n  border-right: 0;\n  border-left: 4px solid #f7f7f7;\n  transform: translate(100%, -50%);\n}\n/* Default bottom arrow for tooltip */\n.cg-tooltip-arrow-bottom::before {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  bottom: 0px;\n  border: 5px solid transparent;\n  border-bottom: 0;\n  border-top: 5px solid #938e8e;\n  transform: translate(-50%, 100%);\n  z-index: 10000;\n}\n.cg-tooltip-arrow-bottom::after {\n  content: '';\n  position: absolute;\n  display: block;\n  width: 0px;\n  left: 50%;\n  bottom: 0;\n  border: 4px solid transparent;\n  border-bottom: 0;\n  border-top: 4px solid #f7f7f7;\n  transform: translate(-50%, 100%);\n  z-index: 10000;\n}\n/* Tooltip item name */\n/* Tooltip item value */\n/* .cg-tooltip-item-value */\n/* Tooltip item value */\n.cg-tooltip-item-unit {\n  text-transform: none;\n}\n\n.cg-tooltip-item-name {\n    text-transform: capitalize;\n    white-space: nowrap;\n    vertical-align: middle;\n    font-size: 13px;\n}\n.cg-tooltip-row {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  white-space: pre-wrap;\n  font-size: 12px;\n  line-height: 100%;\n  margin: 1px 0;\n}\n.cg-tooltip-title {\n  font-size: 13px;\n  height: 14px;\n  text-transform: capitalize;\n}\n.cg-tooltip-title .cg-tooltip-symbol {\n  margin-right: 0 !important;\n}\n.cg-tooltip-title-name {\n  vertical-align: middle;\n}\n.cg-tooltip-row + .cg-tooltip-row {\n  margin-top: 4px;\n}\n.cg-tooltip-row.cg-tooltip-title + .cg-tooltip-row {\n  margin-top: 5px;\n}\n.cg-tooltip-item-value + .cg-tooltip-item-unit {\n    margin-left: 1px;\n}\n/* Tooltip symbol */\n.cg-tooltip-symbol-cell {\n  display: inline-flex;\n  min-width: 13px; /* 10px size + 3px margin */\n}\n.cg-tooltip-symbol {\n  margin-right: 3px;\n  background-color: transparent;\n  display: block;\n}\n.cg-tooltip-symbol > img {\n  display: block;\n}\n.cg-tooltip-list-cell {\n  display: inline-flex;\n}\n.cg-tooltip-list-symbol {\n  display: block;\n  margin-right: 3px;\n  width: 6px;\n  height: 6px;\n  vertical-align: middle;\n  border-radius: 50%;\n  border: 1px solid rgba(0,0,0,.4);\n}\n.cg-tooltip-symbol-legacy {\n  border-radius: 4px;\n  margin-right: 5px;\n  height: 8px;\n  width: 8px;\n  display: inline-block;\n}\n.cg-tooltip-title-legacy {\n  font-weight: 900;\n}\n\n/* Tooltip symbol circle */\n.cg-tooltip-symbol.circle {\n  height: 10px;\n  width: 10px;\n  display: inline-block;\n  border-radius: 50%;\n  border: 1px solid rgba(0,0,0,.4);\n}\n/* Tooltip symbol line */\n.cg-tooltip-symbol.line {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    transform: scale(1.2, 0.2);\n}\n/* Tooltip symbol diamond */\n.cg-tooltip-symbol.diamond {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    transform: rotate(45deg);\n    border-radius: 0px;\n}\n/* Tooltip symbol square */\n.cg-tooltip-symbol.square {\n    height: 10px;\n    width: 10px;\n    display: inline-block;\n    border-radius: 0px;\n    border: 1px solid rgba(0,0,0,.4);\n}\n\n","lang":"css"},"children":[]}]}]},{"$$mdtype":"Tag","name":"iframe","attributes":{"src":"https://dc2-documentation.s3.amazonaws.com/documentation/slb-docs-test/5.0/examples/vue/tutorials/index.html#/WellLog/DataAndTemplates/RealTimeServer/realTimeServer?section=log2d&extract=true","width":"100%","height":"542.5px","style":{"border":"none"}},"children":[]}]},"headings":[{"value":"Real-Time Server","id":"real-time-server","depth":1},{"value":"Show Communication Between Widget and Server","id":"show-communication-between-widget-and-server","depth":3},{"value":"HTTP communication","id":"http-communication","depth":3},{"value":"Socket.IO Communication","id":"socketio-communication","depth":3},{"value":"Log2D Example","id":"log2d-example","depth":3}],"frontmatter":{"title":"Real-Time Server","seo":{"title":"Real-Time Server"}},"lastModified":"2026-02-11T19:54:32.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/solutions/geotoolkit/tutorials/well-log/data-and-templates/real-time-server","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}