Observing Watson Studio Notebooks with Instana

  1. At Notebook startup an environment is created (if the required environment not already available)
  2. When creating a Notebook in the underlying OpenShift environment a deployment, replicaset, pod and a few other configuration items are dynamically created
  3. The created pod hosts the required environment and runs the environment as a “conda” managed Python environment
require("dotenv").config();

const express = require("express");
const https = require("https");

const ACCESS_TOKEN = process.env.ACCESS_TOKEN;
const API_HOST = process.env.API_HOST;
const API_PORT = process.env.API_PORT;
const NAMESPACE = process.env.NAMESPACE;
const port = process.env.PORT || 3000;

const app = express();

app.get("/health", (req, res) => {
console.log("hit GET /health");
res.status(200);
});

app.get("/hostIP/:hostname", (req, res) => {
console.log("hit GET /hostIP");
let host = req.params.hostname;
let path = "/api/v1/namespaces/" + NAMESPACE + "/pods/" + host + "/status";
let api_url = "https://" + API_HOST + ":" + API_PORT + path;

var options = {
"method": "GET",
"hostname": API_HOST,
"port": API_PORT,
"path": path,
headers: {
'Authorization': 'Bearer ' + ACCESS_TOKEN
}
}

var request = https.get(options, function(response) {
var chunks = [];
response.on("data", function (chunk) {
chunks.push(chunk);
});

response.on("error", function (error) {
console.log(error);
});

response.on("end", function() {
var body = Buffer.concat(chunks);
var data = JSON.parse(body.toString())
res.json({
hostIP : data.status.hostIP
});
});

});
});

app.listen(port, () => {
console.log(`Listening on port ${port}`);
});
  1. ACCESS_TOKEN : The security token to allow permission to invoke the OpenShift REST API call. More details on this below
  2. API_HOST : The name of the host where the OpenShift API service is hosted
  3. API_PORT : The port that the OpenShift API service is listening on
  4. NAMESPACE : The namespace for CloudPak for Data as this is where the dynamically created pod will exist
echo "Create Namespace"
oc new-project hostip
echo "Create Service Account"
oc create sa hostname
echo "Add policy NB: change this to match namespace where CloudPak for Data is installed"
oc policy add-role-to-group view system:serviceaccount:hostname -n zen-40
kind: Deployment
apiVersion: apps/v1
metadata:
name: hostip
namespace: hostip
spec:
replicas: 1
selector:
matchLabels:
app: hostipd
template:
metadata:
labels:
app: hostip
spec:
containers:
- name: hostip
image: "<Container registry>/hostip:1"
ports:
- containerPort: 3000
protocol: TCP
env:
- name: ACCESS_TOKEN
valueFrom:
secretKeyRef:
name: <name of service account secret>
key: token
- name: API_HOST
value: <API Host>
- name: API_PORT
value: 32318
- name: NAMESPACE
value: zen-40
kind: Service
apiVersion: v1
metadata:
name: hostip
namespace: hostip
spec:
ports:
- protocol: TCP
port: 3000
targetPort: 3000
selector:
app: hostip
Instana testing Notebook
Instana Trace View
import oshostname = os.environ['HOSTNAME']
print(hostname)
import requests
import json
url = 'http://hostip.hostip.svc.cluster.local:3000/hostIP/'+hostname
req = requests.get(url)
data = req.json()
hostIP = data['hostIP']
%env AUTOWRAPT_BOOTSTRAP instana
%env INSTANA_AGENT_HOST {hostIP}
%env INSTANA_AGENT_PORT 42699
%env INSTANA_SERVICE_NAME instana-test
%env INSTANA_PROCESS_NAME studio-notebook
%env INSTANA_DEBUG true

!pip install instana
import instana
import time
import opentracing as ot
import opentracing.ext.tags as ext
time.sleep(10)
nb_span = ot.tracer.start_active_span('Instana Test')
def simple():
with ot.tracer.start_active_span('asteroid') as pscope:
pscope.span.set_tag(ext.COMPONENT, "Python simple example app")
pscope.span.set_tag(ext.SPAN_KIND, ext.SPAN_KIND_RPC_SERVER)
pscope.span.set_tag(ext.PEER_HOSTNAME, "localhost")
pscope.span.set_tag(ext.HTTP_URL, "/python/simple/one")
pscope.span.set_tag(ext.HTTP_METHOD, "GET")
pscope.span.set_tag(ext.HTTP_STATUS_CODE, 200)
pscope.span.set_tag("Pete's RequestId", "0xdeadbeef")
pscope.span.set_tag("X-Peter-Header", "👀")
pscope.span.set_tag("X-Job-Id", "1947282")
time.sleep(.2)
with ot.tracer.start_active_span('spacedust', child_of=pscope.span) as cscope:
cscope.span.set_tag(ext.SPAN_KIND, ext.SPAN_KIND_RPC_CLIENT)
cscope.span.set_tag(ext.PEER_HOSTNAME, "localhost")
cscope.span.set_tag(ext.HTTP_URL, "/python/simple/two")
cscope.span.set_tag(ext.HTTP_METHOD, "POST")
cscope.span.set_tag(ext.HTTP_STATUS_CODE, 204)
cscope.span.set_baggage_item("someBaggage", "someValue")
time.sleep(.1)

simple()
nb_span.span.finish()

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Tony Hickman

Tony Hickman

I‘ve worked for IBM all of my career and am an avid technologist who is keen to get his hands dirty. My role affords me this opportunity and I share what I can