Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance Documentation on Instrumentation Outcomes for HTTP Package #5042

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
# OpenTelemetry HTTP and HTTPS Instrumentation for Node.js

[![NPM Published Version][npm-img]][npm-url]
[![Apache License][license-image]][license-image]
[![Apache License][license-image]][license-url]

**Note: This is an experimental package under active development. New releases may include breaking changes.**

This module provides automatic instrumentation for [`http`](https://nodejs.org/api/http.html) and [`https`](https://nodejs.org/api/https.html).

For automatic instrumentation see the
[@opentelemetry/sdk-trace-node](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node) package.
For automatic instrumentation, see the [@opentelemetry/sdk-trace-node](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-sdk-trace-node) package.

## Installation

```bash
npm install --save @opentelemetry/instrumentation-http
```
create2000 marked this conversation as resolved.
Show resolved Hide resolved

## Supported Versions

- Nodejs `>=14`
Expand Down Expand Up @@ -43,7 +41,6 @@ provider.register();
registerInstrumentations({
instrumentations: [new HttpInstrumentation()],
});

```

See [examples/http](https://github.com/open-telemetry/opentelemetry-js/tree/main/examples/http) for a short example.
Expand Down Expand Up @@ -119,9 +116,8 @@ Create HTTP client spans which implement Semantic Convention [Version 1.7.0](htt
When `OTEL_SEMCONV_STABILITY_OPT_IN` is not set or includes `http/dup`, this module implements Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md).

Attributes collected:

| Attribute | Short Description |
| ------------------------------------------- | ------------------------------------------------------------------------------ |
|---------------------------------------------|--------------------------------------------------------------------------------|
| `ip_tcp` | Transport protocol used |
| `ip_udp` | Transport protocol used |
| `http.client_ip` | The IP address of the original client behind all proxies, if known |
Expand All @@ -140,13 +136,11 @@ Attributes collected:
| `http.url` | Full HTTP request URL in the form `scheme://host[:port]/path?query[#fragment]` |
| `http.user_agent` | Value of the HTTP User-Agent header sent by the client |
| `net.host.ip` | Like net.peer.ip but for the host IP. Useful in case of a multi-IP host |
| `net.host.name` | Local hostname or similar |
| `net.host.port` | Like net.peer.port but for the host port |
| `net.peer.ip.` | Remote address of the peer (dotted decimal for IPv4 or RFC5952 for IPv6) |
| `net.peer.name` | Remote hostname or similar |
| `net.peer.port` | Remote port number |
| `net.transport` | Transport protocol used |

| `net.host.name` | Local hostname of the server. |
| `net.peer.ip` | The IP address of the remote client |
| `net.peer.name` | The DNS name or IP address of the remote client |
| `net.peer.port` | The port of the remote peer |

## Useful links

- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"access": "public"
},
"devDependencies": {
"@opentelemetry/api": "1.9.0",
"@opentelemetry/api": "^1.9.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the changes to this file are unintentional.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changes in this file should not be needed for a README.md update.

"@opentelemetry/context-async-hooks": "1.26.0",
"@opentelemetry/sdk-metrics": "1.26.0",
"@opentelemetry/sdk-trace-base": "1.26.0",
Expand All @@ -64,7 +64,7 @@
"lerna": "6.6.2",
"mocha": "10.7.3",
"nock": "13.3.8",
"nyc": "15.1.0",
"nyc": "^15.1.0",
"request": "2.88.2",
"request-promise-native": "1.0.9",
"sinon": "15.1.2",
Expand Down
25 changes: 25 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// index.js
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
const { SimpleSpanProcessor, ConsoleSpanExporter } = require('@opentelemetry/sdk-trace-base');
const MyAxiosInstrumentation = require('./instrumentation-my-axios');

// Initialize the OpenTelemetry tracer
const provider = new NodeTracerProvider();
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
provider.register();

// Initialize your custom instrumentation
const myAxiosInstrumentation = new MyAxiosInstrumentation();
myAxiosInstrumentation.init();

// Example usage of the instrumented axios
const axios = require('my-axios');

axios.request({
method: 'GET',
url: 'https://api.example.com/data',
}).then(response => {
console.log('Response:', response.data);
}).catch(error => {
console.error('Error:', error);
});
54 changes: 54 additions & 0 deletions instrumentation-my-axios/MyAxiosInstrumentation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// MyAxiosInstrumentation.js
const { InstrumentationBase } = require('@opentelemetry/instrumentation');
const tracer = require('./tracer'); // Import the tracer configuration

// Define the custom instrumentation class
class MyAxiosInstrumentation extends InstrumentationBase {
constructor() {
super('my-axios-instrumentation', '1.0.0'); // Ensure the instrumentation name is consistent
}

// Initialize the instrumentation by wrapping Axios methods
init() {
const axios = require('axios');
const methodsToInstrument = ['get', 'post', 'put', 'delete', 'patch'];

methodsToInstrument.forEach((method) => {
const originalMethod = axios[method];

// Wrap each Axios method to start and end spans
axios[method] = async (...args) => {
const span = this.startSpan(method, args);

try {
// Call the original Axios method
const response = await originalMethod.apply(axios, args);
span.setStatus({ code: 200 }); // Mark as success
return response;
} catch (error) {
// Set span status based on error response
span.setStatus({ code: error.response ? error.response.status : 500 });
throw error;
} finally {
span.end(); // End the span
console.log(`Span for ${method.toUpperCase()} request completed.`);
}
};
});
}

// Method to start a new span for a specific Axios method and URL
startSpan(method, args) {
const span = tracer.startSpan(`http.${method}`, {
attributes: {
'http.method': method,
'http.url': args[0],
},
});
console.log(`Span started for ${method.toUpperCase()} request to ${args[0]}`);
return span;
}
}

// Export the instrumentation class
module.exports = MyAxiosInstrumentation;
25 changes: 25 additions & 0 deletions instrumentation-my-axios/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// index.js
const MyAxiosInstrumentation = require('./MyAxiosInstrumentation'); // Import your instrumentation class

// Initialize the instrumentation
const myAxiosInstrumentation = new MyAxiosInstrumentation();
myAxiosInstrumentation.init();

const axios = require('axios'); // Ensure axios is imported

async function makeRequests() {
try {
// Example GET request
const getResponse = await axios.get('http://httpbin.org/get'); // Replace with a valid URL
console.log('GET response:', getResponse.data);

// Example POST request
const postResponse = await axios.post('http://httpbin.org/post', { key: 'value' }); // Replace with a valid URL and data
console.log('POST response:', postResponse.data);
} catch (error) {
console.error('Error during HTTP request:', error);
}
}

// Call the function to make requests
makeRequests();
Loading