Skip to content

Commit

Permalink
Compute apmStats in the server. (#21067)
Browse files Browse the repository at this point in the history
- Handle communicating with the trace-agent in the status package
- Update the GUI to rende the apmStats using the informatoin from the server rather than using AJAX
  • Loading branch information
GustavoCaso authored Nov 29, 2023
1 parent 3f5d700 commit d13e6ec
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 114 deletions.
52 changes: 0 additions & 52 deletions cmd/agent/gui/views/private/js/apm.js

This file was deleted.

1 change: 0 additions & 1 deletion cmd/agent/gui/views/private/js/ejs.min.js

This file was deleted.

24 changes: 1 addition & 23 deletions cmd/agent/gui/views/private/js/javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ function checkStatus() {
if (checkStatus.uptime > last_ts) {
$("#restart_status").hide()
}
checkStatus.uptime = last_ts
checkStatus.uptime = last_ts
},function() {
$("#agent_status").html("Not connected<br> to Agent");
$("#agent_status").css({
Expand Down Expand Up @@ -153,28 +153,6 @@ function loadStatus(page) {
sendMessage("agent/status/" + page, "", "post",
function(data, status, xhr){
$("#" + page + "_status").html(DOMPurify.sanitize(data));

// Get the trace-agent status
sendMessage("agent/getConfig/apm_config.receiver_port", "", "GET",
function(data, status, xhr) {
var apmPort = data["apm_config.debug.port"];
if (apmPort == null) {
apmPort = "5012";
}
var url = "http://127.0.0.1:"+apmPort+"/debug/vars"
$.ajax({
url: url,
type: "GET",
success: function(data) {
$("#apmStats > .stat_data").html(ejs.render(apmTemplate, data));
},
error: function() {
$("#apmStats > .stat_data").text("Status: Not running or not on localhost.");
}
})
}, function() {
$("#apmStats > .stat_data").html("Could not obtain trace-agent port from API.");
})
},function(){
$("#" + page + "_status").html("<span class='center'>An error occurred.</span>");
});
Expand Down
59 changes: 56 additions & 3 deletions cmd/agent/gui/views/templates/generalStatus.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -478,9 +478,61 @@
</span>
</div>

<div class="stat" id="apmStats">
<div class="stat">
<span class="stat_title">APM</span>
<span class="stat_data">Loading...</span>
<span class="stat_data">
{{- with .apmStats -}}
{{- if .error }}
Not running or unreachable on localhost:{{.port}}<br>
Error: {{.error}}<br>
{{- else}}
Status: Running<br>
Pid: {{.pid}}<br>
Uptime: {{.uptime}} seconds<br>
Mem alloc: {{humanize .memstats.Alloc}} bytes<br>
Hostname: {{.config.Hostname}}<br>
Receiver: {{.config.ReceiverHost}}:{{.config.ReceiverPort}}<br>
Endpoints:
<span class="stat_subdata">
{{- range $i, $e := .config.Endpoints}}
{{ $e.Host }}<br />
{{- end }}
</span>
<span class="stat_subtitle">Receiver (previous minute)</span>
<span class="stat_subdata">
{{- if eq (len .receiver) 0}}
No traces received in the previous minute.<br>
{{ else }}
{{ range $i, $ts := .receiver }}
From {{if $ts.Lang}}{{ $ts.Lang }} {{ $ts.LangVersion }} ({{ $ts.Interpreter }}), client {{ $ts.TracerVersion }}{{else}}unknown clients{{end}}
<span class="stat_subdata">
Traces received: {{ $ts.TracesReceived }} ({{ humanize $ts.TracesBytes }} bytes)<br>
Spans received: {{ $ts.SpansReceived }}
{{ with $ts.WarnString }}
<br>WARNING: {{ . }}</br>
{{ end }}
</span>
{{ end }}
{{ end }}

{{range $key, $value := .ratebyservice_filtered -}}
{{- if eq $key "service:,env:" -}}
Default priority sampling rate: {{percent $value}}%
{{- else}}
Priority sampling rate for '{{ $key }}': {{percent $value}}%
{{- end}}
{{- end }}
</span>
<span class="stat_subtitle">Writer (previous minute)</span>
<span class="stat_subdata">
Traces: {{.trace_writer.Payloads}} payloads, {{.trace_writer.Traces}} traces, {{.trace_writer.Events}} events, {{humanize .trace_writer.Bytes}} bytes<br>
{{- if gt .trace_writer.Errors 0.0}}WARNING: Traces API errors (1 min): {{.trace_writer.Errors}}{{end}}
Stats: {{.stats_writer.Payloads}} payloads, {{.stats_writer.StatsBuckets}} stats buckets, {{humanize .stats_writer.Bytes}} bytes<br>
{{- if gt .stats_writer.Errors 0.0}}WARNING: Stats API errors (1 min): {{.stats_writer.Errors}}{{end}}
</span>
{{- end }}
{{ end }}
</span>
</div>

<div class="stat">
Expand Down Expand Up @@ -532,7 +584,8 @@
{{- end }}
{{ end }}
</span>
</div>
</div>



<div class="stat">
Expand Down
1 change: 0 additions & 1 deletion cmd/agent/gui/views/templates/index.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
<link rel="stylesheet" href="view/css/stylesheet.css">
<script src="view/js/polyfills.js"> </script>
<script src="view/js/jquery-3.5.1.min.js"> </script>
<script src="view/js/ejs.min.js"> </script>
<script src="view/js/apm.js"> </script>
<script src="view/js/codemirror.js"> </script>
<script src="view/js/yaml.js"> </script>
Expand Down
34 changes: 0 additions & 34 deletions cmd/agent/subcommands/status/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ import (
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
"os"
"time"

"go.uber.org/fx"

Expand Down Expand Up @@ -162,14 +160,6 @@ func requestStatus(config config.Component, cliParams *cliParams) error {
if err != nil {
return err
}
// attach trace-agent status, if obtainable
temp := make(map[string]interface{})
if err := json.Unmarshal(r, &temp); err == nil {
temp["apmStats"] = getAPMStatus(config)
if newr, err := json.Marshal(temp); err == nil {
r = newr
}
}

// The rendering is done in the client so that the agent has less work to do
if cliParams.prettyPrintJSON {
Expand All @@ -195,30 +185,6 @@ func requestStatus(config config.Component, cliParams *cliParams) error {
return nil
}

// getAPMStatus returns a set of key/value pairs summarizing the status of the trace-agent.
// If the status can not be obtained for any reason, the returned map will contain an "error"
// key with an explanation.
func getAPMStatus(config config.Component) map[string]interface{} {
port := config.GetInt("apm_config.debug.port")
url := fmt.Sprintf("http://localhost:%d/debug/vars", port)
resp, err := (&http.Client{Timeout: 2 * time.Second}).Get(url)
if err != nil {
return map[string]interface{}{
"port": port,
"error": err.Error(),
}
}
defer resp.Body.Close()
status := make(map[string]interface{})
if err := json.NewDecoder(resp.Body).Decode(&status); err != nil {
return map[string]interface{}{
"port": port,
"error": err.Error(),
}
}
return status
}

func componentStatusCmd(log log.Component, config config.Component, cliParams *cliParams) error {
if len(cliParams.args) != 1 {
return fmt.Errorf("a component name must be specified")
Expand Down
59 changes: 59 additions & 0 deletions pkg/status/apm/apm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.

// Package apm fetch information about the apm agent.
// This will, in time, be migrated to the apm agent component.
package apm

import (
"encoding/json"
"fmt"
"net/http"
"sync"

apiutil "github.com/DataDog/datadog-agent/pkg/api/util"
"github.com/DataDog/datadog-agent/pkg/config"
)

// httpClients should be reused instead of created as needed. They keep cached TCP connections
// that may leak otherwise
var (
httpClient *http.Client
clientInitOnce sync.Once
)

func client() *http.Client {
clientInitOnce.Do(func() {
httpClient = apiutil.GetClient(false)
})

return httpClient
}

// GetAPMStatus returns a set of key/value pairs summarizing the status of the trace-agent.
// If the status can not be obtained for any reason, the returned map will contain an "error"
// key with an explanation.
func GetAPMStatus() map[string]interface{} {
port := config.Datadog.GetInt("apm_config.debug.port")

c := client()
url := fmt.Sprintf("http://localhost:%d/debug/vars", port)
resp, err := apiutil.DoGet(c, url, apiutil.CloseConnection)
if err != nil {
return map[string]interface{}{
"port": port,
"error": err.Error(),
}
}

status := make(map[string]interface{})
if err := json.Unmarshal(resp, &status); err != nil {
return map[string]interface{}{
"port": port,
"error": err.Error(),
}
}
return status
}
2 changes: 2 additions & 0 deletions pkg/status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/DataDog/datadog-agent/pkg/config/utils"
logsStatus "github.com/DataDog/datadog-agent/pkg/logs/status"
"github.com/DataDog/datadog-agent/pkg/snmp/traps"
"github.com/DataDog/datadog-agent/pkg/status/apm"
"github.com/DataDog/datadog-agent/pkg/status/collector"
"github.com/DataDog/datadog-agent/pkg/status/jmx"
"github.com/DataDog/datadog-agent/pkg/status/otlp"
Expand Down Expand Up @@ -82,6 +83,7 @@ func GetStatus(verbose bool, invAgent inventoryagent.Component) (map[string]inte
}

stats["processAgentStatus"] = GetProcessAgentStatus()
stats["apmStats"] = apm.GetAPMStatus()

if !config.Datadog.GetBool("no_proxy_nonexact_match") {
stats["TransportWarnings"] = httputils.GetNumberOfWarnings() > 0
Expand Down

0 comments on commit d13e6ec

Please sign in to comment.