Skip to content

Commit 40161be

Browse files
author
Israel Blancas
authored
Merge branch 'main' into 3370
2 parents c5fdee5 + ad83cb9 commit 40161be

16 files changed

+491
-54
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: enhancement
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
5+
component: auto-instrumentation
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: add config for installing musl based auto-instrumentation for Python
9+
10+
# One or more tracking issues related to the change
11+
issues: [2264]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext:

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,12 @@ instrumentation.opentelemetry.io/inject-nodejs: "true"
292292
```
293293

294294
Python:
295+
Python auto-instrumentation also honors an annotation that will permit it to run it on images with a different C library than glibc.
295296

296297
```bash
297298
instrumentation.opentelemetry.io/inject-python: "true"
299+
instrumentation.opentelemetry.io/otel-python-platform: "glibc" # for Linux glibc based images, this is the default value and can be omitted
300+
instrumentation.opentelemetry.io/otel-python-platform: "musl" # for Linux musl based images
298301
```
299302

300303
.NET:

cmd/otel-allocator/server/bench_test.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ func BenchmarkTargetItemsJSONHandler(b *testing.B) {
198198
},
199199
}
200200
for _, tc := range tests {
201-
data := makeNTargetItems(*random, tc.numTargets, tc.numLabels)
201+
data := makeNTargetJSON(*random, tc.numTargets, tc.numLabels)
202202
b.Run(fmt.Sprintf("%d_targets_%d_labels", tc.numTargets, tc.numLabels), func(b *testing.B) {
203203
b.ReportAllocs()
204204
for i := 0; i < b.N; i++ {
@@ -242,7 +242,7 @@ func makeNCollectorJSON(random rand.Rand, numCollectors, numItems int) map[strin
242242
for i := 0; i < numCollectors; i++ {
243243
items[randSeq(random, 20)] = collectorJSON{
244244
Link: randSeq(random, 120),
245-
Jobs: makeNTargetItems(random, numItems, 50),
245+
Jobs: makeNTargetJSON(random, numItems, 50),
246246
}
247247
}
248248
return items
@@ -261,6 +261,15 @@ func makeNTargetItems(random rand.Rand, numItems, numLabels int) []*target.Item
261261
return items
262262
}
263263

264+
func makeNTargetJSON(random rand.Rand, numItems, numLabels int) []*targetJSON {
265+
items := makeNTargetItems(random, numItems, numLabels)
266+
targets := make([]*targetJSON, numItems)
267+
for i := 0; i < numItems; i++ {
268+
targets[i] = targetJsonFromTargetItem(items[i])
269+
}
270+
return targets
271+
}
272+
264273
func makeNNewLabels(random rand.Rand, n int) model.LabelSet {
265274
labels := make(map[model.LabelName]model.LabelValue, n)
266275
for i := 0; i < n; i++ {

cmd/otel-allocator/server/server.go

+40-10
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"github.com/prometheus/client_golang/prometheus/promauto"
3535
"github.com/prometheus/client_golang/prometheus/promhttp"
3636
promcommconfig "github.com/prometheus/common/config"
37+
"github.com/prometheus/common/model"
3738
promconfig "github.com/prometheus/prometheus/config"
3839
"gopkg.in/yaml.v2"
3940

@@ -57,8 +58,17 @@ var (
5758
)
5859

5960
type collectorJSON struct {
60-
Link string `json:"_link"`
61-
Jobs []*target.Item `json:"targets"`
61+
Link string `json:"_link"`
62+
Jobs []*targetJSON `json:"targets"`
63+
}
64+
65+
type linkJSON struct {
66+
Link string `json:"_link"`
67+
}
68+
69+
type targetJSON struct {
70+
TargetURL []string `json:"targets"`
71+
Labels model.LabelSet `json:"labels"`
6272
}
6373

6474
type Server struct {
@@ -263,9 +273,9 @@ func (s *Server) ReadinessProbeHandler(c *gin.Context) {
263273
}
264274

265275
func (s *Server) JobHandler(c *gin.Context) {
266-
displayData := make(map[string]target.LinkJSON)
276+
displayData := make(map[string]linkJSON)
267277
for _, v := range s.allocator.TargetItems() {
268-
displayData[v.JobName] = target.LinkJSON{Link: v.Link.Link}
278+
displayData[v.JobName] = linkJSON{Link: fmt.Sprintf("/jobs/%s/targets", url.QueryEscape(v.JobName))}
269279
}
270280
s.jsonHandler(c.Writer, displayData)
271281
}
@@ -294,16 +304,16 @@ func (s *Server) TargetsHandler(c *gin.Context) {
294304
if len(q) == 0 {
295305
displayData := GetAllTargetsByJob(s.allocator, jobId)
296306
s.jsonHandler(c.Writer, displayData)
297-
298307
} else {
299-
tgs := s.allocator.GetTargetsForCollectorAndJob(q[0], jobId)
308+
targets := GetAllTargetsByCollectorAndJob(s.allocator, q[0], jobId)
300309
// Displays empty list if nothing matches
301-
if len(tgs) == 0 {
310+
if len(targets) == 0 {
302311
s.jsonHandler(c.Writer, []interface{}{})
303312
return
304313
}
305-
s.jsonHandler(c.Writer, tgs)
314+
s.jsonHandler(c.Writer, targets)
306315
}
316+
307317
}
308318

309319
func (s *Server) errorHandler(w http.ResponseWriter, err error) {
@@ -323,12 +333,25 @@ func (s *Server) jsonHandler(w http.ResponseWriter, data interface{}) {
323333
func GetAllTargetsByJob(allocator allocation.Allocator, job string) map[string]collectorJSON {
324334
displayData := make(map[string]collectorJSON)
325335
for _, col := range allocator.Collectors() {
326-
items := allocator.GetTargetsForCollectorAndJob(col.Name, job)
327-
displayData[col.Name] = collectorJSON{Link: fmt.Sprintf("/jobs/%s/targets?collector_id=%s", url.QueryEscape(job), col.Name), Jobs: items}
336+
targets := GetAllTargetsByCollectorAndJob(allocator, col.Name, job)
337+
displayData[col.Name] = collectorJSON{
338+
Link: fmt.Sprintf("/jobs/%s/targets?collector_id=%s", url.QueryEscape(job), col.Name),
339+
Jobs: targets,
340+
}
328341
}
329342
return displayData
330343
}
331344

345+
// GetAllTargetsByCollector returns all the targets for a given collector and job.
346+
func GetAllTargetsByCollectorAndJob(allocator allocation.Allocator, collectorName string, jobName string) []*targetJSON {
347+
items := allocator.GetTargetsForCollectorAndJob(collectorName, jobName)
348+
targets := make([]*targetJSON, len(items))
349+
for i, item := range items {
350+
targets[i] = targetJsonFromTargetItem(item)
351+
}
352+
return targets
353+
}
354+
332355
// registerPprof registers the pprof handlers and either serves the requested
333356
// specific profile or falls back to index handler.
334357
func registerPprof(g *gin.RouterGroup) {
@@ -348,3 +371,10 @@ func registerPprof(g *gin.RouterGroup) {
348371
}
349372
})
350373
}
374+
375+
func targetJsonFromTargetItem(item *target.Item) *targetJSON {
376+
return &targetJSON{
377+
TargetURL: item.TargetURL,
378+
Labels: item.Labels,
379+
}
380+
}

cmd/otel-allocator/server/server_test.go

+14-14
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func TestServer_TargetsHandler(t *testing.T) {
7474
allocator allocation.Allocator
7575
}
7676
type want struct {
77-
items []*target.Item
77+
items []*targetJSON
7878
errString string
7979
}
8080
tests := []struct {
@@ -91,7 +91,7 @@ func TestServer_TargetsHandler(t *testing.T) {
9191
allocator: leastWeighted,
9292
},
9393
want: want{
94-
items: []*target.Item{},
94+
items: []*targetJSON{},
9595
},
9696
},
9797
{
@@ -105,7 +105,7 @@ func TestServer_TargetsHandler(t *testing.T) {
105105
allocator: leastWeighted,
106106
},
107107
want: want{
108-
items: []*target.Item{
108+
items: []*targetJSON{
109109
{
110110
TargetURL: []string{"test-url"},
111111
Labels: map[model.LabelName]model.LabelValue{
@@ -127,7 +127,7 @@ func TestServer_TargetsHandler(t *testing.T) {
127127
allocator: leastWeighted,
128128
},
129129
want: want{
130-
items: []*target.Item{
130+
items: []*targetJSON{
131131
{
132132
TargetURL: []string{"test-url"},
133133
Labels: map[model.LabelName]model.LabelValue{
@@ -149,7 +149,7 @@ func TestServer_TargetsHandler(t *testing.T) {
149149
allocator: leastWeighted,
150150
},
151151
want: want{
152-
items: []*target.Item{
152+
items: []*targetJSON{
153153
{
154154
TargetURL: []string{"test-url"},
155155
Labels: map[model.LabelName]model.LabelValue{
@@ -186,7 +186,7 @@ func TestServer_TargetsHandler(t *testing.T) {
186186
assert.EqualError(t, err, tt.want.errString)
187187
return
188188
}
189-
var itemResponse []*target.Item
189+
var itemResponse []*targetJSON
190190
err = json.Unmarshal(bodyBytes, &itemResponse)
191191
assert.NoError(t, err)
192192
assert.ElementsMatch(t, tt.want.items, itemResponse)
@@ -555,27 +555,27 @@ func TestServer_JobHandler(t *testing.T) {
555555
description string
556556
targetItems map[string]*target.Item
557557
expectedCode int
558-
expectedJobs map[string]target.LinkJSON
558+
expectedJobs map[string]linkJSON
559559
}{
560560
{
561561
description: "nil jobs",
562562
targetItems: nil,
563563
expectedCode: http.StatusOK,
564-
expectedJobs: make(map[string]target.LinkJSON),
564+
expectedJobs: make(map[string]linkJSON),
565565
},
566566
{
567567
description: "empty jobs",
568568
targetItems: map[string]*target.Item{},
569569
expectedCode: http.StatusOK,
570-
expectedJobs: make(map[string]target.LinkJSON),
570+
expectedJobs: make(map[string]linkJSON),
571571
},
572572
{
573573
description: "one job",
574574
targetItems: map[string]*target.Item{
575575
"targetitem": target.NewItem("job1", "", model.LabelSet{}, ""),
576576
},
577577
expectedCode: http.StatusOK,
578-
expectedJobs: map[string]target.LinkJSON{
578+
expectedJobs: map[string]linkJSON{
579579
"job1": newLink("job1"),
580580
},
581581
},
@@ -588,7 +588,7 @@ func TestServer_JobHandler(t *testing.T) {
588588
"d": target.NewItem("job3", "", model.LabelSet{}, ""),
589589
"e": target.NewItem("job3", "", model.LabelSet{}, "")},
590590
expectedCode: http.StatusOK,
591-
expectedJobs: map[string]target.LinkJSON{
591+
expectedJobs: map[string]linkJSON{
592592
"job1": newLink("job1"),
593593
"job2": newLink("job2"),
594594
"job3": newLink("job3"),
@@ -609,7 +609,7 @@ func TestServer_JobHandler(t *testing.T) {
609609
assert.Equal(t, tc.expectedCode, result.StatusCode)
610610
bodyBytes, err := io.ReadAll(result.Body)
611611
require.NoError(t, err)
612-
jobs := map[string]target.LinkJSON{}
612+
jobs := map[string]linkJSON{}
613613
err = json.Unmarshal(bodyBytes, &jobs)
614614
require.NoError(t, err)
615615
assert.Equal(t, tc.expectedJobs, jobs)
@@ -737,6 +737,6 @@ func TestServer_ScrapeConfigRespose(t *testing.T) {
737737
}
738738
}
739739

740-
func newLink(jobName string) target.LinkJSON {
741-
return target.LinkJSON{Link: fmt.Sprintf("/jobs/%s/targets", url.QueryEscape(jobName))}
740+
func newLink(jobName string) linkJSON {
741+
return linkJSON{Link: fmt.Sprintf("/jobs/%s/targets", url.QueryEscape(jobName))}
742742
}

cmd/otel-allocator/target/target.go

+4-14
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
package target
1616

1717
import (
18-
"fmt"
19-
"net/url"
20-
2118
"github.com/prometheus/common/model"
2219
)
2320

@@ -34,17 +31,11 @@ var (
3431
endpointSliceTargetNameLabel model.LabelName = "__meta_kubernetes_endpointslice_address_target_name"
3532
)
3633

37-
// LinkJSON This package contains common structs and methods that relate to scrape targets.
38-
type LinkJSON struct {
39-
Link string `json:"_link"`
40-
}
41-
4234
type Item struct {
43-
JobName string `json:"-"`
44-
Link LinkJSON `json:"-"`
45-
TargetURL []string `json:"targets"`
46-
Labels model.LabelSet `json:"labels"`
47-
CollectorName string `json:"-"`
35+
JobName string
36+
TargetURL []string
37+
Labels model.LabelSet
38+
CollectorName string
4839
hash string
4940
}
5041

@@ -73,7 +64,6 @@ func (t *Item) GetNodeName() string {
7364
func NewItem(jobName string, targetURL string, label model.LabelSet, collectorName string) *Item {
7465
return &Item{
7566
JobName: jobName,
76-
Link: LinkJSON{Link: fmt.Sprintf("/jobs/%s/targets", url.QueryEscape(jobName))},
7767
hash: jobName + targetURL + label.Fingerprint().String(),
7868
TargetURL: []string{targetURL},
7969
Labels: label,

pkg/instrumentation/annotation.go

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const (
3030
annotationInjectNodeJSContainersName = "instrumentation.opentelemetry.io/nodejs-container-names"
3131
annotationInjectPython = "instrumentation.opentelemetry.io/inject-python"
3232
annotationInjectPythonContainersName = "instrumentation.opentelemetry.io/python-container-names"
33+
annotationPythonPlatform = "instrumentation.opentelemetry.io/otel-python-platform"
3334
annotationInjectDotNet = "instrumentation.opentelemetry.io/inject-dotnet"
3435
annotationDotNetRuntime = "instrumentation.opentelemetry.io/otel-dotnet-auto-runtime"
3536
annotationInjectDotnetContainersName = "instrumentation.opentelemetry.io/dotnet-container-names"

pkg/instrumentation/podmutator.go

+1
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ func (pm *instPodMutator) Mutate(ctx context.Context, ns corev1.Namespace, pod c
321321
}
322322
if pm.config.EnablePythonAutoInstrumentation() || inst == nil {
323323
insts.Python.Instrumentation = inst
324+
insts.Python.AdditionalAnnotations = map[string]string{annotationPythonPlatform: annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationPythonPlatform)}
324325
} else {
325326
logger.Error(nil, "support for Python auto instrumentation is not enabled")
326327
pm.Recorder.Event(pod.DeepCopy(), "Warning", "InstrumentationRequestRejected", "support for Python auto instrumentation is not enabled")

pkg/instrumentation/python.go

+26-12
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,23 @@ import (
2323
)
2424

2525
const (
26-
envPythonPath = "PYTHONPATH"
27-
envOtelTracesExporter = "OTEL_TRACES_EXPORTER"
28-
envOtelMetricsExporter = "OTEL_METRICS_EXPORTER"
29-
envOtelLogsExporter = "OTEL_LOGS_EXPORTER"
30-
envOtelExporterOTLPProtocol = "OTEL_EXPORTER_OTLP_PROTOCOL"
31-
pythonPathPrefix = "/otel-auto-instrumentation-python/opentelemetry/instrumentation/auto_instrumentation"
32-
pythonPathSuffix = "/otel-auto-instrumentation-python"
33-
pythonInstrMountPath = "/otel-auto-instrumentation-python"
34-
pythonVolumeName = volumeName + "-python"
35-
pythonInitContainerName = initContainerName + "-python"
26+
envPythonPath = "PYTHONPATH"
27+
envOtelTracesExporter = "OTEL_TRACES_EXPORTER"
28+
envOtelMetricsExporter = "OTEL_METRICS_EXPORTER"
29+
envOtelLogsExporter = "OTEL_LOGS_EXPORTER"
30+
envOtelExporterOTLPProtocol = "OTEL_EXPORTER_OTLP_PROTOCOL"
31+
glibcLinuxAutoInstrumentationSrc = "/autoinstrumentation/."
32+
muslLinuxAutoInstrumentationSrc = "/autoinstrumentation-musl/."
33+
pythonPathPrefix = "/otel-auto-instrumentation-python/opentelemetry/instrumentation/auto_instrumentation"
34+
pythonPathSuffix = "/otel-auto-instrumentation-python"
35+
pythonInstrMountPath = "/otel-auto-instrumentation-python"
36+
pythonVolumeName = volumeName + "-python"
37+
pythonInitContainerName = initContainerName + "-python"
38+
glibcLinux = "glibc"
39+
muslLinux = "musl"
3640
)
3741

38-
func injectPythonSDK(pythonSpec v1alpha1.Python, pod corev1.Pod, index int) (corev1.Pod, error) {
42+
func injectPythonSDK(pythonSpec v1alpha1.Python, pod corev1.Pod, index int, platform string) (corev1.Pod, error) {
3943
volume := instrVolume(pythonSpec.VolumeClaimTemplate, pythonVolumeName, pythonSpec.VolumeSizeLimit)
4044

4145
// caller checks if there is at least one container.
@@ -46,6 +50,16 @@ func injectPythonSDK(pythonSpec v1alpha1.Python, pod corev1.Pod, index int) (cor
4650
return pod, err
4751
}
4852

53+
autoInstrumentationSrc := ""
54+
switch platform {
55+
case "", glibcLinux:
56+
autoInstrumentationSrc = glibcLinuxAutoInstrumentationSrc
57+
case muslLinux:
58+
autoInstrumentationSrc = muslLinuxAutoInstrumentationSrc
59+
default:
60+
return pod, fmt.Errorf("provided instrumentation.opentelemetry.io/otel-python-platform annotation value '%s' is not supported", platform)
61+
}
62+
4963
// inject Python instrumentation spec env vars.
5064
for _, env := range pythonSpec.Env {
5165
idx := getIndexOfEnv(container.Env, env.Name)
@@ -111,7 +125,7 @@ func injectPythonSDK(pythonSpec v1alpha1.Python, pod corev1.Pod, index int) (cor
111125
pod.Spec.InitContainers = append(pod.Spec.InitContainers, corev1.Container{
112126
Name: pythonInitContainerName,
113127
Image: pythonSpec.Image,
114-
Command: []string{"cp", "-r", "/autoinstrumentation/.", pythonInstrMountPath},
128+
Command: []string{"cp", "-r", autoInstrumentationSrc, pythonInstrMountPath},
115129
Resources: pythonSpec.Resources,
116130
VolumeMounts: []corev1.VolumeMount{{
117131
Name: volume.Name,

0 commit comments

Comments
 (0)