Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,31 @@ If you use uWSGI in forking workers mode, you must specify `--lazy-apps` (or `la

The instana package will automatically collect key metrics from your Python processes. Just install and go.

## Want End User Monitoring?

Instana provides deep end user monitoring that links server side traces with browser events to give you a complete view from server to browser.

For Python templates and views, get your EUM API key from your Instana dashboard and you can call `instana.helpers.eum_snippet(api_key='abc')` from within your layout file. This will output
a small javascript snippet of code to instrument browser events. It's based on [Weasel](https://github.com/instana/weasel). Check it out.

As an example, you could do the following:

```python
from instana.helpers import eum_snippet

instana.api_key = 'abc'
meta_kvs = { 'username': user.name }

# This will return a string containing the EUM javascript for the layout or view.
eum_snippet(meta=meta_kvs)
```

The optional second argument to `eum_snippet()` is a hash of metadata key/values that will be reported along with the browser instrumentation.

![Instana EUM example with metadata](https://s3.amazonaws.com/instana/Instana+Gameface+EUM+with+metadata+2016-12-22+at+15.32.01.png)

See also the [End User Monitoring](https://docs.instana.io/products/website_monitoring/#configuration) in the Instana documentation portal.

## OpenTracing

This Python package supports [OpenTracing](http://opentracing.io/). When using this package, the OpenTracing tracer (`opentracing.tracer`) is automatically set to the `InstanaTracer`.
Expand Down
3 changes: 3 additions & 0 deletions instana/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,8 @@
# instana.service_name = "myservice"
service_name = None

# User configurable EUM API key for instana.helpers.eum_snippet()
eum_api_key = ''

if "INSTANA_SERVICE_NAME" in os.environ:
service_name = os.environ["INSTANA_SERVICE_NAME"]
10 changes: 10 additions & 0 deletions instana/eum.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script>
(function(i,s,o,g,r,a,m){i['InstanaEumObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//eum.instana.io/eum.min.js','ineum');
ineum('apiKey', '$eum_api_key');
ineum('traceId', '$trace_id');

$meta_kvs
</script>
12 changes: 12 additions & 0 deletions instana/eum_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script nonce="68afd870-ae85-48c6-9689-9a5c359d5a1f">
(function(i,s,o,g,r,a,m){i['InstanaEumObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//eum-test-fullstack-0-us-west-2.instana.io/eum.min.js','ineum');

ineum('reportingUrl', '//eum-test-fullstack-0-us-west-2.instana.io');
ineum('apiKey', '$eum_api_key');
ineum('traceId', '$trace_id');

$meta_kvs
</script>
100 changes: 100 additions & 0 deletions instana/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import os
from string import Template
from instana import internal_tracer, eum_api_key as global_eum_api_key
from instana.log import logger

# Usage:
#
# from instana.helpers import eum_snippet
# meta_kvs = { 'userId': user.id }
# eum_snippet(meta=meta_kvs)


def eum_snippet(trace_id=None, eum_api_key=None, meta={}):
"""
Return an EUM snippet for use in views, templates and layouts that reports
client side metrics to Instana that will automagically be linked to the
current trace.

@param trace_id [optional] the trace ID to insert into the EUM string
@param eum_api_key [optional] the EUM API key from your Instana dashboard
@param meta [optional] optional additional KVs you want reported with the
EUM metrics

@return string
"""
try:
eum_file = open(os.path.dirname(__file__) + '/eum.js')
eum_src = Template(eum_file.read())

# Prepare the standard required IDs
ids = {}
ids['meta_kvs'] = ''

current_ctx = internal_tracer.current_context()

if trace_id or current_ctx:
ids['trace_id'] = trace_id or current_ctx.trace_id
else:
# No trace_id passed in and tracer doesn't show an active span so
# return nothing, nada & zip.
return ''

if eum_api_key:
ids['eum_api_key'] = eum_api_key
else:
ids['eum_api_key'] = global_eum_api_key

# Process passed in EUM 'meta' key/values
for key, value in meta.items():
ids['meta_kvs'] += ("'ineum('meta', '%s', '%s');'" % (key, value))

return eum_src.substitute(ids)
except Exception as e:
logger.debug(e)
return ''

def eum_test_snippet(trace_id=None, eum_api_key=None, meta={}):
"""
Return an EUM snippet for use in views, templates and layouts that reports
client side metrics to Instana that will automagically be linked to the
current trace.

@param trace_id [optional] the trace ID to insert into the EUM string
@param eum_api_key [optional] the EUM API key from your Instana dashboard
@param meta [optional] optional additional KVs you want reported with the
EUM metrics

@return string
"""

try:
eum_file = open(os.path.dirname(__file__) + '/eum_test.js')
eum_src = Template(eum_file.read())

# Prepare the standard required IDs
ids = {}
ids['meta_kvs'] = ''

current_ctx = internal_tracer.current_context()

if trace_id or current_ctx:
ids['trace_id'] = trace_id or current_ctx.trace_id
else:
# No trace_id passed in and tracer doesn't show an active span so
# return nothing, nada & zip.
return ''

if eum_api_key:
ids['eum_api_key'] = eum_api_key
else:
ids['eum_api_key'] = global_eum_api_key

# Process passed in EUM 'meta' key/values
for key, value in meta.items():
ids['meta_kvs'] += ("'ineum('meta', '%s', '%s');'" % (key, value))

return eum_src.substitute(ids)
except Exception as e:
logger.debug(e)
return ''
81 changes: 81 additions & 0 deletions tests/test_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from nose.tools import assert_equals
from instana.helpers import eum_snippet, eum_test_snippet

# fake trace_id to test against
trace_id = "aMLx9G2GnnQ6QyMCLJLuCM8nw"
# fake api key to test against
eum_api_key = "FJB66VjwGgGQX6jiCpekoR4vf"

# fake meta key/values
meta1 = "Z7RmMKQAiyCLEAmseNy7e6Vm4"
meta2 = "Dp2bowfm6kJVD9CccmyBt4ePD"
meta3 = "N4poUwbNz98YcvWRAizy2phCo"


def test_vanilla_eum_snippet():
eum_string = eum_snippet(trace_id=trace_id, eum_api_key=eum_api_key)
assert type(eum_string) is str

assert eum_string.find(trace_id) != -1
assert eum_string.find(eum_api_key) != -1

def test_eum_snippet_with_meta():
meta_kvs = {}
meta_kvs['meta1'] = meta1
meta_kvs['meta2'] = meta2
meta_kvs['meta3'] = meta3

eum_string = eum_snippet(trace_id=trace_id, eum_api_key=eum_api_key, meta=meta_kvs)
assert type(eum_string) is str

assert eum_string.find(trace_id) != -1
assert eum_string.find(eum_api_key) != -1
assert eum_string.find(meta1) != -1
assert eum_string.find(meta2) != -1
assert eum_string.find(meta3) != -1

def test_eum_snippet_error():
meta_kvs = {}
meta_kvs['meta1'] = meta1
meta_kvs['meta2'] = meta2
meta_kvs['meta3'] = meta3

# No active span on tracer & no trace_id passed in.
eum_string = eum_snippet(eum_api_key=eum_api_key, meta=meta_kvs)
assert_equals('', eum_string)

def test_vanilla_eum_test_snippet():
eum_string = eum_test_snippet(trace_id=trace_id, eum_api_key=eum_api_key)
assert type(eum_string) is str

assert eum_string.find(trace_id) != -1
assert eum_string.find(eum_api_key) != -1
assert eum_string.find('reportingUrl') != -1
assert eum_string.find('//eum-test-fullstack-0-us-west-2.instana.io') != -1

def test_eum_test_snippet_with_meta():
meta_kvs = {}
meta_kvs['meta1'] = meta1
meta_kvs['meta2'] = meta2
meta_kvs['meta3'] = meta3

eum_string = eum_test_snippet(trace_id=trace_id, eum_api_key=eum_api_key, meta=meta_kvs)
assert type(eum_string) is str
assert eum_string.find('reportingUrl') != -1
assert eum_string.find('//eum-test-fullstack-0-us-west-2.instana.io') != -1

assert eum_string.find(trace_id) != -1
assert eum_string.find(eum_api_key) != -1
assert eum_string.find(meta1) != -1
assert eum_string.find(meta2) != -1
assert eum_string.find(meta3) != -1

def test_eum_test_snippet_error():
meta_kvs = {}
meta_kvs['meta1'] = meta1
meta_kvs['meta2'] = meta2
meta_kvs['meta3'] = meta3

# No active span on tracer & no trace_id passed in.
eum_string = eum_test_snippet(eum_api_key=eum_api_key, meta=meta_kvs)
assert_equals('', eum_string)