Skip to content

Commit

Permalink
feat: memcached instrumentation (open-telemetry#539)
Browse files Browse the repository at this point in the history
  • Loading branch information
rauno56 authored Jun 30, 2021
1 parent a8465a2 commit c1b6eec
Show file tree
Hide file tree
Showing 19 changed files with 1,131 additions and 35 deletions.
39 changes: 23 additions & 16 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,28 @@ jobs:
container:
image: ${{ matrix.container }}
services:
memcached:
image: memcached:1.6.9-alpine
ports:
- 11211:11211
mongo:
image: mongo
ports:
- 27017:27017
mysql:
image: circleci/mysql:5.7
env:
MYSQL_USER: otel
MYSQL_PASSWORD: secret
MYSQL_DATABASE: circle_database
MYSQL_ROOT_PASSWORD: rootpw
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
postgres:
image: circleci/postgres:9.6-alpine
env:
Expand All @@ -39,25 +57,14 @@ jobs:
--health-interval 10s
--health-timeout 5s
--health-retries 5
mysql:
image: circleci/mysql:5.7
env:
MYSQL_USER: otel
MYSQL_PASSWORD: secret
MYSQL_DATABASE: circle_database
MYSQL_ROOT_PASSWORD: rootpw
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
RUN_POSTGRES_TESTS: 1
RUN_MYSQL_TESTS: 1
RUN_MEMCACHED_TESTS: 1
RUN_MONGODB_TESTS: 1
RUN_MYSQL_TESTS: 1
RUN_POSTGRES_TESTS: 1
RUN_REDIS_TESTS: 1
OPENTELEMETRY_MEMCACHED_HOST: memcached
OPENTELEMETRY_MEMCACHED_PORT: 11211
POSTGRES_USER: postgres
POSTGRES_DB: circle_database
POSTGRES_HOST: postgres
Expand Down
18 changes: 18 additions & 0 deletions examples/memcached/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Overview

OpenTelemetry Memcached instrumentation allows user to automatically collect trace data from queries made by the client and export them to the backend of choice. This example does not showcase export functionality, but there are numerous other examples doing that: [`express`](../express), [`router`](../router).

## Running the Example

Created spans are printed out to stdout while running the example.

```sh
npm install # install the dependencies
npm run docker:start # start memcached server
npm run start # run the example
npm run docker:stop # spin down and clean up the docker container
```

## LICENSE

Apache License 2.0
20 changes: 20 additions & 0 deletions examples/memcached/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';

require('./tracer')('example-resource');
const Memcached = require('memcached');
const assert = require('assert');

const KEY = '_KEY_';
const VALUE = `RAND:${Math.random().toFixed(4)}`;
const LT = 10;
const client = new Memcached();

client.set(KEY, VALUE, LT, (err) => {
assert.strictEqual(err, undefined);
client.get(KEY, (err, result) => {
assert.strictEqual(err, undefined);
assert.strictEqual(result, VALUE);
console.log('Sleeping 5 seconds before shutdown to ensure all records are flushed.');
setTimeout(() => { console.log('Completed.'); }, 5000);
});
});
39 changes: 39 additions & 0 deletions examples/memcached/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "memcached-example",
"private": true,
"version": "0.22.0",
"description": "Example of Memcached client with OpenTelemetry",
"main": "index.js",
"scripts": {
"docker:start": "docker run --rm -d --name otel-memcached -p 11211:11211 memcached:1.6.9-alpine",
"docker:stop": "docker rm -f otel-memcached",
"start": "node index.js"
},
"repository": {
"type": "git",
"url": "git+ssh://[email protected]/open-telemetry/opentelemetry-js-contrib.git"
},
"keywords": [
"opentelemetry",
"instrumentation",
"memcached",
"tracing"
],
"engines": {
"node": ">=8.5.0"
},
"author": "OpenTelemetry Authors",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/open-telemetry/opentelemetry-js-contrib/issues"
},
"dependencies": {
"@opentelemetry/api": "^1.0.1",
"@opentelemetry/instrumentation": "^0.22.0",
"@opentelemetry/instrumentation-memcached": "^0.22.0",
"@opentelemetry/node": "^0.22.0",
"@opentelemetry/tracing": "^0.22.0",
"memcached": "^2.2.2"
},
"homepage": "https://github.com/open-telemetry/opentelemetry-js-contrib#readme"
}
37 changes: 37 additions & 0 deletions examples/memcached/tracer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
'use strict';

const opentelemetry = require('@opentelemetry/api');

const { diag, DiagConsoleLogger, DiagLogLevel } = opentelemetry;
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.VERBOSE);

const { registerInstrumentations } = require('@opentelemetry/instrumentation');
const { NodeTracerProvider } = require('@opentelemetry/node');
const { SimpleSpanProcessor, ConsoleSpanExporter } = require('@opentelemetry/tracing');
const { Resource } = require('@opentelemetry/resources');
const { ResourceAttributes } = require('@opentelemetry/semantic-conventions');

const { MemcachedInstrumentation } = require('@opentelemetry/instrumentation-memcached');

module.exports = (serviceName) => {
const provider = new NodeTracerProvider({
resource: new Resource({
[ResourceAttributes.SERVICE_NAME]: serviceName,
}),
});
registerInstrumentations({
tracerProvider: provider,
instrumentations: [
new MemcachedInstrumentation(),
],
});

const exporter = new ConsoleSpanExporter();

provider.addSpanProcessor(new SimpleSpanProcessor(exporter));

// Initialize the OpenTelemetry APIs to use the NodeTracerProvider bindings
provider.register();

return opentelemetry.trace.getTracer('memcached-example');
};
33 changes: 14 additions & 19 deletions packages/opentelemetry-test-utils/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,18 @@ import {
hrTimeToMicroseconds,
} from '@opentelemetry/core';

export function startDocker(db: 'redis' | 'mysql' | 'postgres') {
let dockerRunCmd;
switch (db) {
case 'redis':
dockerRunCmd = `docker run -d -p 63790:6379 --name ot${db} ${db}:alpine`;
break;

case 'mysql':
dockerRunCmd = `docker run --rm -d -e MYSQL_ROOT_PASSWORD=rootpw -e MYSQL_DATABASE=test_db -e MYSQL_USER=otel -e MYSQL_PASSWORD=secret -p 33306:3306 --name ot${db} circleci/${db}:5.7`;
break;

case 'postgres':
dockerRunCmd = `docker run -d -p 54320:5432 -e POSTGRES_PASSWORD=postgres --name ot${db} ${db}:alpine`;
break;
}
const dockerRunCmds = {
redis: 'docker run --rm -d --name otel-redis -p 63790:6379 redis:alpine',
mysql:
'docker run --rm -d --name otel-mysql -p 33306:3306 -e MYSQL_ROOT_PASSWORD=rootpw -e MYSQL_DATABASE=test_db -e MYSQL_USER=otel -e MYSQL_PASSWORD=secret circleci/mysql:5.7',
postgres:
'docker run --rm -d --name otel-postgres -p 54320:5432 -e POSTGRES_PASSWORD=postgres postgres:alpine',
memcached:
'docker run --rm -d --name otel-memcached -p 11211:11211 memcached:1.6.9-alpine',
};

const tasks = [run(dockerRunCmd)];
export function startDocker(db: keyof typeof dockerRunCmds) {
const tasks = [run(dockerRunCmds[db])];

for (let i = 0; i < tasks.length; i++) {
const task = tasks[i];
Expand All @@ -58,9 +53,9 @@ export function startDocker(db: 'redis' | 'mysql' | 'postgres') {
return true;
}

export function cleanUpDocker(db: 'redis' | 'mysql' | 'postgres') {
run(`docker stop ot${db}`);
run(`docker rm ot${db}`);
export function cleanUpDocker(db: keyof typeof dockerRunCmds) {
run(`docker stop otel-${db}`);
run(`docker rm otel-${db}`);
}

function run(cmd: string) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
"env": {
"mocha": true,
"node": true
},
...require('../../../eslint.config.js')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/bin
/coverage
/doc
/test
Loading

0 comments on commit c1b6eec

Please sign in to comment.