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

feat: container ID detector for cgroup v2 #1181

Merged
merged 26 commits into from
Oct 1, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ad89334
added another block to test for v2
abhee11 Sep 4, 2022
37d45cb
feat: changing export name to reflect generic docker
abhee11 Sep 4, 2022
d933955
feat: adding geenric naming and logic changes to support cgroup v2
abhee11 Sep 15, 2022
4ad530d
test: test file renamed
abhee11 Sep 15, 2022
1ebd445
feat: adding hostname check
abhee11 Sep 16, 2022
5cd6324
feat: adding hostname check- refactor
abhee11 Sep 16, 2022
132e06d
feat: fixed a test and fixed lint
abhee11 Sep 19, 2022
0a61ba2
feat: added another condition to check for length
abhee11 Sep 19, 2022
9ad9f52
test: added two more tests
abhee11 Sep 19, 2022
ffcebb8
Merge pull request #1 from abhee11/docker-v2-detector
abhee11 Sep 19, 2022
432759b
Merge branch 'open-telemetry:main' into main
abhee11 Sep 19, 2022
5e626e9
feat: renamed docker to container and addressed pr comments
abhee11 Sep 20, 2022
5406466
feat: renamed docker to container and addressed pr comments- 2
abhee11 Sep 20, 2022
2c775d0
feat: renamed docker to container and addressed pr comments-3
abhee11 Sep 20, 2022
541b84a
Merge branch 'main' into main
abhee11 Sep 20, 2022
7813abe
feat: addressed pr comments-2
abhee11 Sep 22, 2022
74c362f
Merge branch 'main' of https://github.com/abhee11/opentelemetry-js-co…
abhee11 Sep 22, 2022
c3e2359
Merge branch 'main' into main
abhee11 Sep 22, 2022
3e3a20b
feat: modified tests to take in multiple lines input
abhee11 Sep 30, 2022
6740303
Merge branch 'main' of https://github.com/abhee11/opentelemetry-js-co…
abhee11 Sep 30, 2022
fc0f31c
feat: merge resolution for manifest
abhee11 Sep 30, 2022
e4ca980
Merge branch 'main' into main
abhee11 Sep 30, 2022
9ed5aa5
feat: fixing release please manifest
abhee11 Sep 30, 2022
5dee09c
feat: merge resolution for manifest
abhee11 Sep 30, 2022
a72a56f
feat: changing please-config to rename docker to container
abhee11 Sep 30, 2022
2c4d709
feat: replaced >= check to == check
abhee11 Sep 30, 2022
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
Expand Up @@ -25,10 +25,12 @@ import * as fs from 'fs';
import * as util from 'util';
import { diag } from '@opentelemetry/api';

export class DockerCGroupV1Detector implements Detector {
export class DockerDetector implements Detector {
readonly CONTAINER_ID_LENGTH = 64;
readonly DEFAULT_CGROUP_PATH = '/proc/self/cgroup';
blumamir marked this conversation as resolved.
Show resolved Hide resolved
readonly DEFAULT_CGROUP_V2_PATH = '/proc/self/mountinfo';
readonly UTF8_UNICODE = 'utf8';
readonly HOSTNAME = 'hostname';

private static readFileAsync = util.promisify(fs.readFile);

Expand All @@ -42,7 +44,7 @@ export class DockerCGroupV1Detector implements Detector {
});
} catch (e) {
diag.info(
'Docker CGROUP V1 Detector did not identify running inside a supported docker container, no docker attributes will be added to resource: ',
'Docker Detector did not identify running inside a supported docker container, no docker attributes will be added to resource: ',
e
);
return Resource.empty();
Expand All @@ -51,21 +53,39 @@ export class DockerCGroupV1Detector implements Detector {

private async _getContainerId(): Promise<string | undefined> {
try {
const rawData = await DockerCGroupV1Detector.readFileAsync(
let rawData = await DockerDetector.readFileAsync(
this.DEFAULT_CGROUP_PATH,
this.UTF8_UNICODE
);
const splitData = rawData.trim().split('\n');
let splitData = rawData.trim().split('\n');
for (const str of splitData) {
if (str.length >= this.CONTAINER_ID_LENGTH) {
return str.substring(str.length - this.CONTAINER_ID_LENGTH);
}
}

// If this code is reached - we then check for the V2_PATH
rawData = await DockerDetector.readFileAsync(
blumamir marked this conversation as resolved.
Show resolved Hide resolved
this.DEFAULT_CGROUP_V2_PATH,
this.UTF8_UNICODE
);

splitData = rawData.trim().split('\n');
for (let str of splitData) {
if (str.includes(this.HOSTNAME)) {
blumamir marked this conversation as resolved.
Show resolved Hide resolved
str = str
blumamir marked this conversation as resolved.
Show resolved Hide resolved
.split('/')
.filter(s => s.length >= this.CONTAINER_ID_LENGTH)[0];
blumamir marked this conversation as resolved.
Show resolved Hide resolved
if (str.length >= this.CONTAINER_ID_LENGTH) {
return str.substring(str.length - this.CONTAINER_ID_LENGTH);
}
}
}
} catch (e) {
blumamir marked this conversation as resolved.
Show resolved Hide resolved
if (e instanceof Error) {
const errorMessage = e.message;
diag.info(
'Docker CGROUP V1 Detector failed to read the Container ID: ',
'Docker Detector failed to read the Container ID: ',
errorMessage
);
}
Expand All @@ -74,4 +94,4 @@ export class DockerCGroupV1Detector implements Detector {
}
}

export const dockerCGroupV1Detector = new DockerCGroupV1Detector();
export const dockerDetector = new DockerDetector();
blumamir marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './DockerCGroupV1Detector';
export * from './DockerDetector';
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,23 @@
import * as sinon from 'sinon';
import * as assert from 'assert';
import { Resource } from '@opentelemetry/resources';
import { dockerCGroupV1Detector } from '../src';
import { dockerDetector } from '../src';
import {
assertContainerResource,
assertEmptyResource,
} from '@opentelemetry/contrib-test-utils';

import { DockerCGroupV1Detector } from '../src';
import { DockerDetector } from '../src';

describe('dockerCGroupV1Detector', () => {
let readStub;
const correctCgroupData =
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm';
const correctCgroupV2Data =
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm/hostname';

const wrongCgroupV2Data =
'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm/host';

afterEach(() => {
sinon.restore();
Expand All @@ -37,21 +42,21 @@ describe('dockerCGroupV1Detector', () => {
describe('Supported docker - Container ID ', () => {
it('should return a resource attributes without container id - docker cgroup v1 detector', async () => {
readStub = sinon
.stub(DockerCGroupV1Detector, 'readFileAsync' as any)
.stub(DockerDetector, 'readFileAsync' as any)
.resolves(undefined);

const resource: Resource = await dockerCGroupV1Detector.detect();
const resource: Resource = await dockerDetector.detect();

assert.deepStrictEqual(resource.attributes, {});
assert.ok(resource);
});

it('should return a resource with container ID with a valid container ID present', async () => {
readStub = sinon
.stub(DockerCGroupV1Detector, 'readFileAsync' as any)
.stub(DockerDetector, 'readFileAsync' as any)
.resolves(correctCgroupData);

const resource: Resource = await dockerCGroupV1Detector.detect();
const resource: Resource = await dockerDetector.detect();

sinon.assert.calledOnce(readStub);

Expand All @@ -61,15 +66,42 @@ describe('dockerCGroupV1Detector', () => {
});
});

it('should return a resource with container ID with a valid container ID present for v2', async () => {
readStub = sinon.stub(DockerDetector, 'readFileAsync' as any);

readStub.onFirstCall().resolves('');
readStub.onSecondCall().resolves(correctCgroupV2Data);

const resource: Resource = await dockerDetector.detect();
sinon.assert.calledTwice(readStub);

assert.ok(resource);
assertContainerResource(resource, {
id: 'bcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm',
});
});

it('should return a empty resource with failed hostname check for v2', async () => {
readStub = sinon.stub(DockerDetector, 'readFileAsync' as any);

readStub.onFirstCall().resolves('');
readStub.onSecondCall().resolves(wrongCgroupV2Data);

const resource: Resource = await dockerDetector.detect();
sinon.assert.calledTwice(readStub);

assert.ok(resource);
});

it('should return a resource without attribute container.id when cgroup file does not contain valid Container ID', async () => {
readStub = sinon
.stub(DockerCGroupV1Detector, 'readFileAsync' as any)
.stub(DockerDetector, 'readFileAsync' as any)
.resolves('');

const resource: Resource = await dockerCGroupV1Detector.detect();
const resource: Resource = await dockerDetector.detect();
assert.deepStrictEqual(resource.attributes, {});

sinon.assert.calledOnce(readStub);
sinon.assert.calledTwice(readStub);
assert.ok(resource);
});

Expand All @@ -79,11 +111,27 @@ describe('dockerCGroupV1Detector', () => {
};

readStub = sinon
.stub(DockerCGroupV1Detector, 'readFileAsync' as any)
.stub(DockerDetector, 'readFileAsync' as any)
.rejects(errorMsg.fileNotFoundError);

const resource: Resource = await dockerCGroupV1Detector.detect();
const resource: Resource = await dockerDetector.detect();

sinon.assert.calledOnce(readStub);
assertEmptyResource(resource);
});

//cgroup v2 and containerd test

it('should return an empty resource when containerId is not valid', async () => {
const errorMsg = {
fileNotFoundError: new Error('cannot find file in path'),
};

readStub = sinon
.stub(DockerDetector, 'readFileAsync' as any)
.rejects(errorMsg.fileNotFoundError);

const resource: Resource = await dockerDetector.detect();
sinon.assert.calledOnce(readStub);
assertEmptyResource(resource);
});
Expand Down