diff --git a/docs/docset.yml b/docs/docset.yml new file mode 100644 index 0000000..8dddbaf --- /dev/null +++ b/docs/docset.yml @@ -0,0 +1,489 @@ +project: 'ECS Logging Node.js' +cross_links: + - apm-agent-nodejs + - beats + - docs-content + - ecs + - ecs-logging +toc: + - toc: reference +subs: + ref: "https://www.elastic.co/guide/en/elasticsearch/reference/current" + ref-bare: "https://www.elastic.co/guide/en/elasticsearch/reference" + ref-8x: "https://www.elastic.co/guide/en/elasticsearch/reference/8.1" + ref-80: "https://www.elastic.co/guide/en/elasticsearch/reference/8.0" + ref-7x: "https://www.elastic.co/guide/en/elasticsearch/reference/7.17" + ref-70: "https://www.elastic.co/guide/en/elasticsearch/reference/7.0" + ref-60: "https://www.elastic.co/guide/en/elasticsearch/reference/6.0" + ref-64: "https://www.elastic.co/guide/en/elasticsearch/reference/6.4" + xpack-ref: "https://www.elastic.co/guide/en/x-pack/6.2" + logstash-ref: "https://www.elastic.co/guide/en/logstash/current" + kibana-ref: "https://www.elastic.co/guide/en/kibana/current" + kibana-ref-all: "https://www.elastic.co/guide/en/kibana" + beats-ref-root: "https://www.elastic.co/guide/en/beats" + beats-ref: "https://www.elastic.co/guide/en/beats/libbeat/current" + beats-ref-60: "https://www.elastic.co/guide/en/beats/libbeat/6.0" + beats-ref-63: "https://www.elastic.co/guide/en/beats/libbeat/6.3" + beats-devguide: "https://www.elastic.co/guide/en/beats/devguide/current" + auditbeat-ref: "https://www.elastic.co/guide/en/beats/auditbeat/current" + packetbeat-ref: "https://www.elastic.co/guide/en/beats/packetbeat/current" + metricbeat-ref: "https://www.elastic.co/guide/en/beats/metricbeat/current" + filebeat-ref: "https://www.elastic.co/guide/en/beats/filebeat/current" + functionbeat-ref: "https://www.elastic.co/guide/en/beats/functionbeat/current" + winlogbeat-ref: "https://www.elastic.co/guide/en/beats/winlogbeat/current" + heartbeat-ref: "https://www.elastic.co/guide/en/beats/heartbeat/current" + journalbeat-ref: "https://www.elastic.co/guide/en/beats/journalbeat/current" + ingest-guide: "https://www.elastic.co/guide/en/ingest/current" + fleet-guide: "https://www.elastic.co/guide/en/fleet/current" + apm-guide-ref: "https://www.elastic.co/guide/en/apm/guide/current" + apm-guide-7x: "https://www.elastic.co/guide/en/apm/guide/7.17" + apm-app-ref: "https://www.elastic.co/guide/en/kibana/current" + apm-agents-ref: "https://www.elastic.co/guide/en/apm/agent" + apm-android-ref: "https://www.elastic.co/guide/en/apm/agent/android/current" + apm-py-ref: "https://www.elastic.co/guide/en/apm/agent/python/current" + apm-py-ref-3x: "https://www.elastic.co/guide/en/apm/agent/python/3.x" + apm-node-ref-index: "https://www.elastic.co/guide/en/apm/agent/nodejs" + apm-node-ref: "https://www.elastic.co/guide/en/apm/agent/nodejs/current" + apm-node-ref-1x: "https://www.elastic.co/guide/en/apm/agent/nodejs/1.x" + apm-rum-ref: "https://www.elastic.co/guide/en/apm/agent/rum-js/current" + apm-ruby-ref: "https://www.elastic.co/guide/en/apm/agent/ruby/current" + apm-java-ref: "https://www.elastic.co/guide/en/apm/agent/java/current" + apm-go-ref: "https://www.elastic.co/guide/en/apm/agent/go/current" + apm-dotnet-ref: "https://www.elastic.co/guide/en/apm/agent/dotnet/current" + apm-php-ref: "https://www.elastic.co/guide/en/apm/agent/php/current" + apm-ios-ref: "https://www.elastic.co/guide/en/apm/agent/swift/current" + apm-lambda-ref: "https://www.elastic.co/guide/en/apm/lambda/current" + apm-attacher-ref: "https://www.elastic.co/guide/en/apm/attacher/current" + docker-logging-ref: "https://www.elastic.co/guide/en/beats/loggingplugin/current" + esf-ref: "https://www.elastic.co/guide/en/esf/current" + kinesis-firehose-ref: "https://www.elastic.co/guide/en/kinesis/{{kinesis_version}}" + estc-welcome-current: "https://www.elastic.co/guide/en/starting-with-the-elasticsearch-platform-and-its-solutions/current" + estc-welcome: "https://www.elastic.co/guide/en/starting-with-the-elasticsearch-platform-and-its-solutions/current" + estc-welcome-all: "https://www.elastic.co/guide/en/starting-with-the-elasticsearch-platform-and-its-solutions" + hadoop-ref: "https://www.elastic.co/guide/en/elasticsearch/hadoop/current" + stack-ref: "https://www.elastic.co/guide/en/elastic-stack/current" + stack-ref-67: "https://www.elastic.co/guide/en/elastic-stack/6.7" + stack-ref-68: "https://www.elastic.co/guide/en/elastic-stack/6.8" + stack-ref-70: "https://www.elastic.co/guide/en/elastic-stack/7.0" + stack-ref-80: "https://www.elastic.co/guide/en/elastic-stack/8.0" + stack-ov: "https://www.elastic.co/guide/en/elastic-stack-overview/current" + stack-gs: "https://www.elastic.co/guide/en/elastic-stack-get-started/current" + stack-gs-current: "https://www.elastic.co/guide/en/elastic-stack-get-started/current" + javaclient: "https://www.elastic.co/guide/en/elasticsearch/client/java-api/current" + java-api-client: "https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current" + java-rest: "https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current" + jsclient: "https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current" + jsclient-current: "https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current" + es-ruby-client: "https://www.elastic.co/guide/en/elasticsearch/client/ruby-api/current" + es-dotnet-client: "https://www.elastic.co/guide/en/elasticsearch/client/net-api/current" + es-php-client: "https://www.elastic.co/guide/en/elasticsearch/client/php-api/current" + es-python-client: "https://www.elastic.co/guide/en/elasticsearch/client/python-api/current" + defguide: "https://www.elastic.co/guide/en/elasticsearch/guide/2.x" + painless: "https://www.elastic.co/guide/en/elasticsearch/painless/current" + plugins: "https://www.elastic.co/guide/en/elasticsearch/plugins/current" + plugins-8x: "https://www.elastic.co/guide/en/elasticsearch/plugins/8.1" + plugins-7x: "https://www.elastic.co/guide/en/elasticsearch/plugins/7.17" + plugins-6x: "https://www.elastic.co/guide/en/elasticsearch/plugins/6.8" + glossary: "https://www.elastic.co/guide/en/elastic-stack-glossary/current" + upgrade_guide: "https://www.elastic.co/products/upgrade_guide" + blog-ref: "https://www.elastic.co/blog/" + curator-ref: "https://www.elastic.co/guide/en/elasticsearch/client/curator/current" + curator-ref-current: "https://www.elastic.co/guide/en/elasticsearch/client/curator/current" + metrics-ref: "https://www.elastic.co/guide/en/metrics/current" + metrics-guide: "https://www.elastic.co/guide/en/metrics/guide/current" + logs-ref: "https://www.elastic.co/guide/en/logs/current" + logs-guide: "https://www.elastic.co/guide/en/logs/guide/current" + uptime-guide: "https://www.elastic.co/guide/en/uptime/current" + observability-guide: "https://www.elastic.co/guide/en/observability/current" + observability-guide-all: "https://www.elastic.co/guide/en/observability" + siem-guide: "https://www.elastic.co/guide/en/siem/guide/current" + security-guide: "https://www.elastic.co/guide/en/security/current" + security-guide-all: "https://www.elastic.co/guide/en/security" + endpoint-guide: "https://www.elastic.co/guide/en/endpoint/current" + sql-odbc: "https://www.elastic.co/guide/en/elasticsearch/sql-odbc/current" + ecs-ref: "https://www.elastic.co/guide/en/ecs/current" + ecs-logging-ref: "https://www.elastic.co/guide/en/ecs-logging/overview/current" + ecs-logging-go-logrus-ref: "https://www.elastic.co/guide/en/ecs-logging/go-logrus/current" + ecs-logging-go-zap-ref: "https://www.elastic.co/guide/en/ecs-logging/go-zap/current" + ecs-logging-go-zerolog-ref: "https://www.elastic.co/guide/en/ecs-logging/go-zap/current" + ecs-logging-java-ref: "https://www.elastic.co/guide/en/ecs-logging/java/current" + ecs-logging-dotnet-ref: "https://www.elastic.co/guide/en/ecs-logging/dotnet/current" + ecs-logging-nodejs-ref: "https://www.elastic.co/guide/en/ecs-logging/nodejs/current" + ecs-logging-php-ref: "https://www.elastic.co/guide/en/ecs-logging/php/current" + ecs-logging-python-ref: "https://www.elastic.co/guide/en/ecs-logging/python/current" + ecs-logging-ruby-ref: "https://www.elastic.co/guide/en/ecs-logging/ruby/current" + ml-docs: "https://www.elastic.co/guide/en/machine-learning/current" + eland-docs: "https://www.elastic.co/guide/en/elasticsearch/client/eland/current" + eql-ref: "https://eql.readthedocs.io/en/latest/query-guide" + extendtrial: "https://www.elastic.co/trialextension" + wikipedia: "https://en.wikipedia.org/wiki" + forum: "https://discuss.elastic.co/" + xpack-forum: "https://discuss.elastic.co/c/50-x-pack" + security-forum: "https://discuss.elastic.co/c/x-pack/shield" + watcher-forum: "https://discuss.elastic.co/c/x-pack/watcher" + monitoring-forum: "https://discuss.elastic.co/c/x-pack/marvel" + graph-forum: "https://discuss.elastic.co/c/x-pack/graph" + apm-forum: "https://discuss.elastic.co/c/apm" + enterprise-search-ref: "https://www.elastic.co/guide/en/enterprise-search/current" + app-search-ref: "https://www.elastic.co/guide/en/app-search/current" + workplace-search-ref: "https://www.elastic.co/guide/en/workplace-search/current" + enterprise-search-node-ref: "https://www.elastic.co/guide/en/enterprise-search-clients/enterprise-search-node/current" + enterprise-search-php-ref: "https://www.elastic.co/guide/en/enterprise-search-clients/php/current" + enterprise-search-python-ref: "https://www.elastic.co/guide/en/enterprise-search-clients/python/current" + enterprise-search-ruby-ref: "https://www.elastic.co/guide/en/enterprise-search-clients/ruby/current" + elastic-maps-service: "https://maps.elastic.co" + integrations-docs: "https://docs.elastic.co/en/integrations" + integrations-devguide: "https://www.elastic.co/guide/en/integrations-developer/current" + time-units: "https://www.elastic.co/guide/en/elasticsearch/reference/current/api-conventions.html#time-units" + byte-units: "https://www.elastic.co/guide/en/elasticsearch/reference/current/api-conventions.html#byte-units" + apm-py-ref-v: "https://www.elastic.co/guide/en/apm/agent/python/current" + apm-node-ref-v: "https://www.elastic.co/guide/en/apm/agent/nodejs/current" + apm-rum-ref-v: "https://www.elastic.co/guide/en/apm/agent/rum-js/current" + apm-ruby-ref-v: "https://www.elastic.co/guide/en/apm/agent/ruby/current" + apm-java-ref-v: "https://www.elastic.co/guide/en/apm/agent/java/current" + apm-go-ref-v: "https://www.elastic.co/guide/en/apm/agent/go/current" + apm-ios-ref-v: "https://www.elastic.co/guide/en/apm/agent/swift/current" + apm-dotnet-ref-v: "https://www.elastic.co/guide/en/apm/agent/dotnet/current" + apm-php-ref-v: "https://www.elastic.co/guide/en/apm/agent/php/current" + ecloud: "Elastic Cloud" + esf: "Elastic Serverless Forwarder" + ess: "Elasticsearch Service" + ece: "Elastic Cloud Enterprise" + eck: "Elastic Cloud on Kubernetes" + serverless-full: "Elastic Cloud Serverless" + serverless-short: "Serverless" + es-serverless: "Elasticsearch Serverless" + es3: "Elasticsearch Serverless" + obs-serverless: "Elastic Observability Serverless" + sec-serverless: "Elastic Security Serverless" + serverless-docs: "https://docs.elastic.co/serverless" + cloud: "https://www.elastic.co/guide/en/cloud/current" + ess-utm-params: "?page=docs&placement=docs-body" + ess-baymax: "?page=docs&placement=docs-body" + ess-trial: "https://cloud.elastic.co/registration?page=docs&placement=docs-body" + ess-product: "https://www.elastic.co/cloud/elasticsearch-service?page=docs&placement=docs-body" + ess-console: "https://cloud.elastic.co?page=docs&placement=docs-body" + ess-console-name: "Elasticsearch Service Console" + ess-deployments: "https://cloud.elastic.co/deployments?page=docs&placement=docs-body" + ece-ref: "https://www.elastic.co/guide/en/cloud-enterprise/current" + eck-ref: "https://www.elastic.co/guide/en/cloud-on-k8s/current" + ess-leadin: "You can run Elasticsearch on your own hardware or use our hosted Elasticsearch Service that is available on AWS, GCP, and Azure. https://cloud.elastic.co/registration{ess-utm-params}[Try the Elasticsearch Service for free]." + ess-leadin-short: "Our hosted Elasticsearch Service is available on AWS, GCP, and Azure, and you can https://cloud.elastic.co/registration{ess-utm-params}[try it for free]." + ess-icon: "image:https://doc-icons.s3.us-east-2.amazonaws.com/logo_cloud.svg[link=\"https://cloud.elastic.co/registration{ess-utm-params}\", title=\"Supported on Elasticsearch Service\"]" + ece-icon: "image:https://doc-icons.s3.us-east-2.amazonaws.com/logo_cloud_ece.svg[link=\"https://cloud.elastic.co/registration{ess-utm-params}\", title=\"Supported on Elastic Cloud Enterprise\"]" + cloud-only: "This feature is designed for indirect use by https://cloud.elastic.co/registration{ess-utm-params}[Elasticsearch Service], https://www.elastic.co/guide/en/cloud-enterprise/{ece-version-link}[Elastic Cloud Enterprise], and https://www.elastic.co/guide/en/cloud-on-k8s/current[Elastic Cloud on Kubernetes]. Direct use is not supported." + ess-setting-change: "image:https://doc-icons.s3.us-east-2.amazonaws.com/logo_cloud.svg[link=\"{ess-trial}\", title=\"Supported on {ess}\"] indicates a change to a supported https://www.elastic.co/guide/en/cloud/current/ec-add-user-settings.html[user setting] for Elasticsearch Service." + ess-skip-section: "If you use Elasticsearch Service, skip this section. Elasticsearch Service handles these changes for you." + api-cloud: "https://www.elastic.co/docs/api/doc/cloud" + api-ece: "https://www.elastic.co/docs/api/doc/cloud-enterprise" + api-kibana-serverless: "https://www.elastic.co/docs/api/doc/serverless" + es-feature-flag: "This feature is in development and not yet available for use. This documentation is provided for informational purposes only." + es-ref-dir: "'{{elasticsearch-root}}/docs/reference'" + apm-app: "APM app" + uptime-app: "Uptime app" + synthetics-app: "Synthetics app" + logs-app: "Logs app" + metrics-app: "Metrics app" + infrastructure-app: "Infrastructure app" + siem-app: "SIEM app" + security-app: "Elastic Security app" + ml-app: "Machine Learning" + dev-tools-app: "Dev Tools" + ingest-manager-app: "Ingest Manager" + stack-manage-app: "Stack Management" + stack-monitor-app: "Stack Monitoring" + alerts-ui: "Alerts and Actions" + rules-ui: "Rules" + rac-ui: "Rules and Connectors" + connectors-ui: "Connectors" + connectors-feature: "Actions and Connectors" + stack-rules-feature: "Stack Rules" + user-experience: "User Experience" + ems: "Elastic Maps Service" + ems-init: "EMS" + hosted-ems: "Elastic Maps Server" + ipm-app: "Index Pattern Management" + ingest-pipelines: "ingest pipelines" + ingest-pipelines-app: "Ingest Pipelines" + ingest-pipelines-cap: "Ingest pipelines" + ls-pipelines: "Logstash pipelines" + ls-pipelines-app: "Logstash Pipelines" + maint-windows: "maintenance windows" + maint-windows-app: "Maintenance Windows" + maint-windows-cap: "Maintenance windows" + custom-roles-app: "Custom Roles" + data-source: "data view" + data-sources: "data views" + data-source-caps: "Data View" + data-sources-caps: "Data Views" + data-source-cap: "Data view" + data-sources-cap: "Data views" + project-settings: "Project settings" + manage-app: "Management" + index-manage-app: "Index Management" + data-views-app: "Data Views" + rules-app: "Rules" + saved-objects-app: "Saved Objects" + tags-app: "Tags" + api-keys-app: "API keys" + transforms-app: "Transforms" + connectors-app: "Connectors" + files-app: "Files" + reports-app: "Reports" + maps-app: "Maps" + alerts-app: "Alerts" + crawler: "Enterprise Search web crawler" + ents: "Enterprise Search" + app-search-crawler: "App Search web crawler" + agent: "Elastic Agent" + agents: "Elastic Agents" + fleet: "Fleet" + fleet-server: "Fleet Server" + integrations-server: "Integrations Server" + ingest-manager: "Ingest Manager" + ingest-management: "ingest management" + package-manager: "Elastic Package Manager" + integrations: "Integrations" + package-registry: "Elastic Package Registry" + artifact-registry: "Elastic Artifact Registry" + aws: "AWS" + stack: "Elastic Stack" + xpack: "X-Pack" + es: "Elasticsearch" + kib: "Kibana" + esms: "Elastic Stack Monitoring Service" + esms-init: "ESMS" + ls: "Logstash" + beats: "Beats" + auditbeat: "Auditbeat" + filebeat: "Filebeat" + heartbeat: "Heartbeat" + metricbeat: "Metricbeat" + packetbeat: "Packetbeat" + winlogbeat: "Winlogbeat" + functionbeat: "Functionbeat" + journalbeat: "Journalbeat" + es-sql: "Elasticsearch SQL" + esql: "ES|QL" + elastic-agent: "Elastic Agent" + k8s: "Kubernetes" + log-driver-long: "Elastic Logging Plugin for Docker" + security: "X-Pack security" + security-features: "security features" + operator-feature: "operator privileges feature" + es-security-features: "Elasticsearch security features" + stack-security-features: "Elastic Stack security features" + endpoint-sec: "Endpoint Security" + endpoint-cloud-sec: "Endpoint and Cloud Security" + elastic-defend: "Elastic Defend" + elastic-sec: "Elastic Security" + elastic-endpoint: "Elastic Endpoint" + swimlane: "Swimlane" + sn: "ServiceNow" + sn-itsm: "ServiceNow ITSM" + sn-itom: "ServiceNow ITOM" + sn-sir: "ServiceNow SecOps" + jira: "Jira" + ibm-r: "IBM Resilient" + webhook: "Webhook" + webhook-cm: "Webhook - Case Management" + opsgenie: "Opsgenie" + bedrock: "Amazon Bedrock" + gemini: "Google Gemini" + hive: "TheHive" + monitoring: "X-Pack monitoring" + monitor-features: "monitoring features" + stack-monitor-features: "Elastic Stack monitoring features" + watcher: "Watcher" + alert-features: "alerting features" + reporting: "X-Pack reporting" + report-features: "reporting features" + graph: "X-Pack graph" + graph-features: "graph analytics features" + searchprofiler: "Search Profiler" + xpackml: "X-Pack machine learning" + ml: "machine learning" + ml-cap: "Machine learning" + ml-init: "ML" + ml-features: "machine learning features" + stack-ml-features: "Elastic Stack machine learning features" + ccr: "cross-cluster replication" + ccr-cap: "Cross-cluster replication" + ccr-init: "CCR" + ccs: "cross-cluster search" + ccs-cap: "Cross-cluster search" + ccs-init: "CCS" + ilm: "index lifecycle management" + ilm-cap: "Index lifecycle management" + ilm-init: "ILM" + dlm: "data lifecycle management" + dlm-cap: "Data lifecycle management" + dlm-init: "DLM" + search-snap: "searchable snapshot" + search-snaps: "searchable snapshots" + search-snaps-cap: "Searchable snapshots" + slm: "snapshot lifecycle management" + slm-cap: "Snapshot lifecycle management" + slm-init: "SLM" + rollup-features: "data rollup features" + ipm: "index pattern management" + ipm-cap: "Index pattern" + rollup: "rollup" + rollup-cap: "Rollup" + rollups: "rollups" + rollups-cap: "Rollups" + rollup-job: "rollup job" + rollup-jobs: "rollup jobs" + rollup-jobs-cap: "Rollup jobs" + dfeed: "datafeed" + dfeeds: "datafeeds" + dfeed-cap: "Datafeed" + dfeeds-cap: "Datafeeds" + ml-jobs: "machine learning jobs" + ml-jobs-cap: "Machine learning jobs" + anomaly-detect: "anomaly detection" + anomaly-detect-cap: "Anomaly detection" + anomaly-job: "anomaly detection job" + anomaly-jobs: "anomaly detection jobs" + anomaly-jobs-cap: "Anomaly detection jobs" + dataframe: "data frame" + dataframes: "data frames" + dataframe-cap: "Data frame" + dataframes-cap: "Data frames" + watcher-transform: "payload transform" + watcher-transforms: "payload transforms" + watcher-transform-cap: "Payload transform" + watcher-transforms-cap: "Payload transforms" + transform: "transform" + transforms: "transforms" + transform-cap: "Transform" + transforms-cap: "Transforms" + dataframe-transform: "transform" + dataframe-transform-cap: "Transform" + dataframe-transforms: "transforms" + dataframe-transforms-cap: "Transforms" + dfanalytics-cap: "Data frame analytics" + dfanalytics: "data frame analytics" + dataframe-analytics-config: "'{dataframe} analytics config'" + dfanalytics-job: "'{dataframe} analytics job'" + dfanalytics-jobs: "'{dataframe} analytics jobs'" + dfanalytics-jobs-cap: "'{dataframe-cap} analytics jobs'" + cdataframe: "continuous data frame" + cdataframes: "continuous data frames" + cdataframe-cap: "Continuous data frame" + cdataframes-cap: "Continuous data frames" + cdataframe-transform: "continuous transform" + cdataframe-transforms: "continuous transforms" + cdataframe-transforms-cap: "Continuous transforms" + ctransform: "continuous transform" + ctransform-cap: "Continuous transform" + ctransforms: "continuous transforms" + ctransforms-cap: "Continuous transforms" + oldetection: "outlier detection" + oldetection-cap: "Outlier detection" + olscore: "outlier score" + olscores: "outlier scores" + fiscore: "feature influence score" + evaluatedf-api: "evaluate {dataframe} analytics API" + evaluatedf-api-cap: "Evaluate {dataframe} analytics API" + binarysc: "binary soft classification" + binarysc-cap: "Binary soft classification" + regression: "regression" + regression-cap: "Regression" + reganalysis: "regression analysis" + reganalysis-cap: "Regression analysis" + depvar: "dependent variable" + feature-var: "feature variable" + feature-vars: "feature variables" + feature-vars-cap: "Feature variables" + classification: "classification" + classification-cap: "Classification" + classanalysis: "classification analysis" + classanalysis-cap: "Classification analysis" + infer-cap: "Inference" + infer: "inference" + lang-ident-cap: "Language identification" + lang-ident: "language identification" + data-viz: "Data Visualizer" + file-data-viz: "File Data Visualizer" + feat-imp: "feature importance" + feat-imp-cap: "Feature importance" + nlp: "natural language processing" + nlp-cap: "Natural language processing" + apm-agent: "APM agent" + apm-go-agent: "Elastic APM Go agent" + apm-go-agents: "Elastic APM Go agents" + apm-ios-agent: "Elastic APM iOS agent" + apm-ios-agents: "Elastic APM iOS agents" + apm-java-agent: "Elastic APM Java agent" + apm-java-agents: "Elastic APM Java agents" + apm-dotnet-agent: "Elastic APM .NET agent" + apm-dotnet-agents: "Elastic APM .NET agents" + apm-node-agent: "Elastic APM Node.js agent" + apm-node-agents: "Elastic APM Node.js agents" + apm-php-agent: "Elastic APM PHP agent" + apm-php-agents: "Elastic APM PHP agents" + apm-py-agent: "Elastic APM Python agent" + apm-py-agents: "Elastic APM Python agents" + apm-ruby-agent: "Elastic APM Ruby agent" + apm-ruby-agents: "Elastic APM Ruby agents" + apm-rum-agent: "Elastic APM Real User Monitoring (RUM) JavaScript agent" + apm-rum-agents: "Elastic APM RUM JavaScript agents" + apm-lambda-ext: "Elastic APM AWS Lambda extension" + project-monitors: "project monitors" + project-monitors-cap: "Project monitors" + private-location: "Private Location" + private-locations: "Private Locations" + pwd: "YOUR_PASSWORD" + esh: "ES-Hadoop" + default-dist: "default distribution" + oss-dist: "OSS-only distribution" + observability: "Observability" + api-request-title: "Request" + api-prereq-title: "Prerequisites" + api-description-title: "Description" + api-path-parms-title: "Path parameters" + api-query-parms-title: "Query parameters" + api-request-body-title: "Request body" + api-response-codes-title: "Response codes" + api-response-body-title: "Response body" + api-example-title: "Example" + api-examples-title: "Examples" + api-definitions-title: "Properties" + multi-arg: "†footnoteref:[multi-arg,This parameter accepts multiple arguments.]" + multi-arg-ref: "†footnoteref:[multi-arg]" + yes-icon: "image:https://doc-icons.s3.us-east-2.amazonaws.com/icon-yes.png[Yes,20,15]" + no-icon: "image:https://doc-icons.s3.us-east-2.amazonaws.com/icon-no.png[No,20,15]" + es-repo: "https://github.com/elastic/elasticsearch/" + es-issue: "https://github.com/elastic/elasticsearch/issues/" + es-pull: "https://github.com/elastic/elasticsearch/pull/" + es-commit: "https://github.com/elastic/elasticsearch/commit/" + kib-repo: "https://github.com/elastic/kibana/" + kib-issue: "https://github.com/elastic/kibana/issues/" + kibana-issue: "'{kib-repo}issues/'" + kib-pull: "https://github.com/elastic/kibana/pull/" + kibana-pull: "'{kib-repo}pull/'" + kib-commit: "https://github.com/elastic/kibana/commit/" + ml-repo: "https://github.com/elastic/ml-cpp/" + ml-issue: "https://github.com/elastic/ml-cpp/issues/" + ml-pull: "https://github.com/elastic/ml-cpp/pull/" + ml-commit: "https://github.com/elastic/ml-cpp/commit/" + apm-repo: "https://github.com/elastic/apm-server/" + apm-issue: "https://github.com/elastic/apm-server/issues/" + apm-pull: "https://github.com/elastic/apm-server/pull/" + kibana-blob: "https://github.com/elastic/kibana/blob/current/" + apm-get-started-ref: "https://www.elastic.co/guide/en/apm/get-started/current" + apm-server-ref: "https://www.elastic.co/guide/en/apm/server/current" + apm-server-ref-v: "https://www.elastic.co/guide/en/apm/server/current" + apm-server-ref-m: "https://www.elastic.co/guide/en/apm/server/master" + apm-server-ref-62: "https://www.elastic.co/guide/en/apm/server/6.2" + apm-server-ref-64: "https://www.elastic.co/guide/en/apm/server/6.4" + apm-server-ref-70: "https://www.elastic.co/guide/en/apm/server/7.0" + apm-overview-ref-v: "https://www.elastic.co/guide/en/apm/get-started/current" + apm-overview-ref-70: "https://www.elastic.co/guide/en/apm/get-started/7.0" + apm-overview-ref-m: "https://www.elastic.co/guide/en/apm/get-started/master" + infra-guide: "https://www.elastic.co/guide/en/infrastructure/guide/current" + a-data-source: "a data view" + icon-bug: "pass:[]" + icon-checkInCircleFilled: "pass:[]" + icon-warningFilled: "pass:[]" diff --git a/docs/index.asciidoc b/docs/index.asciidoc deleted file mode 100644 index 3b966df..0000000 --- a/docs/index.asciidoc +++ /dev/null @@ -1,18 +0,0 @@ -:ecs-repo-dir: {ecs-logging-root}/docs/ - -include::{docs-root}/shared/versions/stack/current.asciidoc[] -include::{docs-root}/shared/attributes.asciidoc[] - -ifdef::env-github[] -NOTE: For the best reading experience, -please view this documentation at https://www.elastic.co/guide/en/ecs-logging/nodejs/current/index.html[elastic.co] -endif::[] - -= ECS Logging Node.js Reference - -ifndef::env-github[] -include::./intro.asciidoc[Introduction] -include::./pino.asciidoc[Logging with Pino] -include::./winston.asciidoc[Logging with Winston] -include::./morgan.asciidoc[Logging with Morgan] -endif::[] diff --git a/docs/intro.asciidoc b/docs/intro.asciidoc deleted file mode 100644 index 20fce91..0000000 --- a/docs/intro.asciidoc +++ /dev/null @@ -1,33 +0,0 @@ -[[intro]] -== Introduction - -Node.js ECS loggers are formatter plugins for your favorite logging libraries. -They make it easy to format your logs into ECS-compatible JSON. In combination -with https://www.elastic.co/products/beats/filebeat[filebeat] you can send your -logs directly to Elasticsearch and leverage {observability-guide}/monitor-logs.html[Kibana's Logs app] -to inspect all logs in one single place. - -The Node.js ECS logging formatters log structured JSON and support serialization -of Error objects and HTTP Request and Response objects from Node.js core and -popular web frameworks. A minimal log record includes the following fields: - -[source,json] ----- -{ - "@timestamp": "2021-01-13T21:32:38.095Z", - "log.level": "info", - "message": "hi", - "ecs.version": "8.10.0" -} ----- - -TIP: Want to learn more about ECS, ECS logging, and other available language plugins? -See the {ecs-logging-ref}/intro.html[ECS logging guide]. - -Ready to jump into Node.js ECS logging? - -- <> -- <> -- <> - -If you'd like to try out a tutorial using Node.js ECS logging with winston, see {cloud}/ec-getting-started-search-use-cases-node-logs.html[Ingest logs from a Node.js web application using Filebeat]. diff --git a/docs/morgan.asciidoc b/docs/morgan.asciidoc deleted file mode 100644 index 1166da5..0000000 --- a/docs/morgan.asciidoc +++ /dev/null @@ -1,226 +0,0 @@ -[[morgan]] -== ECS Logging with Morgan - -This Node.js package provides a formatter for the https://github.com/expressjs/morgan#readme[morgan] -logging middleware -- commonly used with Express -- compatible with -{ecs-logging-ref}/intro.html[Elastic Common Schema (ECS) logging]. -In combination with the https://www.elastic.co/beats/filebeat[Filebeat] shipper, -you can https://www.elastic.co/log-monitoring[monitor all your logs] in one -place in the Elastic Stack. - - -[float] -=== Setup - -[float] -[[morgan-setup-step-1]] -==== Step 1: Install - -[source,cmd] ----- -$ npm install @elastic/ecs-morgan-format ----- - - -[float] -[[morgan-setup-step-2]] -==== Step 2: Configure - -[source,js] ----- -const app = require('express')(); -const morgan = require('morgan'); -const { ecsFormat } = require('@elastic/ecs-morgan-format'); - -app.use(morgan(ecsFormat(/* options */))); <1> - -// ... -app.get('/', function (req, res) { - res.send('hello, world!'); -}) -app.listen(3000); ----- -<1> Pass the ECS formatter to `morgan()`. - - -[float] -[[morgan-setup-step-3]] -==== Step 3: Configure Filebeat - -The best way to collect the logs once they are ECS-formatted is with {filebeat-ref}[Filebeat]: - -include::{ecs-repo-dir}/setup.asciidoc[tag=configure-filebeat] - - -[float] -[[morgan-usage]] -=== Usage - -[source,js] ----- -const app = require('express')(); -const morgan = require('morgan'); -const { ecsFormat } = require('@elastic/ecs-morgan-format'); - -app.use(morgan(ecsFormat(/* options */))); <1> - -app.get('/', function (req, res) { - res.send('hello, world!'); -}) -app.get('/error', function (req, res, next) { - next(new Error('boom')); -}) - -app.listen(3000) ----- -<1> See available options <>. - -Running this script (the full example is https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-morgan-format/examples/express.js[here]) -and making a request (via `curl -i localhost:3000/`) will produce log output -similar to the following: - -[source,cmd] ----- -% node examples/express.js | jq . # piping to jq for pretty-printing -{ - "@timestamp": "2021-01-16T00:03:23.279Z", - "log.level": "info", - "message": "::1 - - [16/Jan/2021:00:03:23 +0000] \"GET / HTTP/1.1\" 200 13 \"-\" \"curl/7.64.1\"", - "ecs.version": "8.10.0", - "http": { - "version": "1.1", - "request": { - "method": "GET", - "headers": { - "host": "localhost:3000", - "accept": "*/*" - } - }, - "response": { - "status_code": 200, - "headers": { - "x-powered-by": "Express", - "content-type": "text/html; charset=utf-8", - "etag": "W/\"d-HwnTDHB9U/PRbFMN1z1wps51lqk\"" - }, - "body": { - "bytes": 13 - } - } - }, - "url": { - "path": "/", - "domain": "localhost", - "full": "http://localhost:3000/" - }, - "user_agent": { - "original": "curl/7.64.1" - } -} ----- - -[float] -[[morgan-format-options]] -=== Format Options - -You can pass any https://github.com/expressjs/morgan#morganformat-options[`format` argument] -you would normally pass to `morgan()`, and the log "message" field will use the -specified format. The default is https://github.com/expressjs/morgan#combined[`combined`]. - -[source,js] ----- -const app = require('express')(); -const morgan = require('morgan'); -const { ecsFormat } = require('@elastic/ecs-morgan-format'); - -app.use(morgan(ecsFormat({ format: 'tiny' }))); <1> -// ... ----- -<1> If "format" is the only option you are using, you may pass it as `ecsFormat('tiny')`. - -[float] -[[morgan-log-level]] -=== log.level - -The `log.level` field will be "error" for response codes >= 500, otherwise -"info". For example, running https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-morgan-format/examples/express.js[examples/express.js] -again, a `curl -i localhost:3000/error` will yield: - -[source,cmd] ----- -% node examples/express.js | jq . -{ - "@timestamp": "2021-01-18T17:52:12.810Z", - "log.level": "error", - "message": "::1 - - [18/Jan/2021:17:52:12 +0000] \"GET /error HTTP/1.1\" 500 1416 \"-\" \"curl/7.64.1\"", - "http": { - "response": { - "status_code": 500, - ... ----- - - -[float] -[[morgan-apm]] -=== Log Correlation with APM - -This ECS log formatter integrates with https://www.elastic.co/apm[Elastic APM]. -If your Node app is using the {apm-node-ref}/intro.html[Node.js Elastic APM Agent], -then a number of fields are added to log records to correlate between APM -services or traces and logging data: - -- Log statements (e.g. `logger.info(...)`) called when there is a current - tracing span will include {ecs-ref}/ecs-tracing.html[tracing fields] -- - `trace.id`, `transaction.id`. -- A number of service identifier fields determined by or configured on the APM - agent allow cross-linking between services and logs in Kibana -- - `service.name`, `service.version`, `service.environment`, `service.node.name`. -- `event.dataset` enables {observability-guide}/inspect-log-anomalies.html[log - rate anomaly detection] in the Elastic Observability app. - -For example, running https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-morgan-format/examples/express-with-apm.js[examples/express-with-apm.js] and `curl -i localhost:3000/` results in a log record with the following: - -[source,cmd] ----- -% node examples/express-with-apm.js | jq . -{ - // The same fields as before, plus: - "service.name": "express-with-elastic-apm", - "service.version": "1.1.0", - "service.environment": "development", - "event.dataset": "express-with-elastic-apm", - "trace.id": "116d46f667a7600deed9c41fa015f7de", - "transaction.id": "b84fb72d7bf42866" -} ----- - -These IDs match trace data reported by the APM agent. - -Integration with Elastic APM can be explicitly disabled via the -`apmIntegration: false` option, for example: - -[source,js] ----- -app.use(morgan(ecsFormat({ apmIntegration: false }))); ----- - - -[float] -[[morgan-ref]] -=== Reference - -[float] -[[morgan-ref-ecsFormat]] -==== `ecsFormat([options])` - -* `options` +{type-object}+ The following options are supported: -** `format` +{type-string}+ A format *name* (e.g. 'combined'), format function (e.g. `morgan.combined`), or a format string (e.g. ':method :url :status'). This is used to format the "message" field. Defaults to `morgan.combined`. -** `convertErr` +{type-boolean}+ Whether to convert a logged `err` field to ECS error fields. *Default:* `true`. -** `apmIntegration` +{type-boolean}+ Whether to enable APM agent integration. *Default:* `true`. -** `serviceName` +{type-string}+ A "service.name" value. If specified this overrides any value from an active APM agent. -** `serviceVersion` +{type-string}+ A "service.version" value. If specified this overrides any value from an active APM agent. -** `serviceEnvironment` +{type-string}+ A "service.environment" value. If specified this overrides any value from an active APM agent. -** `serviceNodeName` +{type-string}+ A "service.node.name" value. If specified this overrides any value from an active APM agent. -** `eventDataset` +{type-string}+ A "event.dataset" value. If specified this overrides the default of using `${serviceVersion}`. - -Create a formatter for morgan that emits in ECS Logging format. diff --git a/docs/pino.asciidoc b/docs/pino.asciidoc deleted file mode 100644 index f0855d5..0000000 --- a/docs/pino.asciidoc +++ /dev/null @@ -1,286 +0,0 @@ -[[pino]] -== ECS Logging with Pino - -This Node.js package provides a formatter for the https://getpino.io[pino] -logger, compatible with {ecs-logging-ref}/intro.html[Elastic Common Schema (ECS) logging]. -In combination with the https://www.elastic.co/beats/filebeat[Filebeat] shipper, -you can https://www.elastic.co/log-monitoring[monitor all your logs] in one -place in the Elastic Stack. `pino` 6.x, 7.x, and 8.x versions are supported. - - -[float] -=== Setup - -[float] -[[pino-setup-step-1]] -==== Step 1: Install - -[source,cmd] ----- -$ npm install @elastic/ecs-pino-format ----- - -[float] -[[pino-setup-step-2]] -==== Step 2: Configure - -[source,js] ----- -const { ecsFormat } = require('@elastic/ecs-pino-format'); -const pino = require('pino'); - -const log = pino(ecsFormat(/* options */)); <1> -log.info('hi'); -log.error({ err: new Error('boom') }, 'oops there is a problem'); -// ... ----- -<1> This will https://getpino.io/#/docs/api?id=options[configure] Pino's `formatters`, `messageKey` and `timestamp` options. - -See usage discussion and examples below. - -[float] -[[pino-setup-step-3]] -==== Step 3: Configure Filebeat - -The best way to collect the logs once they are ECS-formatted is with {filebeat-ref}[Filebeat]: - -include::{ecs-repo-dir}/setup.asciidoc[tag=configure-filebeat] - - -[float] -[[pino-usage]] -=== Usage - -[source,js] ----- -const { ecsFormat } = require('@elastic/ecs-pino-format'); -const pino = require('pino'); - -const log = pino(ecsFormat(/* options */)); <1> -log.info('Hello world'); - -const child = log.child({ module: 'foo' }); -child.warn('From child'); ----- -<1> See available options <>. - -Running this will produce log output similar to the following: - -[source,cmd] ----- -{"log.level":"info","@timestamp":"2023-10-14T02:07:47.901Z","process.pid":56645,"host.hostname":"pink.local","ecs.version":"8.10.0","message":"Hello world"} -{"log.level":"warn","@timestamp":"2023-10-14T02:07:47.901Z","process.pid":56645,"host.hostname":"pink.local","ecs.version":"8.10.0","module":"foo","message":"From child"} ----- - -[float] -[[pino-error-logging]] -=== Error Logging - -By default, the formatter will convert an `err` field that is an Error instance -to {ecs-ref}/ecs-error.html[ECS Error fields]. -For example: - -[source,js] ----- -const { ecsFormat } = require('@elastic/ecs-pino-format'); -const pino = require('pino'); -const log = pino(ecsFormat()); - -const myErr = new Error('boom'); -log.info({ err: myErr }, 'oops'); ----- - -will yield (pretty-printed for readability): - -[source,cmd] ----- -% node examples/error.js | jq . -{ - "log.level": "info", - "@timestamp": "2021-01-26T17:02:23.697Z", - ... - "error": { - "type": "Error", - "message": "boom", - "stack_trace": "Error: boom\n at Object. (..." - }, - "message": "oops" -} ----- - -This is analogous to and overrides -https://getpino.io/#/docs/api?id=serializers-object[Pino's default err serializer]. -Special handling of the `err` field can be disabled via the `convertErr: false` option: - -[source,js] ----- -const log = pino(ecsFormat({ convertErr: false })); ----- - - -[float] -[[pino-http-logging]] -=== HTTP Request and Response Logging - -With the `convertReqRes: true` option, the formatter will automatically -convert Node.js core https://nodejs.org/api/http.html#http_class_http_incomingmessage[request] -and https://nodejs.org/api/http.html#http_class_http_serverresponse[response] -objects when passed as the `req` and `res` fields, respectively. -(This option replaces the usage of `req` and `res` https://getpino.io/#/docs/api?id=pinostdserializers-object[Pino serializers].) - -[source,js] ----- -const http = require('http'); -const { ecsFormat } = require('@elastic/ecs-pino-format'); -const pino = require('pino'); - -const log = pino(ecsFormat({ convertReqRes: true })); <1> - -const server = http.createServer(function handler (req, res) { - res.setHeader('Foo', 'Bar'); - res.end('ok'); - log.info({ req, res }, 'handled request'); <2> -}); - -server.listen(3000, () => { - log.info('listening at http://localhost:3000'); -} ----- -<1> use `convertReqRes` option -<2> log with `req` and/or `res` fields - -This will produce logs with request and response info using -{ecs-ref}/ecs-http.html[ECS HTTP fields]. -For example: - -[source,cmd] ----- -% node examples/http.js | jq . # using jq for pretty printing -... # run 'curl http://localhost:3000/' -{ - "log.level": "info", - "@timestamp": "2023-10-14T02:10:14.477Z", - "process.pid": 56697, - "host.hostname": "pink.local", - "ecs.version": "8.10.0", - "http": { - "version": "1.1", - "request": { - "method": "GET", - "headers": { - "host": "localhost:3000", - "user-agent": "curl/8.1.2", - "accept": "*/*" - } - }, - "response": { - "status_code": 200, - "headers": { - "foo": "Bar" - } - } - }, - "url": { - "full": "http://localhost:3000/", - "path": "/" - }, - "client": { - "address": "::ffff:127.0.0.1", - "ip": "::ffff:127.0.0.1", - "port": 49504 - }, - "user_agent": { - "original": "curl/8.1.2" - }, - "message": "handled request" -} ----- - -The https://github.com/elastic/ecs-logging-nodejs/tree/main/packages/ecs-pino-format/examples[examples/ directory] -shows sample programs using request and response logging: -https://github.com/elastic/ecs-logging-nodejs/tree/main/packages/ecs-pino-format/examples/express-simple.js[with Express], -https://github.com/elastic/ecs-logging-nodejs/tree/main/packages/ecs-pino-format/examples/express-with-pino-http.js[with the pino-http middleware package], -etc. - - -[float] -[[pino-apm]] -=== Log Correlation with APM - -This ECS log formatter integrates with https://www.elastic.co/apm[Elastic APM]. -If your Node app is using the {apm-node-ref}/intro.html[Node.js Elastic APM Agent], -then a number of fields are added to log records to correlate between APM -services or traces and logging data: - -- Log statements (e.g. `logger.info(...)`) called when there is a current - tracing span will include {ecs-ref}/ecs-tracing.html[tracing fields] -- - `trace.id`, `transaction.id`, `span.id`. -- A number of service identifier fields determined by or configured on the APM - agent allow cross-linking between services and logs in Kibana -- - `service.name`, `service.version`, `service.environment`, `service.node.name`. -- `event.dataset` enables {observability-guide}/inspect-log-anomalies.html[log - rate anomaly detection] in the Elastic Observability app. - -For example, running https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-pino-format/examples/http-with-elastic-apm.js[examples/http-with-elastic-apm.js] and `curl -i localhost:3000/` results in a log record with the following: - -[source,cmd] ----- -% node examples/http-with-elastic-apm.js | jq . -... - "service.name": "http-with-elastic-apm", - "service.version": "1.4.0", - "service.environment": "development", - "event.dataset": "http-with-elastic-apm", - "trace.id": "9f338eae7211b7993b98929046aed21d", - "transaction.id": "2afbef5642cc7a3f", -... ----- - -These IDs match trace data reported by the APM agent. - -Integration with Elastic APM can be explicitly disabled via the -`apmIntegration: false` option, for example: - -[source,js] ----- -const log = pino(ecsFormat({ apmIntegration: false })); ----- - - -[float] -[[pino-considerations]] -=== Limitations and Considerations - -The https://github.com/elastic/ecs-logging/tree/main/spec[ecs-logging spec] -suggests that the first three fields in log records must be `@timestamp`, -`log.level`, and `message`. Pino does not provide a mechanism to put -the `message` field near the front. Given that ordering of ecs-logging fields -is for *human readability* and does not affect interoperability, this is not -considered a significant concern. - -The hooks that Pino currently provides do not enable this package to convert -fields passed to `.child({ ... })`. This means that, even with the -`convertReqRes` option, a call to `.child({ req })` will *not* convert -that `req` to ECS HTTP fields. This is a slight limitation for users of -https://github.com/pinojs/pino-http[pino-http] which does this. - - -[float] -[[pino-ref]] -=== Reference - -[float] -[[pino-ref-ecsFormat]] -==== `ecsFormat([options])` - -* `options` +{type-object}+ The following options are supported: -** `convertErr` +{type-boolean}+ Whether to convert a logged `err` field to ECS error fields. *Default:* `true`. -** `convertReqRes` +{type-boolean}+ Whether to logged `req` and `res` HTTP request and response fields to ECS HTTP, User agent, and URL fields. *Default:* `false`. -** `apmIntegration` +{type-boolean}+ Whether to enable APM agent integration. *Default:* `true`. -** `serviceName` +{type-string}+ A "service.name" value. If specified this overrides any value from an active APM agent. -** `serviceVersion` +{type-string}+ A "service.version" value. If specified this overrides any value from an active APM agent. -** `serviceEnvironment` +{type-string}+ A "service.environment" value. If specified this overrides any value from an active APM agent. -** `serviceNodeName` +{type-string}+ A "service.node.name" value. If specified this overrides any value from an active APM agent. -** `eventDataset` +{type-string}+ A "event.dataset" value. If specified this overrides the default of using `${serviceVersion}`. - -Create options for `pino(...)` that configures ECS Logging format output. diff --git a/docs/reference/index.md b/docs/reference/index.md new file mode 100644 index 0000000..b05b883 --- /dev/null +++ b/docs/reference/index.md @@ -0,0 +1,34 @@ +--- +mapped_pages: + - https://www.elastic.co/guide/en/ecs-logging/nodejs/current/intro.html + - https://www.elastic.co/guide/en/ecs-logging/nodejs/current/index.html +--- + +# ECS Logging Node.js [intro] + +Node.js ECS loggers are formatter plugins for your favorite logging libraries. They make it easy to format your logs into ECS-compatible JSON. In combination with [filebeat](https://www.elastic.co/products/beats/filebeat) you can send your logs directly to Elasticsearch and leverage [Kibana’s Logs app](docs-content://solutions/observability/logs/explore-logs.md) to inspect all logs in one single place. + +The Node.js ECS logging formatters log structured JSON and support serialization of Error objects and HTTP Request and Response objects from Node.js core and popular web frameworks. A minimal log record includes the following fields: + +```json +{ + "@timestamp": "2021-01-13T21:32:38.095Z", + "log.level": "info", + "message": "hi", + "ecs.version": "8.10.0" +} +``` + +::::{tip} +Want to learn more about ECS, ECS logging, and other available language plugins? See the [ECS logging guide](ecs-logging://docs/reference/intro.md). +:::: + + +Ready to jump into Node.js ECS logging? + +* [ECS Logging with Pino](/reference/pino.md) +* [ECS Logging with Winston](/reference/winston.md) +* [ECS Logging with Morgan](/reference/morgan.md) + +If you’d like to try out a tutorial using Node.js ECS logging with winston, see [Ingest logs from a Node.js web application using Filebeat](docs-content://manage-data/ingest/ingesting-data-from-applications/ingest-logs-from-nodejs-web-application-using-filebeat.md). + diff --git a/docs/reference/morgan.md b/docs/reference/morgan.md new file mode 100644 index 0000000..c461eaa --- /dev/null +++ b/docs/reference/morgan.md @@ -0,0 +1,283 @@ +--- +mapped_pages: + - https://www.elastic.co/guide/en/ecs-logging/nodejs/current/morgan.html +--- + +# ECS Logging with Morgan [morgan] + +This Node.js package provides a formatter for the [morgan](https://github.com/expressjs/morgan#readme) logging middleware — commonly used with Express — compatible with [Elastic Common Schema (ECS) logging](ecs-logging://docs/reference/intro.md). In combination with the [Filebeat](https://www.elastic.co/beats/filebeat) shipper, you can [monitor all your logs](https://www.elastic.co/log-monitoring) in one place in the Elastic Stack. + + +## Setup [_setup_3] + +### Step 1: Install [morgan-setup-step-1] + +```cmd +$ npm install @elastic/ecs-morgan-format +``` + + +### Step 2: Configure [morgan-setup-step-2] + +```js +const app = require('express')(); +const morgan = require('morgan'); +const { ecsFormat } = require('@elastic/ecs-morgan-format'); + +app.use(morgan(ecsFormat(/* options */))); <1> + +// ... +app.get('/', function (req, res) { + res.send('hello, world!'); +}) +app.listen(3000); +``` + +1. Pass the ECS formatter to `morgan()`. + + + +### Step 3: Configure Filebeat [morgan-setup-step-3] + +The best way to collect the logs once they are ECS-formatted is with [Filebeat](beats://docs/reference/filebeat/filebeat-overview.md): + +:::::::{tab-set} + +::::::{tab-item} Log file +1. Follow the [Filebeat quick start](beats://docs/reference/filebeat/filebeat-installation-configuration.md) +2. Add the following configuration to your `filebeat.yaml` file. + +For Filebeat 7.16+ + +```yaml +filebeat.inputs: +- type: filestream <1> + paths: /path/to/logs.json + parsers: + - ndjson: + overwrite_keys: true <2> + add_error_key: true <3> + expand_keys: true <4> + +processors: <5> + - add_host_metadata: ~ + - add_cloud_metadata: ~ + - add_docker_metadata: ~ + - add_kubernetes_metadata: ~ +``` + +1. Use the filestream input to read lines from active log files. +2. Values from the decoded JSON object overwrite the fields that {{filebeat}} normally adds (type, source, offset, etc.) in case of conflicts. +3. {{filebeat}} adds an "error.message" and "error.type: json" key in case of JSON unmarshalling errors. +4. {{filebeat}} will recursively de-dot keys in the decoded JSON, and expand them into a hierarchical object structure. +5. Processors enhance your data. See [processors](beats://docs/reference/filebeat/filtering-enhancing-data.md) to learn more. + + +For Filebeat < 7.16 + +```yaml +filebeat.inputs: +- type: log + paths: /path/to/logs.json + json.keys_under_root: true + json.overwrite_keys: true + json.add_error_key: true + json.expand_keys: true + +processors: +- add_host_metadata: ~ +- add_cloud_metadata: ~ +- add_docker_metadata: ~ +- add_kubernetes_metadata: ~ +``` +:::::: + +::::::{tab-item} Kubernetes +1. Make sure your application logs to stdout/stderr. +2. Follow the [Run Filebeat on Kubernetes](beats://docs/reference/filebeat/running-on-kubernetes.md) guide. +3. Enable [hints-based autodiscover](beats://docs/reference/filebeat/configuration-autodiscover-hints.md) (uncomment the corresponding section in `filebeat-kubernetes.yaml`). +4. Add these annotations to your pods that log using ECS loggers. This will make sure the logs are parsed appropriately. + +```yaml +annotations: + co.elastic.logs/json.overwrite_keys: true <1> + co.elastic.logs/json.add_error_key: true <2> + co.elastic.logs/json.expand_keys: true <3> +``` + +1. Values from the decoded JSON object overwrite the fields that {{filebeat}} normally adds (type, source, offset, etc.) in case of conflicts. +2. {{filebeat}} adds an "error.message" and "error.type: json" key in case of JSON unmarshalling errors. +3. {{filebeat}} will recursively de-dot keys in the decoded JSON, and expand them into a hierarchical object structure. +:::::: + +::::::{tab-item} Docker +1. Make sure your application logs to stdout/stderr. +2. Follow the [Run Filebeat on Docker](beats://docs/reference/filebeat/running-on-docker.md) guide. +3. Enable [hints-based autodiscover](beats://docs/reference/filebeat/configuration-autodiscover-hints.md). +4. Add these labels to your containers that log using ECS loggers. This will make sure the logs are parsed appropriately. + +```yaml +labels: + co.elastic.logs/json.overwrite_keys: true <1> + co.elastic.logs/json.add_error_key: true <2> + co.elastic.logs/json.expand_keys: true <3> +``` + +1. Values from the decoded JSON object overwrite the fields that {{filebeat}} normally adds (type, source, offset, etc.) in case of conflicts. +2. {{filebeat}} adds an "error.message" and "error.type: json" key in case of JSON unmarshalling errors. +3. {{filebeat}} will recursively de-dot keys in the decoded JSON, and expand them into a hierarchical object structure. +:::::: + +::::::: +For more information, see the [Filebeat reference](beats://docs/reference/filebeat/configuring-howto-filebeat.md). + + +## Usage [morgan-usage] + +```js +const app = require('express')(); +const morgan = require('morgan'); +const { ecsFormat } = require('@elastic/ecs-morgan-format'); + +app.use(morgan(ecsFormat(/* options */))); <1> + +app.get('/', function (req, res) { + res.send('hello, world!'); +}) +app.get('/error', function (req, res, next) { + next(new Error('boom')); +}) + +app.listen(3000) +``` + +1. See available options [below](#morgan-ref). + + +Running this script (the full example is [here](https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-morgan-format/examples/express.js)) and making a request (via `curl -i localhost:3000/`) will produce log output similar to the following: + +```cmd +% node examples/express.js | jq . # piping to jq for pretty-printing +{ + "@timestamp": "2021-01-16T00:03:23.279Z", + "log.level": "info", + "message": "::1 - - [16/Jan/2021:00:03:23 +0000] \"GET / HTTP/1.1\" 200 13 \"-\" \"curl/7.64.1\"", + "ecs.version": "8.10.0", + "http": { + "version": "1.1", + "request": { + "method": "GET", + "headers": { + "host": "localhost:3000", + "accept": "*/*" + } + }, + "response": { + "status_code": 200, + "headers": { + "x-powered-by": "Express", + "content-type": "text/html; charset=utf-8", + "etag": "W/\"d-HwnTDHB9U/PRbFMN1z1wps51lqk\"" + }, + "body": { + "bytes": 13 + } + } + }, + "url": { + "path": "/", + "domain": "localhost", + "full": "http://localhost:3000/" + }, + "user_agent": { + "original": "curl/7.64.1" + } +} +``` + + +## Format options [morgan-format-options] + +You can pass any [`format` argument](https://github.com/expressjs/morgan#morganformat-options) you would normally pass to `morgan()`, and the log "message" field will use the specified format. The default is [`combined`](https://github.com/expressjs/morgan#combined). + +```js +const app = require('express')(); +const morgan = require('morgan'); +const { ecsFormat } = require('@elastic/ecs-morgan-format'); + +app.use(morgan(ecsFormat({ format: 'tiny' }))); <1> +// ... +``` + +1. If "format" is the only option you are using, you may pass it as `ecsFormat('tiny')`. + + + +## log.level [morgan-log-level] + +The `log.level` field will be "error" for response codes >= 500, otherwise "info". For example, running [examples/express.js](https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-morgan-format/examples/express.js) again, a `curl -i localhost:3000/error` will yield: + +```cmd +% node examples/express.js | jq . +{ + "@timestamp": "2021-01-18T17:52:12.810Z", + "log.level": "error", + "message": "::1 - - [18/Jan/2021:17:52:12 +0000] \"GET /error HTTP/1.1\" 500 1416 \"-\" \"curl/7.64.1\"", + "http": { + "response": { + "status_code": 500, + ... +``` + + +## Log correlation with APM [morgan-apm] + +This ECS log formatter integrates with [Elastic APM](https://www.elastic.co/apm). If your Node app is using the [Node.js Elastic APM Agent](apm-agent-nodejs://docs/reference/index.md), then a number of fields are added to log records to correlate between APM services or traces and logging data: + +* Log statements (e.g. `logger.info(...)`) called when there is a current tracing span will include [tracing fields](ecs://docs/reference/ecs-tracing.md) — `trace.id`, `transaction.id`. +* A number of service identifier fields determined by or configured on the APM agent allow cross-linking between services and logs in Kibana — `service.name`, `service.version`, `service.environment`, `service.node.name`. +* `event.dataset` enables [log rate anomaly detection](docs-content://solutions/observability/logs/inspect-log-anomalies.md) in the Elastic Observability app. + +For example, running [examples/express-with-apm.js](https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-morgan-format/examples/express-with-apm.js) and `curl -i localhost:3000/` results in a log record with the following: + +```cmd +% node examples/express-with-apm.js | jq . +{ + // The same fields as before, plus: + "service.name": "express-with-elastic-apm", + "service.version": "1.1.0", + "service.environment": "development", + "event.dataset": "express-with-elastic-apm", + "trace.id": "116d46f667a7600deed9c41fa015f7de", + "transaction.id": "b84fb72d7bf42866" +} +``` + +These IDs match trace data reported by the APM agent. + +Integration with Elastic APM can be explicitly disabled via the `apmIntegration: false` option, for example: + +```js +app.use(morgan(ecsFormat({ apmIntegration: false }))); +``` + + +## Reference [morgan-ref] + + +### `ecsFormat([options])` [morgan-ref-ecsFormat] + +* `options` `{type-object}` The following options are supported: + + * `format` `{type-string}` A format **name** (e.g. *combined*), format function (e.g. `morgan.combined`), or a format string (e.g. *:method :url :status*). This is used to format the "message" field. Defaults to `morgan.combined`. + * `convertErr` `{type-boolean}` Whether to convert a logged `err` field to ECS error fields. **Default:** `true`. + * `apmIntegration` `{type-boolean}` Whether to enable APM agent integration. **Default:** `true`. + * `serviceName` `{type-string}` A "service.name" value. If specified this overrides any value from an active APM agent. + * `serviceVersion` `{type-string}` A "service.version" value. If specified this overrides any value from an active APM agent. + * `serviceEnvironment` `{type-string}` A "service.environment" value. If specified this overrides any value from an active APM agent. + * `serviceNodeName` `{type-string}` A "service.node.name" value. If specified this overrides any value from an active APM agent. + * `eventDataset` `{type-string}` A "event.dataset" value. If specified this overrides the default of using `${serviceVersion}`. + + +Create a formatter for morgan that emits in ECS Logging format. + diff --git a/docs/reference/pino.md b/docs/reference/pino.md new file mode 100644 index 0000000..1697d72 --- /dev/null +++ b/docs/reference/pino.md @@ -0,0 +1,324 @@ +--- +mapped_pages: + - https://www.elastic.co/guide/en/ecs-logging/nodejs/current/pino.html +--- + +# ECS Logging with Pino [pino] + +This Node.js package provides a formatter for the [pino](https://getpino.io) logger, compatible with [Elastic Common Schema (ECS) logging](ecs-logging://docs/reference/intro.md). In combination with the [Filebeat](https://www.elastic.co/beats/filebeat) shipper, you can [monitor all your logs](https://www.elastic.co/log-monitoring) in one place in the Elastic Stack. `pino` 6.x, 7.x, and 8.x versions are supported. + + +## Setup [_setup] + + +### Step 1: Install [pino-setup-step-1] + +```cmd +$ npm install @elastic/ecs-pino-format +``` + + +### Step 2: Configure [pino-setup-step-2] + +```js +const { ecsFormat } = require('@elastic/ecs-pino-format'); +const pino = require('pino'); + +const log = pino(ecsFormat(/* options */)); <1> +log.info('hi'); +log.error({ err: new Error('boom') }, 'oops there is a problem'); +// ... +``` + +1. This will [configure](https://getpino.io/#/docs/api?id=options) Pino’s `formatters`, `messageKey` and `timestamp` options. + + +See usage discussion and examples below. + + +### Step 3: Configure Filebeat [pino-setup-step-3] + +The best way to collect the logs once they are ECS-formatted is with [Filebeat](beats://docs/reference/filebeat/filebeat-overview.md): + +:::::::{tab-set} + +::::::{tab-item} Log file +1. Follow the [Filebeat quick start](beats://docs/reference/filebeat/filebeat-installation-configuration.md) +2. Add the following configuration to your `filebeat.yaml` file. + +For Filebeat 7.16+ + +```yaml +filebeat.inputs: +- type: filestream <1> + paths: /path/to/logs.json + parsers: + - ndjson: + overwrite_keys: true <2> + add_error_key: true <3> + expand_keys: true <4> + +processors: <5> + - add_host_metadata: ~ + - add_cloud_metadata: ~ + - add_docker_metadata: ~ + - add_kubernetes_metadata: ~ +``` + +1. Use the filestream input to read lines from active log files. +2. Values from the decoded JSON object overwrite the fields that {{filebeat}} normally adds (type, source, offset, etc.) in case of conflicts. +3. {{filebeat}} adds an "error.message" and "error.type: json" key in case of JSON unmarshalling errors. +4. {{filebeat}} will recursively de-dot keys in the decoded JSON, and expand them into a hierarchical object structure. +5. Processors enhance your data. See [processors](beats://docs/reference/filebeat/filtering-enhancing-data.md) to learn more. + + +For Filebeat < 7.16 + +```yaml +filebeat.inputs: +- type: log + paths: /path/to/logs.json + json.keys_under_root: true + json.overwrite_keys: true + json.add_error_key: true + json.expand_keys: true + +processors: +- add_host_metadata: ~ +- add_cloud_metadata: ~ +- add_docker_metadata: ~ +- add_kubernetes_metadata: ~ +``` +:::::: + +::::::{tab-item} Kubernetes +1. Make sure your application logs to stdout/stderr. +2. Follow the [Run Filebeat on Kubernetes](beats://docs/reference/filebeat/running-on-kubernetes.md) guide. +3. Enable [hints-based autodiscover](beats://docs/reference/filebeat/configuration-autodiscover-hints.md) (uncomment the corresponding section in `filebeat-kubernetes.yaml`). +4. Add these annotations to your pods that log using ECS loggers. This will make sure the logs are parsed appropriately. + +```yaml +annotations: + co.elastic.logs/json.overwrite_keys: true <1> + co.elastic.logs/json.add_error_key: true <2> + co.elastic.logs/json.expand_keys: true <3> +``` + +1. Values from the decoded JSON object overwrite the fields that {{filebeat}} normally adds (type, source, offset, etc.) in case of conflicts. +2. {{filebeat}} adds an "error.message" and "error.type: json" key in case of JSON unmarshalling errors. +3. {{filebeat}} will recursively de-dot keys in the decoded JSON, and expand them into a hierarchical object structure. +:::::: + +::::::{tab-item} Docker +1. Make sure your application logs to stdout/stderr. +2. Follow the [Run Filebeat on Docker](beats://docs/reference/filebeat/running-on-docker.md) guide. +3. Enable [hints-based autodiscover](beats://docs/reference/filebeat/configuration-autodiscover-hints.md). +4. Add these labels to your containers that log using ECS loggers. This will make sure the logs are parsed appropriately. + +```yaml +labels: + co.elastic.logs/json.overwrite_keys: true <1> + co.elastic.logs/json.add_error_key: true <2> + co.elastic.logs/json.expand_keys: true <3> +``` + +1. Values from the decoded JSON object overwrite the fields that {{filebeat}} normally adds (type, source, offset, etc.) in case of conflicts. +2. {{filebeat}} adds an "error.message" and "error.type: json" key in case of JSON unmarshalling errors. +3. {{filebeat}} will recursively de-dot keys in the decoded JSON, and expand them into a hierarchical object structure. +:::::: + +::::::: +For more information, see the [Filebeat reference](beats://docs/reference/filebeat/configuring-howto-filebeat.md). + + +## Usage [pino-usage] + +```js +const { ecsFormat } = require('@elastic/ecs-pino-format'); +const pino = require('pino'); + +const log = pino(ecsFormat(/* options */)); <1> +log.info('Hello world'); + +const child = log.child({ module: 'foo' }); +child.warn('From child'); +``` + +1. See available options [below](#pino-ref). + + +Running this will produce log output similar to the following: + +```cmd +{"log.level":"info","@timestamp":"2023-10-14T02:07:47.901Z","process.pid":56645,"host.hostname":"pink.local","ecs.version":"8.10.0","message":"Hello world"} +{"log.level":"warn","@timestamp":"2023-10-14T02:07:47.901Z","process.pid":56645,"host.hostname":"pink.local","ecs.version":"8.10.0","module":"foo","message":"From child"} +``` + + +## Error Logging [pino-error-logging] + +By default, the formatter will convert an `err` field that is an Error instance to [ECS Error fields](ecs://docs/reference/ecs-error.md). For example: + +```js +const { ecsFormat } = require('@elastic/ecs-pino-format'); +const pino = require('pino'); +const log = pino(ecsFormat()); + +const myErr = new Error('boom'); +log.info({ err: myErr }, 'oops'); +``` + +will yield (pretty-printed for readability): + +```cmd +% node examples/error.js | jq . +{ + "log.level": "info", + "@timestamp": "2021-01-26T17:02:23.697Z", + ... + "error": { + "type": "Error", + "message": "boom", + "stack_trace": "Error: boom\n at Object. (..." + }, + "message": "oops" +} +``` + +This is analogous to and overrides [Pino’s default err serializer](https://getpino.io/#/docs/api?id=serializers-object). Special handling of the `err` field can be disabled via the `convertErr: false` option: + +```js +const log = pino(ecsFormat({ convertErr: false })); +``` + + +## HTTP Request and Response Logging [pino-http-logging] + +With the `convertReqRes: true` option, the formatter will automatically convert Node.js core [request](https://nodejs.org/api/http.md#http_class_http_incomingmessage) and [response](https://nodejs.org/api/http.md#http_class_http_serverresponse) objects when passed as the `req` and `res` fields, respectively. (This option replaces the usage of `req` and `res` [Pino serializers](https://getpino.io/#/docs/api?id=pinostdserializers-object).) + +```js +const http = require('http'); +const { ecsFormat } = require('@elastic/ecs-pino-format'); +const pino = require('pino'); + +const log = pino(ecsFormat({ convertReqRes: true })); <1> + +const server = http.createServer(function handler (req, res) { + res.setHeader('Foo', 'Bar'); + res.end('ok'); + log.info({ req, res }, 'handled request'); <2> +}); + +server.listen(3000, () => { + log.info('listening at http://localhost:3000'); +} +``` + +1. use `convertReqRes` option +2. log with `req` and/or `res` fields + + +This will produce logs with request and response info using [ECS HTTP fields](ecs://docs/reference/ecs-http.md). For example: + +```cmd +% node examples/http.js | jq . # using jq for pretty printing +... # run 'curl http://localhost:3000/' +{ + "log.level": "info", + "@timestamp": "2023-10-14T02:10:14.477Z", + "process.pid": 56697, + "host.hostname": "pink.local", + "ecs.version": "8.10.0", + "http": { + "version": "1.1", + "request": { + "method": "GET", + "headers": { + "host": "localhost:3000", + "user-agent": "curl/8.1.2", + "accept": "*/*" + } + }, + "response": { + "status_code": 200, + "headers": { + "foo": "Bar" + } + } + }, + "url": { + "full": "http://localhost:3000/", + "path": "/" + }, + "client": { + "address": "::ffff:127.0.0.1", + "ip": "::ffff:127.0.0.1", + "port": 49504 + }, + "user_agent": { + "original": "curl/8.1.2" + }, + "message": "handled request" +} +``` + +The [examples/ directory](https://github.com/elastic/ecs-logging-nodejs/tree/main/packages/ecs-pino-format/examples) shows sample programs using request and response logging: [with Express](https://github.com/elastic/ecs-logging-nodejs/tree/main/packages/ecs-pino-format/examples/express-simple.js), [with the pino-http middleware package](https://github.com/elastic/ecs-logging-nodejs/tree/main/packages/ecs-pino-format/examples/express-with-pino-http.js), etc. + + +## Log Correlation with APM [pino-apm] + +This ECS log formatter integrates with [Elastic APM](https://www.elastic.co/apm). If your Node app is using the [Node.js Elastic APM Agent](apm-agent-nodejs://docs/reference/index.md), then a number of fields are added to log records to correlate between APM services or traces and logging data: + +* Log statements (e.g. `logger.info(...)`) called when there is a current tracing span will include [tracing fields](ecs://docs/reference/ecs-tracing.md) — `trace.id`, `transaction.id`, `span.id`. +* A number of service identifier fields determined by or configured on the APM agent allow cross-linking between services and logs in Kibana — `service.name`, `service.version`, `service.environment`, `service.node.name`. +* `event.dataset` enables [log rate anomaly detection](docs-content://solutions/observability/logs/inspect-log-anomalies.md) in the Elastic Observability app. + +For example, running [examples/http-with-elastic-apm.js](https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-pino-format/examples/http-with-elastic-apm.js) and `curl -i localhost:3000/` results in a log record with the following: + +```cmd +% node examples/http-with-elastic-apm.js | jq . +... + "service.name": "http-with-elastic-apm", + "service.version": "1.4.0", + "service.environment": "development", + "event.dataset": "http-with-elastic-apm", + "trace.id": "9f338eae7211b7993b98929046aed21d", + "transaction.id": "2afbef5642cc7a3f", +... +``` + +These IDs match trace data reported by the APM agent. + +Integration with Elastic APM can be explicitly disabled via the `apmIntegration: false` option, for example: + +```js +const log = pino(ecsFormat({ apmIntegration: false })); +``` + + +## Limitations and Considerations [pino-considerations] + +The [ecs-logging spec](https://github.com/elastic/ecs-logging/tree/main/spec) suggests that the first three fields in log records must be `@timestamp`, `log.level`, and `message`. Pino does not provide a mechanism to put the `message` field near the front. Given that ordering of ecs-logging fields is for **human readability** and does not affect interoperability, this is not considered a significant concern. + +The hooks that Pino currently provides do not enable this package to convert fields passed to `.child({ ... })`. This means that, even with the `convertReqRes` option, a call to `.child({ req })` will **not** convert that `req` to ECS HTTP fields. This is a slight limitation for users of [pino-http](https://github.com/pinojs/pino-http) which does this. + + +## Reference [pino-ref] + + +### `ecsFormat([options])` [pino-ref-ecsFormat] + +* `options` `{type-object}` The following options are supported: + + * `convertErr` `{type-boolean}` Whether to convert a logged `err` field to ECS error fields. **Default:** `true`. + * `convertReqRes` `{type-boolean}` Whether to logged `req` and `res` HTTP request and response fields to ECS HTTP, User agent, and URL fields. **Default:** `false`. + * `apmIntegration` `{type-boolean}` Whether to enable APM agent integration. **Default:** `true`. + * `serviceName` `{type-string}` A "service.name" value. If specified this overrides any value from an active APM agent. + * `serviceVersion` `{type-string}` A "service.version" value. If specified this overrides any value from an active APM agent. + * `serviceEnvironment` `{type-string}` A "service.environment" value. If specified this overrides any value from an active APM agent. + * `serviceNodeName` `{type-string}` A "service.node.name" value. If specified this overrides any value from an active APM agent. + * `eventDataset` `{type-string}` A "event.dataset" value. If specified this overrides the default of using `${serviceVersion}`. + + +Create options for `pino(...)` that configures ECS Logging format output. + diff --git a/docs/reference/toc.yml b/docs/reference/toc.yml new file mode 100644 index 0000000..2d6afdd --- /dev/null +++ b/docs/reference/toc.yml @@ -0,0 +1,5 @@ +toc: + - file: index.md + - file: pino.md + - file: winston.md + - file: morgan.md \ No newline at end of file diff --git a/docs/reference/winston.md b/docs/reference/winston.md new file mode 100644 index 0000000..f006023 --- /dev/null +++ b/docs/reference/winston.md @@ -0,0 +1,397 @@ +--- +mapped_pages: + - https://www.elastic.co/guide/en/ecs-logging/nodejs/current/winston.html +--- + +# ECS Logging with Winston [winston] + +This Node.js package provides a formatter for the [winston](https://github.com/winstonjs/winston#readme) logger, compatible with [Elastic Common Schema (ECS) logging](ecs-logging://docs/reference/intro.md). In combination with the [Filebeat](https://www.elastic.co/beats/filebeat) shipper, you can [monitor all your logs](https://www.elastic.co/log-monitoring) in one place in the Elastic Stack. `winston` 3.x versions >=3.3.3 are supported. + + +## Setup [_setup_2] + + +### Step 1: Install [winston-setup-step-1] + +```cmd +$ npm install @elastic/ecs-winston-format +``` + + +### Step 2: Configure [winston-setup-step-2] + +```js +const winston = require('winston'); +const { ecsFormat } = require('@elastic/ecs-winston-format'); + +const logger = winston.createLogger({ + format: ecsFormat(/* options */), <1> + transports: [ + new winston.transports.Console() + ] +}); + +logger.info('hi'); +logger.error('oops there is a problem', { err: new Error('boom') }); +``` + +1. Pass the ECS formatter to winston here. + + + +### Step 3: Configure Filebeat [winston-setup-step-3] + +The best way to collect the logs once they are ECS-formatted is with [Filebeat](beats://docs/reference/filebeat/filebeat-overview.md): + +:::::::{tab-set} + +::::::{tab-item} Log file +1. Follow the [Filebeat quick start](beats://docs/reference/filebeat/filebeat-installation-configuration.md) +2. Add the following configuration to your `filebeat.yaml` file. + +For Filebeat 7.16+ + +```yaml +filebeat.inputs: +- type: filestream <1> + paths: /path/to/logs.json + parsers: + - ndjson: + overwrite_keys: true <2> + add_error_key: true <3> + expand_keys: true <4> + +processors: <5> + - add_host_metadata: ~ + - add_cloud_metadata: ~ + - add_docker_metadata: ~ + - add_kubernetes_metadata: ~ +``` + +1. Use the filestream input to read lines from active log files. +2. Values from the decoded JSON object overwrite the fields that {{filebeat}} normally adds (type, source, offset, etc.) in case of conflicts. +3. {{filebeat}} adds an "error.message" and "error.type: json" key in case of JSON unmarshalling errors. +4. {{filebeat}} will recursively de-dot keys in the decoded JSON, and expand them into a hierarchical object structure. +5. Processors enhance your data. See [processors](beats://docs/reference/filebeat/filtering-enhancing-data.md) to learn more. + + +For Filebeat < 7.16 + +```yaml +filebeat.inputs: +- type: log + paths: /path/to/logs.json + json.keys_under_root: true + json.overwrite_keys: true + json.add_error_key: true + json.expand_keys: true + +processors: +- add_host_metadata: ~ +- add_cloud_metadata: ~ +- add_docker_metadata: ~ +- add_kubernetes_metadata: ~ +``` +:::::: + +::::::{tab-item} Kubernetes +1. Make sure your application logs to stdout/stderr. +2. Follow the [Run Filebeat on Kubernetes](beats://docs/reference/filebeat/running-on-kubernetes.md) guide. +3. Enable [hints-based autodiscover](beats://docs/reference/filebeat/configuration-autodiscover-hints.md) (uncomment the corresponding section in `filebeat-kubernetes.yaml`). +4. Add these annotations to your pods that log using ECS loggers. This will make sure the logs are parsed appropriately. + +```yaml +annotations: + co.elastic.logs/json.overwrite_keys: true <1> + co.elastic.logs/json.add_error_key: true <2> + co.elastic.logs/json.expand_keys: true <3> +``` + +1. Values from the decoded JSON object overwrite the fields that {{filebeat}} normally adds (type, source, offset, etc.) in case of conflicts. +2. {{filebeat}} adds an "error.message" and "error.type: json" key in case of JSON unmarshalling errors. +3. {{filebeat}} will recursively de-dot keys in the decoded JSON, and expand them into a hierarchical object structure. +:::::: + +::::::{tab-item} Docker +1. Make sure your application logs to stdout/stderr. +2. Follow the [Run Filebeat on Docker](beats://docs/reference/filebeat/running-on-docker.md) guide. +3. Enable [hints-based autodiscover](beats://docs/reference/filebeat/configuration-autodiscover-hints.md). +4. Add these labels to your containers that log using ECS loggers. This will make sure the logs are parsed appropriately. + +```yaml +labels: + co.elastic.logs/json.overwrite_keys: true <1> + co.elastic.logs/json.add_error_key: true <2> + co.elastic.logs/json.expand_keys: true <3> +``` + +1. Values from the decoded JSON object overwrite the fields that {{filebeat}} normally adds (type, source, offset, etc.) in case of conflicts. +2. {{filebeat}} adds an "error.message" and "error.type: json" key in case of JSON unmarshalling errors. +3. {{filebeat}} will recursively de-dot keys in the decoded JSON, and expand them into a hierarchical object structure. +:::::: + +::::::: +For more information, see the [Filebeat reference](beats://docs/reference/filebeat/configuring-howto-filebeat.md). + +::::{note} +You might like to try out our tutorial using Node.js ECS logging with winston: [Ingest logs from a Node.js web application using Filebeat](docs-content://manage-data/ingest/ingesting-data-from-applications/ingest-logs-from-nodejs-web-application-using-filebeat.md). +:::: + + + +## Usage [winston-usage] + +```js +const winston = require('winston'); +const { ecsFormat } = require('@elastic/ecs-winston-format'); + +const logger = winston.createLogger({ + level: 'info', + format: ecsFormat(/* options */), <1> + transports: [ + new winston.transports.Console() + ] +}); + +logger.info('hi'); +logger.error('oops there is a problem', { foo: 'bar' }); +``` + +1. See available options [below](#winston-ref). + + +Running this script (available [here](https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-winston-format/examples/basic.js)) will produce log output similar to the following: + +```cmd +% node examples/basic.js +{"@timestamp":"2023-10-14T02:14:17.302Z","log.level":"info","message":"hi","ecs.version":"8.10.0"} +{"@timestamp":"2023-10-14T02:14:17.304Z","log.level":"error","message":"oops there is a problem","ecs.version":"8.10.0","foo":"bar"} +``` + +The formatter handles serialization to JSON, so you don’t need to add the [json](https://github.com/winstonjs/logform#json) formatter. As well, a timestamp is automatically generated by the formatter, so you don’t need to add the [timestamp](https://github.com/winstonjs/logform#timestamp) formatter. + + +## Error logging [winston-error-logging] + +By default, the formatter will convert an `err` meta field that is an Error instance to [ECS Error fields](ecs://docs/reference/ecs-error.md). For [example](https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-winston-format/examples/error.js): + +```js +const winston = require('winston'); +const { ecsFormat } = require('@elastic/ecs-winston-format'); +const logger = winston.createLogger({ + format: ecsFormat(), + transports: [ + new winston.transports.Console() + ] +}); + +const myErr = new Error('boom'); +logger.info('oops', { err: myErr }); +``` + +will yield (pretty-printed for readability): + +```cmd +% node examples/error.js | jq . +{ + "@timestamp": "2021-01-26T17:25:07.983Z", + "log.level": "info", + "message": "oops", + "error": { + "type": "Error", + "message": "boom", + "stack_trace": "Error: boom\n at Object. (..." + }, + "ecs.version": "8.10.0" +} +``` + +Special handling of the `err` meta field can be disabled via the `convertErr: false` option: + +```js +... +const logger = winston.createLogger({ + format: ecsFormat({ convertErr: false }), +... +``` + + +## HTTP Request and Response Logging [winston-http-logging] + +With the `convertReqRes: true` option, the formatter will automatically convert Node.js core [request](https://nodejs.org/api/http.md#http_class_http_incomingmessage) and [response](https://nodejs.org/api/http.md#http_class_http_serverresponse) objects when passed as the `req` and `res` meta fields, respectively. + +```js +const http = require('http'); +const winston = require('winston'); +const { ecsFormat } = require('@elastic/ecs-winston-format'); + +const logger = winston.createLogger({ + level: 'info', + format: ecsFormat({ convertReqRes: true }), <1> + transports: [ + new winston.transports.Console() + ] +}); + +const server = http.createServer(handler); +server.listen(3000, () => { + logger.info('listening at http://localhost:3000') +}); + +function handler (req, res) { + res.setHeader('Foo', 'Bar'); + res.end('ok'); + logger.info('handled request', { req, res }); <2> +} +``` + +1. use `convertReqRes` option +2. log `req` and/or `res` meta fields + + +This will produce logs with request and response info using [ECS HTTP fields](ecs://docs/reference/ecs-http.md). For [example](https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-winston-format/examples/http.js): + +```cmd +% node examples/http.js | jq . # using jq for pretty printing +... # run 'curl http://localhost:3000/' +{ + "@timestamp": "2023-10-14T02:15:54.768Z", + "log.level": "info", + "message": "handled request", + "http": { + "version": "1.1", + "request": { + "method": "GET", + "headers": { + "host": "localhost:3000", + "user-agent": "curl/8.1.2", + "accept": "*/*" + } + }, + "response": { + "status_code": 200, + "headers": { + "foo": "Bar" + } + } + }, + "url": { + "path": "/", + "full": "http://localhost:3000/" + }, + "client": { + "address": "::ffff:127.0.0.1", + "ip": "::ffff:127.0.0.1", + "port": 49538 + }, + "user_agent": { + "original": "curl/8.1.2" + }, + "ecs.version": "8.10.0" +} +``` + + +## Log Correlation with APM [winston-apm] + +This ECS log formatter integrates with [Elastic APM](https://www.elastic.co/apm). If your Node app is using the [Node.js Elastic APM Agent](apm-agent-nodejs://docs/reference/index.md), then a number of fields are added to log records to correlate between APM services or traces and logging data: + +* Log statements (e.g. `logger.info(...)`) called when there is a current tracing span will include [tracing fields](ecs://docs/reference/ecs-tracing.md) — `trace.id`, `transaction.id`, `span.id`. +* A number of service identifier fields determined by or configured on the APM agent allow cross-linking between services and logs in Kibana — `service.name`, `service.version`, `service.environment`, `service.node.name`. +* `event.dataset` enables [log rate anomaly detection](docs-content://solutions/observability/logs/inspect-log-anomalies.md) in the Elastic Observability app. + +For example, running [examples/http-with-elastic-apm.js](https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-winston-format/examples/http-with-elastic-apm.js) and `curl -i localhost:3000/` results in a log record with the following: + +```cmd +% node examples/http-with-elastic-apm.js | jq . +... + "service.name": "http-with-elastic-apm", + "service.version": "1.4.0", + "service.environment": "development", + "event.dataset": "http-with-elastic-apm" + "trace.id": "7fd75f0f33ff49aba85d060b46dcad7e", + "transaction.id": "6c97c7c1b468fa05" +} +``` + +These IDs match trace data reported by the APM agent. + +Integration with Elastic APM can be explicitly disabled via the `apmIntegration: false` option, for example: + +```js +const logger = winston.createLogger({ + format: ecsFormat({ apmIntegration: false }), + // ... +}) +``` + + +## Limitations and Considerations [winston-limitations] + +The [ecs-logging spec](https://github.com/elastic/ecs-logging/tree/main/spec) suggests that the first three fields in log records should be `@timestamp`, `log.level`, and `message`. As of version 1.5.0, this formatter does **not** follow this suggestion. It would be possible but would require creating a new Object in `ecsFields` for each log record. Given that ordering of ecs-logging fields is for **human readability** and does not affect interoperability, the decision was made to prefer performance. + + +## Reference [winston-ref] + + +### `ecsFormat([options])` [winston-ref-ecsFormat] + +* `options` `{type-object}` The following options are supported: + + * `convertErr` `{type-boolean}` Whether to convert a logged `err` field to ECS error fields. **Default:** `true`. + * `convertReqRes` `{type-boolean}` Whether to logged `req` and `res` HTTP request and response fields to ECS HTTP, User agent, and URL fields. **Default:** `false`. + * `apmIntegration` `{type-boolean}` Whether to enable APM agent integration. **Default:** `true`. + * `serviceName` `{type-string}` A "service.name" value. If specified this overrides any value from an active APM agent. + * `serviceVersion` `{type-string}` A "service.version" value. If specified this overrides any value from an active APM agent. + * `serviceEnvironment` `{type-string}` A "service.environment" value. If specified this overrides any value from an active APM agent. + * `serviceNodeName` `{type-string}` A "service.node.name" value. If specified this overrides any value from an active APM agent. + * `eventDataset` `{type-string}` A "event.dataset" value. If specified this overrides the default of using `${serviceVersion}`. + + +Create a formatter for winston that emits in ECS Logging format. This is a single format that handles both [`ecsFields([options])`](#winston-ref-ecsFields) and [`ecsStringify([options])`](#winston-ref-ecsStringify). The following two are equivalent: + +```js +const { ecsFormat, ecsFields, ecsStringify } = require('@elastic/ecs-winston-format'); +const winston = require('winston'); + +const logger = winston.createLogger({ + format: ecsFormat(/* options */), + // ... +}); + +const logger = winston.createLogger({ + format: winston.format.combine( + ecsFields(/* options */), + ecsStringify() + ), + // ... +}); +``` + + +### `ecsFields([options])` [winston-ref-ecsFields] + +* `options` `{type-object}` The following options are supported: + + * `convertErr` `{type-boolean}` Whether to convert a logged `err` field to ECS error fields. **Default:** `true`. + * `convertReqRes` `{type-boolean}` Whether to logged `req` and `res` HTTP request and response fields to ECS HTTP, User agent, and URL fields. **Default:** `false`. + * `apmIntegration` `{type-boolean}` Whether to enable APM agent integration. **Default:** `true`. + * `serviceName` `{type-string}` A "service.name" value. If specified this overrides any value from an active APM agent. + * `serviceVersion` `{type-string}` A "service.version" value. If specified this overrides any value from an active APM agent. + * `serviceEnvironment` `{type-string}` A "service.environment" value. If specified this overrides any value from an active APM agent. + * `serviceNodeName` `{type-string}` A "service.node.name" value. If specified this overrides any value from an active APM agent. + * `eventDataset` `{type-string}` A "event.dataset" value. If specified this overrides the default of using `${serviceVersion}`. + + +Create a formatter for winston that converts fields on the log record info object to ECS Logging format. + + +### `ecsStringify([options])` [winston-ref-ecsStringify] + +Create a formatter for winston that stringifies/serializes the log record to JSON. + +This is similar to `logform.json()`. They both use the `safe-stable-stringify` package to produce the JSON. Some differences: + +* This stringifier skips serializing the `level` field, because it is not an ECS field. +* Winston provides a `replacer` that converts bigints to strings The argument **for** doing so is that a **JavaScript** JSON parser looses precision when parsing a bigint. The argument against is that a BigInt changes type to a string rather than a number. For now this stringifier does not convert BitInts to strings. + diff --git a/docs/winston.asciidoc b/docs/winston.asciidoc deleted file mode 100644 index 9a22108..0000000 --- a/docs/winston.asciidoc +++ /dev/null @@ -1,360 +0,0 @@ -[[winston]] -== ECS Logging with Winston - -This Node.js package provides a formatter for the https://github.com/winstonjs/winston#readme[winston] -logger, compatible with {ecs-logging-ref}/intro.html[Elastic Common Schema (ECS) logging]. -In combination with the https://www.elastic.co/beats/filebeat[Filebeat] shipper, -you can https://www.elastic.co/log-monitoring[monitor all your logs] in one -place in the Elastic Stack. `winston` 3.x versions >=3.3.3 are supported. - - -[float] -=== Setup - -[float] -[[winston-setup-step-1]] -==== Step 1: Install - -[source,cmd] ----- -$ npm install @elastic/ecs-winston-format ----- - -[float] -[[winston-setup-step-2]] -==== Step 2: Configure - -[source,js] ----- -const winston = require('winston'); -const { ecsFormat } = require('@elastic/ecs-winston-format'); - -const logger = winston.createLogger({ - format: ecsFormat(/* options */), <1> - transports: [ - new winston.transports.Console() - ] -}); - -logger.info('hi'); -logger.error('oops there is a problem', { err: new Error('boom') }); ----- -<1> Pass the ECS formatter to winston here. - - -[float] -[[winston-setup-step-3]] -==== Step 3: Configure Filebeat - -The best way to collect the logs once they are ECS-formatted is with {filebeat-ref}[Filebeat]: - -include::{ecs-repo-dir}/setup.asciidoc[tag=configure-filebeat] - -NOTE: You might like to try out our tutorial using Node.js ECS logging with winston: {cloud}/ec-getting-started-search-use-cases-node-logs.html[Ingest logs from a Node.js web application using Filebeat]. - -[float] -[[winston-usage]] -=== Usage - -[source,js] ----- -const winston = require('winston'); -const { ecsFormat } = require('@elastic/ecs-winston-format'); - -const logger = winston.createLogger({ - level: 'info', - format: ecsFormat(/* options */), <1> - transports: [ - new winston.transports.Console() - ] -}); - -logger.info('hi'); -logger.error('oops there is a problem', { foo: 'bar' }); ----- -<1> See available options <>. - -Running this script (available https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-winston-format/examples/basic.js[here]) will produce log output similar to the following: - -[source,cmd] ----- -% node examples/basic.js -{"@timestamp":"2023-10-14T02:14:17.302Z","log.level":"info","message":"hi","ecs.version":"8.10.0"} -{"@timestamp":"2023-10-14T02:14:17.304Z","log.level":"error","message":"oops there is a problem","ecs.version":"8.10.0","foo":"bar"} ----- - -The formatter handles serialization to JSON, so you don't need to add the -https://github.com/winstonjs/logform#json[json] formatter. As well, a -timestamp is automatically generated by the formatter, so you don't need to add -the https://github.com/winstonjs/logform#timestamp[timestamp] formatter. - - -[float] -[[winston-error-logging]] -=== Error logging - -By default, the formatter will convert an `err` meta field that is an Error instance -to {ecs-ref}/ecs-error.html[ECS Error fields]. -For https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-winston-format/examples/error.js[example]: - -[source,js] ----- -const winston = require('winston'); -const { ecsFormat } = require('@elastic/ecs-winston-format'); -const logger = winston.createLogger({ - format: ecsFormat(), <1> - transports: [ - new winston.transports.Console() - ] -}); - -const myErr = new Error('boom'); -logger.info('oops', { err: myErr }); <2> ----- - -will yield (pretty-printed for readability): - -[source,cmd] ----- -% node examples/error.js | jq . -{ - "@timestamp": "2021-01-26T17:25:07.983Z", - "log.level": "info", - "message": "oops", - "error": { - "type": "Error", - "message": "boom", - "stack_trace": "Error: boom\n at Object. (..." - }, - "ecs.version": "8.10.0" -} ----- - -Special handling of the `err` meta field can be disabled via the `convertErr: -false` option: - -[source,js] ----- -... -const logger = winston.createLogger({ - format: ecsFormat({ convertErr: false }), -... ----- - - -[float] -[[winston-http-logging]] -=== HTTP Request and Response Logging - -With the `convertReqRes: true` option, the formatter will automatically -convert Node.js core https://nodejs.org/api/http.html#http_class_http_incomingmessage[request] -and https://nodejs.org/api/http.html#http_class_http_serverresponse[response] -objects when passed as the `req` and `res` meta fields, respectively. - -[source,js] ----- -const http = require('http'); -const winston = require('winston'); -const { ecsFormat } = require('@elastic/ecs-winston-format'); - -const logger = winston.createLogger({ - level: 'info', - format: ecsFormat({ convertReqRes: true }), <1> - transports: [ - new winston.transports.Console() - ] -}); - -const server = http.createServer(handler); -server.listen(3000, () => { - logger.info('listening at http://localhost:3000') -}); - -function handler (req, res) { - res.setHeader('Foo', 'Bar'); - res.end('ok'); - logger.info('handled request', { req, res }); <2> -} ----- -<1> use `convertReqRes` option -<2> log `req` and/or `res` meta fields - -This will produce logs with request and response info using -{ecs-ref}/ecs-http.html[ECS HTTP fields]. -For https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-winston-format/examples/http.js[example]: - -[source,cmd] ----- -% node examples/http.js | jq . # using jq for pretty printing -... # run 'curl http://localhost:3000/' -{ - "@timestamp": "2023-10-14T02:15:54.768Z", - "log.level": "info", - "message": "handled request", - "http": { - "version": "1.1", - "request": { - "method": "GET", - "headers": { - "host": "localhost:3000", - "user-agent": "curl/8.1.2", - "accept": "*/*" - } - }, - "response": { - "status_code": 200, - "headers": { - "foo": "Bar" - } - } - }, - "url": { - "path": "/", - "full": "http://localhost:3000/" - }, - "client": { - "address": "::ffff:127.0.0.1", - "ip": "::ffff:127.0.0.1", - "port": 49538 - }, - "user_agent": { - "original": "curl/8.1.2" - }, - "ecs.version": "8.10.0" -} ----- - - -[float] -[[winston-apm]] -=== Log Correlation with APM - -This ECS log formatter integrates with https://www.elastic.co/apm[Elastic APM]. -If your Node app is using the {apm-node-ref}/intro.html[Node.js Elastic APM Agent], -then a number of fields are added to log records to correlate between APM -services or traces and logging data: - -- Log statements (e.g. `logger.info(...)`) called when there is a current - tracing span will include {ecs-ref}/ecs-tracing.html[tracing fields] -- - `trace.id`, `transaction.id`, `span.id`. -- A number of service identifier fields determined by or configured on the APM - agent allow cross-linking between services and logs in Kibana -- - `service.name`, `service.version`, `service.environment`, `service.node.name`. -- `event.dataset` enables {observability-guide}/inspect-log-anomalies.html[log - rate anomaly detection] in the Elastic Observability app. - -For example, running https://github.com/elastic/ecs-logging-nodejs/blob/main/packages/ecs-winston-format/examples/http-with-elastic-apm.js[examples/http-with-elastic-apm.js] and `curl -i localhost:3000/` results in a log record with the following: - -[source,cmd] ----- -% node examples/http-with-elastic-apm.js | jq . -... - "service.name": "http-with-elastic-apm", - "service.version": "1.4.0", - "service.environment": "development", - "event.dataset": "http-with-elastic-apm" - "trace.id": "7fd75f0f33ff49aba85d060b46dcad7e", - "transaction.id": "6c97c7c1b468fa05" -} ----- - -These IDs match trace data reported by the APM agent. - -Integration with Elastic APM can be explicitly disabled via the -`apmIntegration: false` option, for example: - -[source,js] ----- -const logger = winston.createLogger({ - format: ecsFormat({ apmIntegration: false }), - // ... -}) ----- - -[float] -[[winston-limitations]] -=== Limitations and Considerations - -The https://github.com/elastic/ecs-logging/tree/main/spec[ecs-logging spec] -suggests that the first three fields in log records should be `@timestamp`, -`log.level`, and `message`. As of version 1.5.0, this formatter does *not* -follow this suggestion. It would be possible but would require creating a new -Object in `ecsFields` for each log record. Given that ordering of ecs-logging -fields is for *human readability* and does not affect interoperability, the -decision was made to prefer performance. - -[float] -[[winston-ref]] -=== Reference - -[float] -[[winston-ref-ecsFormat]] -==== `ecsFormat([options])` - -* `options` +{type-object}+ The following options are supported: -** `convertErr` +{type-boolean}+ Whether to convert a logged `err` field to ECS error fields. *Default:* `true`. -** `convertReqRes` +{type-boolean}+ Whether to logged `req` and `res` HTTP request and response fields to ECS HTTP, User agent, and URL fields. *Default:* `false`. -** `apmIntegration` +{type-boolean}+ Whether to enable APM agent integration. *Default:* `true`. -** `serviceName` +{type-string}+ A "service.name" value. If specified this overrides any value from an active APM agent. -** `serviceVersion` +{type-string}+ A "service.version" value. If specified this overrides any value from an active APM agent. -** `serviceEnvironment` +{type-string}+ A "service.environment" value. If specified this overrides any value from an active APM agent. -** `serviceNodeName` +{type-string}+ A "service.node.name" value. If specified this overrides any value from an active APM agent. -** `eventDataset` +{type-string}+ A "event.dataset" value. If specified this overrides the default of using `${serviceVersion}`. - -Create a formatter for winston that emits in ECS Logging format. This is a -single format that handles both <> and <>. -The following two are equivalent: - -[source,js] ----- -const { ecsFormat, ecsFields, ecsStringify } = require('@elastic/ecs-winston-format'); -const winston = require('winston'); - -const logger = winston.createLogger({ - format: ecsFormat(/* options */), - // ... -}); - -const logger = winston.createLogger({ - format: winston.format.combine( - ecsFields(/* options */), - ecsStringify() - ), - // ... -}); ----- - -[float] -[[winston-ref-ecsFields]] -==== `ecsFields([options])` - -* `options` +{type-object}+ The following options are supported: -** `convertErr` +{type-boolean}+ Whether to convert a logged `err` field to ECS error fields. *Default:* `true`. -** `convertReqRes` +{type-boolean}+ Whether to logged `req` and `res` HTTP request and response fields to ECS HTTP, User agent, and URL fields. *Default:* `false`. -** `apmIntegration` +{type-boolean}+ Whether to enable APM agent integration. *Default:* `true`. -** `serviceName` +{type-string}+ A "service.name" value. If specified this overrides any value from an active APM agent. -** `serviceVersion` +{type-string}+ A "service.version" value. If specified this overrides any value from an active APM agent. -** `serviceEnvironment` +{type-string}+ A "service.environment" value. If specified this overrides any value from an active APM agent. -** `serviceNodeName` +{type-string}+ A "service.node.name" value. If specified this overrides any value from an active APM agent. -** `eventDataset` +{type-string}+ A "event.dataset" value. If specified this overrides the default of using `${serviceVersion}`. - -Create a formatter for winston that converts fields on the log record info -object to ECS Logging format. - -[float] -[[winston-ref-ecsStringify]] -==== `ecsStringify([options])` - -Create a formatter for winston that stringifies/serializes the log record to -JSON. - -This is similar to `logform.json()`. They both use the `safe-stable-stringify` -package to produce the JSON. Some differences: - -* This stringifier skips serializing the `level` field, because it is not - an ECS field. -* Winston provides a `replacer` that converts bigints to strings The argument - *for* doing so is that a *JavaScript* JSON parser looses precision when - parsing a bigint. The argument against is that a BigInt changes type to a - string rather than a number. For now this stringifier does not convert - BitInts to strings.